diff --git a/README.md b/README.md index 12d2d395e6614936bc00a3a2f7c880ff0b0d7650..487fba3700273017a55a062e528ace14aa6fdfe0 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,3 @@ -

@@ -9,7 +8,9 @@ 开 箱 即 用 的 Spring 快 速 开 发 平 台 - [预 览](http://boot.pearadmin.com) | [官 网](http://www.pearadmin.com/) | [群聊](https://jq.qq.com/?_wv=1027&k=5OdSmve) | [社区](http://forum.pearadmin.com/) | [更新](http://forum.pearadmin.com/posts/fb16cb02ba2347a6ac236c434e07f8e1/detail) +[预 览](http://boot.pearadmin.com) | [官 网](http://www.pearadmin.com/) +| [群聊](https://jq.qq.com/?_wv=1027&k=5OdSmve) | [社区](http://forum.pearadmin.com/) +| [更新](http://forum.pearadmin.com/posts/fb16cb02ba2347a6ac236c434e07f8e1/detail)

@@ -28,12 +29,11 @@ - -#### 项目介绍 :jack_o_lantern: +#### 项目介绍 :jack_o_lantern: Spring Boot + Security + MyBatis + Thymeleaf + Activiti 快速开发平台 - 项目不定时更新,建议 Star watch 一份 +项目不定时更新,建议 Star watch 一份 #### 模块划分 @@ -45,13 +45,13 @@ Spring Boot + Security + MyBatis + Thymeleaf + Activiti 快速开发平台 #### 内置功能 -1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置。 -2. 权限管理:配置系统菜单,操作权限,按钮权限标识等。 -3. 角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。 -4. 字典管理:对系统中经常使用的一些较为固定的数据进行维护。 -5. 参数管理:对系统动态配置常用参数。 -6. 通知公告:系统通知公告信息发布维护。 -7. 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。 +1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置。 +2. 权限管理:配置系统菜单,操作权限,按钮权限标识等。 +3. 角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。 +4. 字典管理:对系统中经常使用的一些较为固定的数据进行维护。 +5. 参数管理:对系统动态配置常用参数。 +6. 通知公告:系统通知公告信息发布维护。 +7. 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。 8. 登录日志:系统登录日志记录查询包含登录异常。 9. 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。 10. 代码生成:前后端代码的生成(java、html、xml、sql)支持CRUD下载 。 diff --git a/annex/schedule.sql b/annex/schedule.sql index 6b9d65fccc51d4d5641ac8c9964250a8e2b924a6..461273f484ccb60cafff2d641a0921f67d4dcfb1 100644 --- a/annex/schedule.sql +++ b/annex/schedule.sql @@ -15,20 +15,22 @@ */ SET NAMES utf8mb4; -SET FOREIGN_KEY_CHECKS = 0; +SET +FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for schedule_blob_triggers -- ---------------------------- DROP TABLE IF EXISTS `schedule_blob_triggers`; -CREATE TABLE `schedule_blob_triggers` ( - `SCHED_NAME` varchar(120) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - `TRIGGER_NAME` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - `TRIGGER_GROUP` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - `BLOB_DATA` blob NULL, - PRIMARY KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE, - INDEX `SCHED_NAME`(`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE, - CONSTRAINT `schedule_blob_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `schedule_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) ON DELETE RESTRICT ON UPDATE RESTRICT +CREATE TABLE `schedule_blob_triggers` +( + `SCHED_NAME` varchar(120) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `TRIGGER_NAME` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `TRIGGER_GROUP` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `BLOB_DATA` blob NULL, + PRIMARY KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE, + INDEX `SCHED_NAME`(`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE, + CONSTRAINT `schedule_blob_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `schedule_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) ON DELETE RESTRICT ON UPDATE RESTRICT ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC; -- ---------------------------- @@ -39,11 +41,12 @@ CREATE TABLE `schedule_blob_triggers` ( -- Table structure for schedule_calendars -- ---------------------------- DROP TABLE IF EXISTS `schedule_calendars`; -CREATE TABLE `schedule_calendars` ( - `SCHED_NAME` varchar(120) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - `CALENDAR_NAME` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - `CALENDAR` blob NOT NULL, - PRIMARY KEY (`SCHED_NAME`, `CALENDAR_NAME`) USING BTREE +CREATE TABLE `schedule_calendars` +( + `SCHED_NAME` varchar(120) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `CALENDAR_NAME` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `CALENDAR` blob NOT NULL, + PRIMARY KEY (`SCHED_NAME`, `CALENDAR_NAME`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC; -- ---------------------------- @@ -54,14 +57,15 @@ CREATE TABLE `schedule_calendars` ( -- Table structure for schedule_cron_triggers -- ---------------------------- DROP TABLE IF EXISTS `schedule_cron_triggers`; -CREATE TABLE `schedule_cron_triggers` ( - `SCHED_NAME` varchar(120) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - `TRIGGER_NAME` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - `TRIGGER_GROUP` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - `CRON_EXPRESSION` varchar(120) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - `TIME_ZONE_ID` varchar(80) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, - PRIMARY KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE, - CONSTRAINT `schedule_cron_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `schedule_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) ON DELETE RESTRICT ON UPDATE RESTRICT +CREATE TABLE `schedule_cron_triggers` +( + `SCHED_NAME` varchar(120) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `TRIGGER_NAME` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `TRIGGER_GROUP` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `CRON_EXPRESSION` varchar(120) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `TIME_ZONE_ID` varchar(80) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + PRIMARY KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE, + CONSTRAINT `schedule_cron_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `schedule_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) ON DELETE RESTRICT ON UPDATE RESTRICT ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC; -- ---------------------------- @@ -72,27 +76,28 @@ CREATE TABLE `schedule_cron_triggers` ( -- Table structure for schedule_fired_triggers -- ---------------------------- DROP TABLE IF EXISTS `schedule_fired_triggers`; -CREATE TABLE `schedule_fired_triggers` ( - `SCHED_NAME` varchar(120) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - `ENTRY_ID` varchar(95) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - `TRIGGER_NAME` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - `TRIGGER_GROUP` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - `INSTANCE_NAME` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - `FIRED_TIME` bigint(20) NOT NULL, - `SCHED_TIME` bigint(20) NOT NULL, - `PRIORITY` int(11) NOT NULL, - `STATE` varchar(16) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - `JOB_NAME` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, - `JOB_GROUP` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, - `IS_NONCONCURRENT` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, - `REQUESTS_RECOVERY` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, - PRIMARY KEY (`SCHED_NAME`, `ENTRY_ID`) USING BTREE, - INDEX `IDX_QRTZ_FT_TRIG_INST_NAME`(`SCHED_NAME`, `INSTANCE_NAME`) USING BTREE, - INDEX `IDX_QRTZ_FT_INST_JOB_REQ_RCVRY`(`SCHED_NAME`, `INSTANCE_NAME`, `REQUESTS_RECOVERY`) USING BTREE, - INDEX `IDX_QRTZ_FT_J_G`(`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) USING BTREE, - INDEX `IDX_QRTZ_FT_JG`(`SCHED_NAME`, `JOB_GROUP`) USING BTREE, - INDEX `IDX_QRTZ_FT_T_G`(`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE, - INDEX `IDX_QRTZ_FT_TG`(`SCHED_NAME`, `TRIGGER_GROUP`) USING BTREE +CREATE TABLE `schedule_fired_triggers` +( + `SCHED_NAME` varchar(120) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `ENTRY_ID` varchar(95) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `TRIGGER_NAME` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `TRIGGER_GROUP` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `INSTANCE_NAME` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `FIRED_TIME` bigint(20) NOT NULL, + `SCHED_TIME` bigint(20) NOT NULL, + `PRIORITY` int(11) NOT NULL, + `STATE` varchar(16) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `JOB_NAME` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `JOB_GROUP` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `IS_NONCONCURRENT` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `REQUESTS_RECOVERY` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + PRIMARY KEY (`SCHED_NAME`, `ENTRY_ID`) USING BTREE, + INDEX `IDX_QRTZ_FT_TRIG_INST_NAME`(`SCHED_NAME`, `INSTANCE_NAME`) USING BTREE, + INDEX `IDX_QRTZ_FT_INST_JOB_REQ_RCVRY`(`SCHED_NAME`, `INSTANCE_NAME`, `REQUESTS_RECOVERY`) USING BTREE, + INDEX `IDX_QRTZ_FT_J_G`(`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) USING BTREE, + INDEX `IDX_QRTZ_FT_JG`(`SCHED_NAME`, `JOB_GROUP`) USING BTREE, + INDEX `IDX_QRTZ_FT_T_G`(`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE, + INDEX `IDX_QRTZ_FT_TG`(`SCHED_NAME`, `TRIGGER_GROUP`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC; -- ---------------------------- @@ -103,16 +108,17 @@ CREATE TABLE `schedule_fired_triggers` ( -- Table structure for schedule_job -- ---------------------------- DROP TABLE IF EXISTS `schedule_job`; -CREATE TABLE `schedule_job` ( - `job_id` char(19) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '任务id', - `bean_name` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'spring bean名称', - `params` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '参数', - `cron_expression` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'cron表达式', - `status` tinyint(4) NULL DEFAULT NULL COMMENT '任务状态 0:正常 1:暂停', - `remark` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注', - `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', - `job_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, - PRIMARY KEY (`job_id`) USING BTREE +CREATE TABLE `schedule_job` +( + `job_id` char(19) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '任务id', + `bean_name` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'spring bean名称', + `params` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '参数', + `cron_expression` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'cron表达式', + `status` tinyint(4) NULL DEFAULT NULL COMMENT '任务状态 0:正常 1:暂停', + `remark` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '备注', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + `job_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + PRIMARY KEY (`job_id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '定时任务' ROW_FORMAT = DYNAMIC; -- ---------------------------- @@ -123,20 +129,21 @@ CREATE TABLE `schedule_job` ( -- Table structure for schedule_job_details -- ---------------------------- DROP TABLE IF EXISTS `schedule_job_details`; -CREATE TABLE `schedule_job_details` ( - `SCHED_NAME` varchar(120) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - `JOB_NAME` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - `JOB_GROUP` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - `DESCRIPTION` varchar(250) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, - `JOB_CLASS_NAME` varchar(250) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - `IS_DURABLE` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - `IS_NONCONCURRENT` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - `IS_UPDATE_DATA` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - `REQUESTS_RECOVERY` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - `JOB_DATA` blob NULL, - PRIMARY KEY (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) USING BTREE, - INDEX `IDX_QRTZ_J_REQ_RECOVERY`(`SCHED_NAME`, `REQUESTS_RECOVERY`) USING BTREE, - INDEX `IDX_QRTZ_J_GRP`(`SCHED_NAME`, `JOB_GROUP`) USING BTREE +CREATE TABLE `schedule_job_details` +( + `SCHED_NAME` varchar(120) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `JOB_NAME` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `JOB_GROUP` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `DESCRIPTION` varchar(250) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `JOB_CLASS_NAME` varchar(250) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `IS_DURABLE` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `IS_NONCONCURRENT` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `IS_UPDATE_DATA` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `REQUESTS_RECOVERY` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `JOB_DATA` blob NULL, + PRIMARY KEY (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) USING BTREE, + INDEX `IDX_QRTZ_J_REQ_RECOVERY`(`SCHED_NAME`, `REQUESTS_RECOVERY`) USING BTREE, + INDEX `IDX_QRTZ_J_GRP`(`SCHED_NAME`, `JOB_GROUP`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC; -- ---------------------------- @@ -147,10 +154,11 @@ CREATE TABLE `schedule_job_details` ( -- Table structure for schedule_locks -- ---------------------------- DROP TABLE IF EXISTS `schedule_locks`; -CREATE TABLE `schedule_locks` ( - `SCHED_NAME` varchar(120) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - `LOCK_NAME` varchar(40) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - PRIMARY KEY (`SCHED_NAME`, `LOCK_NAME`) USING BTREE +CREATE TABLE `schedule_locks` +( + `SCHED_NAME` varchar(120) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `LOCK_NAME` varchar(40) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + PRIMARY KEY (`SCHED_NAME`, `LOCK_NAME`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC; -- ---------------------------- @@ -161,17 +169,18 @@ CREATE TABLE `schedule_locks` ( -- Table structure for schedule_log -- ---------------------------- DROP TABLE IF EXISTS `schedule_log`; -CREATE TABLE `schedule_log` ( - `log_id` char(19) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '任务日志id', - `job_id` char(19) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '任务id', - `bean_name` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'spring bean名称', - `params` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '参数', - `status` tinyint(4) NOT NULL COMMENT '任务状态 0:成功 1:失败', - `error` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '失败信息', - `times` int(11) NOT NULL COMMENT '耗时(单位:毫秒)', - `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', - PRIMARY KEY (`log_id`) USING BTREE, - INDEX `job_id`(`job_id`) USING BTREE +CREATE TABLE `schedule_log` +( + `log_id` char(19) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '任务日志id', + `job_id` char(19) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '任务id', + `bean_name` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT 'spring bean名称', + `params` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '参数', + `status` tinyint(4) NOT NULL COMMENT '任务状态 0:成功 1:失败', + `error` varchar(2000) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '失败信息', + `times` int(11) NOT NULL COMMENT '耗时(单位:毫秒)', + `create_time` datetime(0) NULL DEFAULT NULL COMMENT '创建时间', + PRIMARY KEY (`log_id`) USING BTREE, + INDEX `job_id`(`job_id`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '定时任务日志' ROW_FORMAT = DYNAMIC; -- ---------------------------- @@ -182,10 +191,11 @@ CREATE TABLE `schedule_log` ( -- Table structure for schedule_paused_trigger_grps -- ---------------------------- DROP TABLE IF EXISTS `schedule_paused_trigger_grps`; -CREATE TABLE `schedule_paused_trigger_grps` ( - `SCHED_NAME` varchar(120) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - `TRIGGER_GROUP` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - PRIMARY KEY (`SCHED_NAME`, `TRIGGER_GROUP`) USING BTREE +CREATE TABLE `schedule_paused_trigger_grps` +( + `SCHED_NAME` varchar(120) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `TRIGGER_GROUP` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + PRIMARY KEY (`SCHED_NAME`, `TRIGGER_GROUP`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC; -- ---------------------------- @@ -196,12 +206,13 @@ CREATE TABLE `schedule_paused_trigger_grps` ( -- Table structure for schedule_scheduler_state -- ---------------------------- DROP TABLE IF EXISTS `schedule_scheduler_state`; -CREATE TABLE `schedule_scheduler_state` ( - `SCHED_NAME` varchar(120) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - `INSTANCE_NAME` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - `LAST_CHECKIN_TIME` bigint(20) NOT NULL, - `CHECKIN_INTERVAL` bigint(20) NOT NULL, - PRIMARY KEY (`SCHED_NAME`, `INSTANCE_NAME`) USING BTREE +CREATE TABLE `schedule_scheduler_state` +( + `SCHED_NAME` varchar(120) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `INSTANCE_NAME` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `LAST_CHECKIN_TIME` bigint(20) NOT NULL, + `CHECKIN_INTERVAL` bigint(20) NOT NULL, + PRIMARY KEY (`SCHED_NAME`, `INSTANCE_NAME`) USING BTREE ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC; -- ---------------------------- @@ -212,15 +223,16 @@ CREATE TABLE `schedule_scheduler_state` ( -- Table structure for schedule_simple_triggers -- ---------------------------- DROP TABLE IF EXISTS `schedule_simple_triggers`; -CREATE TABLE `schedule_simple_triggers` ( - `SCHED_NAME` varchar(120) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - `TRIGGER_NAME` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - `TRIGGER_GROUP` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - `REPEAT_COUNT` bigint(20) NOT NULL, - `REPEAT_INTERVAL` bigint(20) NOT NULL, - `TIMES_TRIGGERED` bigint(20) NOT NULL, - PRIMARY KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE, - CONSTRAINT `schedule_simple_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `schedule_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) ON DELETE RESTRICT ON UPDATE RESTRICT +CREATE TABLE `schedule_simple_triggers` +( + `SCHED_NAME` varchar(120) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `TRIGGER_NAME` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `TRIGGER_GROUP` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `REPEAT_COUNT` bigint(20) NOT NULL, + `REPEAT_INTERVAL` bigint(20) NOT NULL, + `TIMES_TRIGGERED` bigint(20) NOT NULL, + PRIMARY KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE, + CONSTRAINT `schedule_simple_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `schedule_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) ON DELETE RESTRICT ON UPDATE RESTRICT ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC; -- ---------------------------- @@ -231,23 +243,24 @@ CREATE TABLE `schedule_simple_triggers` ( -- Table structure for schedule_simprop_triggers -- ---------------------------- DROP TABLE IF EXISTS `schedule_simprop_triggers`; -CREATE TABLE `schedule_simprop_triggers` ( - `SCHED_NAME` varchar(120) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - `TRIGGER_NAME` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - `TRIGGER_GROUP` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - `STR_PROP_1` varchar(512) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, - `STR_PROP_2` varchar(512) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, - `STR_PROP_3` varchar(512) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, - `INT_PROP_1` int(11) NULL DEFAULT NULL, - `INT_PROP_2` int(11) NULL DEFAULT NULL, - `LONG_PROP_1` bigint(20) NULL DEFAULT NULL, - `LONG_PROP_2` bigint(20) NULL DEFAULT NULL, - `DEC_PROP_1` decimal(13, 4) NULL DEFAULT NULL, - `DEC_PROP_2` decimal(13, 4) NULL DEFAULT NULL, - `BOOL_PROP_1` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, - `BOOL_PROP_2` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, - PRIMARY KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE, - CONSTRAINT `schedule_simprop_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `schedule_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) ON DELETE RESTRICT ON UPDATE RESTRICT +CREATE TABLE `schedule_simprop_triggers` +( + `SCHED_NAME` varchar(120) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `TRIGGER_NAME` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `TRIGGER_GROUP` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `STR_PROP_1` varchar(512) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `STR_PROP_2` varchar(512) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `STR_PROP_3` varchar(512) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `INT_PROP_1` int(11) NULL DEFAULT NULL, + `INT_PROP_2` int(11) NULL DEFAULT NULL, + `LONG_PROP_1` bigint(20) NULL DEFAULT NULL, + `LONG_PROP_2` bigint(20) NULL DEFAULT NULL, + `DEC_PROP_1` decimal(13, 4) NULL DEFAULT NULL, + `DEC_PROP_2` decimal(13, 4) NULL DEFAULT NULL, + `BOOL_PROP_1` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `BOOL_PROP_2` varchar(1) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + PRIMARY KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE, + CONSTRAINT `schedule_simprop_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) REFERENCES `schedule_triggers` (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) ON DELETE RESTRICT ON UPDATE RESTRICT ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC; -- ---------------------------- @@ -258,41 +271,43 @@ CREATE TABLE `schedule_simprop_triggers` ( -- Table structure for schedule_triggers -- ---------------------------- DROP TABLE IF EXISTS `schedule_triggers`; -CREATE TABLE `schedule_triggers` ( - `SCHED_NAME` varchar(120) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - `TRIGGER_NAME` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - `TRIGGER_GROUP` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - `JOB_NAME` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - `JOB_GROUP` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - `DESCRIPTION` varchar(250) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, - `NEXT_FIRE_TIME` bigint(20) NULL DEFAULT NULL, - `PREV_FIRE_TIME` bigint(20) NULL DEFAULT NULL, - `PRIORITY` int(11) NULL DEFAULT NULL, - `TRIGGER_STATE` varchar(16) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - `TRIGGER_TYPE` varchar(8) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, - `START_TIME` bigint(20) NOT NULL, - `END_TIME` bigint(20) NULL DEFAULT NULL, - `CALENDAR_NAME` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, - `MISFIRE_INSTR` smallint(6) NULL DEFAULT NULL, - `JOB_DATA` blob NULL, - PRIMARY KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE, - INDEX `IDX_QRTZ_T_J`(`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) USING BTREE, - INDEX `IDX_QRTZ_T_JG`(`SCHED_NAME`, `JOB_GROUP`) USING BTREE, - INDEX `IDX_QRTZ_T_C`(`SCHED_NAME`, `CALENDAR_NAME`) USING BTREE, - INDEX `IDX_QRTZ_T_G`(`SCHED_NAME`, `TRIGGER_GROUP`) USING BTREE, - INDEX `IDX_QRTZ_T_STATE`(`SCHED_NAME`, `TRIGGER_STATE`) USING BTREE, - INDEX `IDX_QRTZ_T_N_STATE`(`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `TRIGGER_STATE`) USING BTREE, - INDEX `IDX_QRTZ_T_N_G_STATE`(`SCHED_NAME`, `TRIGGER_GROUP`, `TRIGGER_STATE`) USING BTREE, - INDEX `IDX_QRTZ_T_NEXT_FIRE_TIME`(`SCHED_NAME`, `NEXT_FIRE_TIME`) USING BTREE, - INDEX `IDX_QRTZ_T_NFT_ST`(`SCHED_NAME`, `TRIGGER_STATE`, `NEXT_FIRE_TIME`) USING BTREE, - INDEX `IDX_QRTZ_T_NFT_MISFIRE`(`SCHED_NAME`, `MISFIRE_INSTR`, `NEXT_FIRE_TIME`) USING BTREE, - INDEX `IDX_QRTZ_T_NFT_ST_MISFIRE`(`SCHED_NAME`, `MISFIRE_INSTR`, `NEXT_FIRE_TIME`, `TRIGGER_STATE`) USING BTREE, - INDEX `IDX_QRTZ_T_NFT_ST_MISFIRE_GRP`(`SCHED_NAME`, `MISFIRE_INSTR`, `NEXT_FIRE_TIME`, `TRIGGER_GROUP`, `TRIGGER_STATE`) USING BTREE, - CONSTRAINT `schedule_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) REFERENCES `schedule_job_details` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) ON DELETE RESTRICT ON UPDATE RESTRICT +CREATE TABLE `schedule_triggers` +( + `SCHED_NAME` varchar(120) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `TRIGGER_NAME` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `TRIGGER_GROUP` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `JOB_NAME` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `JOB_GROUP` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `DESCRIPTION` varchar(250) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `NEXT_FIRE_TIME` bigint(20) NULL DEFAULT NULL, + `PREV_FIRE_TIME` bigint(20) NULL DEFAULT NULL, + `PRIORITY` int(11) NULL DEFAULT NULL, + `TRIGGER_STATE` varchar(16) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `TRIGGER_TYPE` varchar(8) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, + `START_TIME` bigint(20) NOT NULL, + `END_TIME` bigint(20) NULL DEFAULT NULL, + `CALENDAR_NAME` varchar(200) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `MISFIRE_INSTR` smallint(6) NULL DEFAULT NULL, + `JOB_DATA` blob NULL, + PRIMARY KEY (`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`) USING BTREE, + INDEX `IDX_QRTZ_T_J`(`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) USING BTREE, + INDEX `IDX_QRTZ_T_JG`(`SCHED_NAME`, `JOB_GROUP`) USING BTREE, + INDEX `IDX_QRTZ_T_C`(`SCHED_NAME`, `CALENDAR_NAME`) USING BTREE, + INDEX `IDX_QRTZ_T_G`(`SCHED_NAME`, `TRIGGER_GROUP`) USING BTREE, + INDEX `IDX_QRTZ_T_STATE`(`SCHED_NAME`, `TRIGGER_STATE`) USING BTREE, + INDEX `IDX_QRTZ_T_N_STATE`(`SCHED_NAME`, `TRIGGER_NAME`, `TRIGGER_GROUP`, `TRIGGER_STATE`) USING BTREE, + INDEX `IDX_QRTZ_T_N_G_STATE`(`SCHED_NAME`, `TRIGGER_GROUP`, `TRIGGER_STATE`) USING BTREE, + INDEX `IDX_QRTZ_T_NEXT_FIRE_TIME`(`SCHED_NAME`, `NEXT_FIRE_TIME`) USING BTREE, + INDEX `IDX_QRTZ_T_NFT_ST`(`SCHED_NAME`, `TRIGGER_STATE`, `NEXT_FIRE_TIME`) USING BTREE, + INDEX `IDX_QRTZ_T_NFT_MISFIRE`(`SCHED_NAME`, `MISFIRE_INSTR`, `NEXT_FIRE_TIME`) USING BTREE, + INDEX `IDX_QRTZ_T_NFT_ST_MISFIRE`(`SCHED_NAME`, `MISFIRE_INSTR`, `NEXT_FIRE_TIME`, `TRIGGER_STATE`) USING BTREE, + INDEX `IDX_QRTZ_T_NFT_ST_MISFIRE_GRP`(`SCHED_NAME`, `MISFIRE_INSTR`, `NEXT_FIRE_TIME`, `TRIGGER_GROUP`, `TRIGGER_STATE`) USING BTREE, + CONSTRAINT `schedule_triggers_ibfk_1` FOREIGN KEY (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) REFERENCES `schedule_job_details` (`SCHED_NAME`, `JOB_NAME`, `JOB_GROUP`) ON DELETE RESTRICT ON UPDATE RESTRICT ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = DYNAMIC; -- ---------------------------- -- Records of schedule_triggers -- ---------------------------- -SET FOREIGN_KEY_CHECKS = 1; +SET +FOREIGN_KEY_CHECKS = 1; diff --git a/pear-common/pom.xml b/pear-common/pom.xml index a66b10a6e00aae690fec9b82821d4e3b232bd84a..c6ff258b1e7d0645d78a82c87df94694dd6a3ceb 100644 --- a/pear-common/pom.xml +++ b/pear-common/pom.xml @@ -1,5 +1,5 @@ - 4.0.0 diff --git a/pear-common/src/main/java/com/pearadmin/common/config/CoreConfig.java b/pear-common/src/main/java/com/pearadmin/common/config/CoreConfig.java index d771528a01476ca6d75424b2f27d18aed08b2c4b..ac378950b565ccf684c3628ec9f33ae36a58cabb 100644 --- a/pear-common/src/main/java/com/pearadmin/common/config/CoreConfig.java +++ b/pear-common/src/main/java/com/pearadmin/common/config/CoreConfig.java @@ -14,15 +14,18 @@ import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactor import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer; import org.springframework.data.redis.serializer.StringRedisSerializer; + import javax.annotation.Resource; import java.io.Serializable; -import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.format.DateTimeFormatter; +/** + * @author 就 眠 仪 式 + */ @Configuration public class CoreConfig { @@ -33,7 +36,7 @@ public class CoreConfig { public MailAccount mailAccount() { MailAccount mailAccount = new MailAccount(); mailAccount.setHost(sysContext.getConfig(ConfigurationConstant.MAIN_HOST)); - mailAccount.setPort(sysContext.getConfig(ConfigurationConstant.MAIN_PORT)==""?0000: Integer.parseInt(sysContext.getConfig(ConfigurationConstant.MAIN_PORT))); + mailAccount.setPort(sysContext.getConfig(ConfigurationConstant.MAIN_PORT) == "" ? 0000 : Integer.parseInt(sysContext.getConfig(ConfigurationConstant.MAIN_PORT))); mailAccount.setFrom(sysContext.getConfig(ConfigurationConstant.MAIN_FROM)); mailAccount.setUser(sysContext.getConfig(ConfigurationConstant.MAIN_USER)); mailAccount.setPass(sysContext.getConfig(ConfigurationConstant.MAIN_PASS)); @@ -53,7 +56,7 @@ public class CoreConfig { } @Bean - public Module dateTime(){ + public Module dateTime() { JavaTimeModule javaTimeModule = new JavaTimeModule(); javaTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); javaTimeModule.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd"))); diff --git a/pear-common/src/main/java/com/pearadmin/common/config/QuartzConfig.java b/pear-common/src/main/java/com/pearadmin/common/config/QuartzConfig.java index 5edd8327a4daacece00583d59cdadd1345bfd032..bd5ffc0e0fc9b95d2d26e833f5e52e29beff4cb4 100644 --- a/pear-common/src/main/java/com/pearadmin/common/config/QuartzConfig.java +++ b/pear-common/src/main/java/com/pearadmin/common/config/QuartzConfig.java @@ -5,15 +5,15 @@ import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.quartz.SchedulerFactoryBean; import javax.annotation.Resource; -import javax.annotation.sql.DataSourceDefinition; import javax.sql.DataSource; import java.util.Properties; /** * Describe: 定 时 任 务 配 置 文 件 - * Author: 就 眠 仪 式 + * + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ + */ @Configuration public class QuartzConfig { @@ -24,7 +24,7 @@ public class QuartzConfig { * Describe: 定时任务工厂 * Param: DataSource * Return: ScheduleFactoryBean - * */ + */ @Bean public SchedulerFactoryBean schedulerFactoryBean() { Properties prop = new Properties(); diff --git a/pear-common/src/main/java/com/pearadmin/common/config/SwaggerConfig.java b/pear-common/src/main/java/com/pearadmin/common/config/SwaggerConfig.java index 456f1fdc7a1bb66ca1c9c9b47f716e2248dc0e2e..5cce276fafd4c08b9f82414ff3e97aa780c08d66 100644 --- a/pear-common/src/main/java/com/pearadmin/common/config/SwaggerConfig.java +++ b/pear-common/src/main/java/com/pearadmin/common/config/SwaggerConfig.java @@ -1,25 +1,27 @@ package com.pearadmin.common.config; -import lombok.extern.slf4j.Slf4j; import com.pearadmin.common.config.proprety.SwaggerProperty; -import org.springframework.context.annotation.Configuration; -import springfox.documentation.builders.RequestHandlerSelectors; +import lombok.extern.slf4j.Slf4j; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.context.properties.EnableConfigurationProperties; -import springfox.documentation.swagger2.annotations.EnableSwagger2; -import springfox.documentation.spring.web.plugins.Docket; -import springfox.documentation.spi.DocumentationType; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.service.ApiInfo; import springfox.documentation.service.Contact; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + import javax.annotation.Resource; import java.util.ArrayList; /** * Describe: 接 口 文 档 配 置 文 件 - * Author: 就 眠 仪 式 + * + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ + */ @Slf4j @Configuration @EnableSwagger2 @@ -31,7 +33,7 @@ public class SwaggerConfig { private SwaggerProperty documentAutoProperties; @Bean - public Docket docker(){ + public Docket docker() { log.info("Read document configuration information"); return new Docket(DocumentationType.SWAGGER_2) .apiInfo(apiInfo()) @@ -42,13 +44,13 @@ public class SwaggerConfig { .build(); } - private ApiInfo apiInfo(){ + private ApiInfo apiInfo() { return new ApiInfo( documentAutoProperties.getTitle(), - documentAutoProperties.getDescribe() , + documentAutoProperties.getDescribe(), documentAutoProperties.getVersion(), - documentAutoProperties.getTermsOfServiceUrl(),documentAutoProperties.getContact(),documentAutoProperties.getLicence(),documentAutoProperties.getLicenceUrl(), + documentAutoProperties.getTermsOfServiceUrl(), documentAutoProperties.getContact(), documentAutoProperties.getLicence(), documentAutoProperties.getLicenceUrl(), new ArrayList<>() ); } -} \ No newline at end of file +} diff --git a/pear-common/src/main/java/com/pearadmin/common/config/proprety/SecurityProperty.java b/pear-common/src/main/java/com/pearadmin/common/config/proprety/SecurityProperty.java index cfca895f1c91e69514d5b06f59f795efc20ba339..0e8db7a67c06da64b6644d6d48b36ee120e7e778 100644 --- a/pear-common/src/main/java/com/pearadmin/common/config/proprety/SecurityProperty.java +++ b/pear-common/src/main/java/com/pearadmin/common/config/proprety/SecurityProperty.java @@ -5,36 +5,37 @@ import org.springframework.boot.context.properties.ConfigurationProperties; /** * Describe: 系 统 权 限 配 置 类 - * Author: 就 眠 仪 式 + * + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ + */ @Data @ConfigurationProperties("pear.security") public class SecurityProperty { /** * 超级管理员不认证 - * */ + */ private boolean superAuthOpen; /** * 不验证权限用户名 - * */ + */ private String superAdmin; /** * 记住密码标识 - * */ + */ private String rememberKey; /** * 开放接口列表 - * */ + */ private String[] openApi; /** * 是否允许多账号在线 - * */ + */ private Integer maximum = 1; } diff --git a/pear-common/src/main/java/com/pearadmin/common/config/proprety/SwaggerProperty.java b/pear-common/src/main/java/com/pearadmin/common/config/proprety/SwaggerProperty.java index b0030b546c3dbce3978d067c062e02355ef7aa2c..aeca694497c96388dd2ae9be9c39a126a1ddf158 100644 --- a/pear-common/src/main/java/com/pearadmin/common/config/proprety/SwaggerProperty.java +++ b/pear-common/src/main/java/com/pearadmin/common/config/proprety/SwaggerProperty.java @@ -6,41 +6,62 @@ import springfox.documentation.service.Contact; /** * Describe: 接 口 文 档 配 置 类 - * Author: 就 眠 仪 式 + * + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ + */ @Data @ConfigurationProperties("pear.swagger") public class SwaggerProperty { - /** 是 否 开 启 */ + /** + * 是 否 开 启 + */ private Boolean enable = true; - /** 分 组 名 称 */ + /** + * 分 组 名 称 + */ private String groupName; - /** 系 统 标 题 */ + /** + * 系 统 标 题 + */ private String title; - /** 描 述 信 息 */ + /** + * 描 述 信 息 + */ private String describe; - /** 版 本 信 息 */ + /** + * 版 本 信 息 + */ private String version; - /** 扫 描 路 径 */ + /** + * 扫 描 路 径 + */ private String scanPackage; - /** 扩 展 信 息 */ + /** + * 扩 展 信 息 + */ private Contact contact; - /** 协 议 */ + /** + * 协 议 + */ private String licence; - /** 协 议 链 接 */ + /** + * 协 议 链 接 + */ private String licenceUrl; - /** 组 织 链 接 */ + /** + * 组 织 链 接 + */ private String termsOfServiceUrl; -} \ No newline at end of file +} diff --git a/pear-common/src/main/java/com/pearadmin/common/config/proprety/TemplateProperty.java b/pear-common/src/main/java/com/pearadmin/common/config/proprety/TemplateProperty.java index 5e898911d84fe8825b49b0cb086d5a68f1b1f574..3a516c1075427ad89066c311edf373fc0c6a24a5 100644 --- a/pear-common/src/main/java/com/pearadmin/common/config/proprety/TemplateProperty.java +++ b/pear-common/src/main/java/com/pearadmin/common/config/proprety/TemplateProperty.java @@ -8,28 +8,29 @@ import java.io.File; /** * Describe: 接 口 文 档 配 置 类 - * Author: 就 眠 仪 式 + * + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ + */ @Data @Component @ConfigurationProperties("pear.upload") public class TemplateProperty { /** - * windows 系统文件上传路径 - * */ + * windows 系统文件上传路径 + */ private String windowsPath; /** * linux 系统文件上传路径 - * */ + */ private String linuxPath; /** * upload path 根据系统环境获取上传路径 - * */ - public String getUploadPath(){ + */ + public String getUploadPath() { return '\\' == File.separatorChar ? this.windowsPath : this.linuxPath; } diff --git a/pear-common/src/main/java/com/pearadmin/common/constant/ConfigurationConstant.java b/pear-common/src/main/java/com/pearadmin/common/constant/ConfigurationConstant.java index 83a5cfd3fae407e06cc025f82118f77dfc1fa473..5c5caf3cdb2f93800c0fcc3a191df9c480029b18 100644 --- a/pear-common/src/main/java/com/pearadmin/common/constant/ConfigurationConstant.java +++ b/pear-common/src/main/java/com/pearadmin/common/constant/ConfigurationConstant.java @@ -1,5 +1,8 @@ package com.pearadmin.common.constant; +/** + * @author 就眠仪式 + */ public class ConfigurationConstant { public final static String MAIN_HOST = "main_host"; diff --git a/pear-common/src/main/java/com/pearadmin/common/constant/ControllerConstant.java b/pear-common/src/main/java/com/pearadmin/common/constant/ControllerConstant.java index d4f80a78e05ba6d654902d9d8ae4739c24d0c0a2..1ae0eec14877595dc9fa3e25a9e63361a99c39ce 100644 --- a/pear-common/src/main/java/com/pearadmin/common/constant/ControllerConstant.java +++ b/pear-common/src/main/java/com/pearadmin/common/constant/ControllerConstant.java @@ -2,28 +2,29 @@ package com.pearadmin.common.constant; /** * Describe: 接 口 静 态 常 量 - * Author: 就 眠 仪 式 + * + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ + */ public class ControllerConstant { /** * 系统业务基础路径 - * */ + */ public final static String API_SYSTEM_PREFIX = "/system/"; /** * 代码生成基础路径 - * */ + */ public final static String API_GENERATOR_PREFIX = "/generate/"; /** * 定时任务基础路径 - * */ + */ public final static String API_SCHEDULE_PREFIX = "/schedule/"; /** * 工作流程基础路径 - * */ + */ public final static String API_PROCESS_PREFIX = "/process/"; } diff --git a/pear-common/src/main/java/com/pearadmin/common/constant/GenerateConstant.java b/pear-common/src/main/java/com/pearadmin/common/constant/GenerateConstant.java index 431bb9b8a679ceab5a2bfe428ba35212f043b743..c8672eb8a15ab431983e8af9c4e492216984c55a 100644 --- a/pear-common/src/main/java/com/pearadmin/common/constant/GenerateConstant.java +++ b/pear-common/src/main/java/com/pearadmin/common/constant/GenerateConstant.java @@ -2,107 +2,169 @@ package com.pearadmin.common.constant; /** * Describe: 代 码 生 成 通 用 常 量 - * Author: 就 眠 仪 式 + * + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ -public class GenerateConstant -{ + */ +public class GenerateConstant { - /** 单表(增删改查) */ + /** + * 单表(增删改查) + */ public static final String TPL_CRUD = "crud"; - /** 树表(增删改查) */ + /** + * 树表(增删改查) + */ public static final String TPL_TREE = "tree"; - /** 主子表(增删改查) */ + /** + * 主子表(增删改查) + */ public static final String TPL_SUB = "sub"; - /** 树编码字段 */ + /** + * 树编码字段 + */ public static final String TREE_CODE = "treeCode"; - /** 树父编码字段 */ + /** + * 树父编码字段 + */ public static final String TREE_PARENT_CODE = "treeParentCode"; - /** 树名称字段 */ + /** + * 树名称字段 + */ public static final String TREE_NAME = "treeName"; - /** 上级菜单ID字段 */ + /** + * 上级菜单ID字段 + */ public static final String PARENT_MENU_ID = "parentMenuId"; - /** 上级菜单名称字段 */ + /** + * 上级菜单名称字段 + */ public static final String PARENT_MENU_NAME = "parentMenuName"; - /** 数据库字符串类型 */ - public static final String[] COLUMNTYPE_STR = { "char", "varchar", "narchar", "varchar2", "tinytext", "text", - "mediumtext", "longtext" }; - - /** 数据库时间类型 */ - public static final String[] COLUMNTYPE_TIME = { "datetime", "time", "date", "timestamp" }; - - /** 数据库数字类型 */ - public static final String[] COLUMNTYPE_NUMBER = { "tinyint", "smallint", "mediumint", "int", "number", "integer", - "bigint", "float", "float", "double", "decimal" }; - - /** 页面不需要编辑字段 */ - public static final String[] COLUMNNAME_NOT_EDIT = { "id", "create_by", "create_time", "del_flag" }; - - /** 页面不需要显示的列表字段 */ - public static final String[] COLUMNNAME_NOT_LIST = { "id", "create_by", "create_time", "del_flag", "update_by", - "update_time" }; - - /** 页面不需要查询字段 */ - public static final String[] COLUMNNAME_NOT_QUERY = { "id", "create_by", "create_time", "del_flag", "update_by", - "update_time", "remark" }; - - /** Entity基类字段 */ - public static final String[] BASE_ENTITY = { "createBy", "createTime", "updateBy", "updateTime", "remark" }; - - /** Tree基类字段 */ - public static final String[] TREE_ENTITY = { "parentName", "parentId", "orderNum", "ancestors" }; - - /** 文本框 */ + /** + * 数据库字符串类型 + */ + public static final String[] COLUMNTYPE_STR = {"char", "varchar", "narchar", "varchar2", "tinytext", "text", + "mediumtext", "longtext"}; + + /** + * 数据库时间类型 + */ + public static final String[] COLUMNTYPE_TIME = {"datetime", "time", "date", "timestamp"}; + + /** + * 数据库数字类型 + */ + public static final String[] COLUMNTYPE_NUMBER = {"tinyint", "smallint", "mediumint", "int", "number", "integer", + "bigint", "float", "float", "double", "decimal"}; + + /** + * 页面不需要编辑字段 + */ + public static final String[] COLUMNNAME_NOT_EDIT = {"id", "create_by", "create_time", "del_flag"}; + + /** + * 页面不需要显示的列表字段 + */ + public static final String[] COLUMNNAME_NOT_LIST = {"id", "create_by", "create_time", "del_flag", "update_by", + "update_time"}; + + /** + * 页面不需要查询字段 + */ + public static final String[] COLUMNNAME_NOT_QUERY = {"id", "create_by", "create_time", "del_flag", "update_by", + "update_time", "remark"}; + + /** + * Entity基类字段 + */ + public static final String[] BASE_ENTITY = {"createBy", "createTime", "updateBy", "updateTime", "remark"}; + + /** + * Tree基类字段 + */ + public static final String[] TREE_ENTITY = {"parentName", "parentId", "orderNum", "ancestors"}; + + /** + * 文本框 + */ public static final String HTML_INPUT = "input"; - /** 文本域 */ + /** + * 文本域 + */ public static final String HTML_TEXTAREA = "textarea"; - /** 下拉框 */ + /** + * 下拉框 + */ public static final String HTML_SELECT = "select"; - /** 单选框 */ + /** + * 单选框 + */ public static final String HTML_RADIO = "radio"; - /** 复选框 */ + /** + * 复选框 + */ public static final String HTML_CHECKBOX = "checkbox"; - /** 日期控件 */ + /** + * 日期控件 + */ public static final String HTML_DATETIME = "datetime"; - /** 上传控件 */ + /** + * 上传控件 + */ public static final String HTML_UPLOAD = "upload"; - /** 字符串类型 */ + /** + * 字符串类型 + */ public static final String TYPE_STRING = "String"; - /** 整型 */ + /** + * 整型 + */ public static final String TYPE_INTEGER = "Integer"; - /** 长整型 */ + /** + * 长整型 + */ public static final String TYPE_LONG = "Long"; - /** 浮点型 */ + /** + * 浮点型 + */ public static final String TYPE_DOUBLE = "Double"; - /** 高精度计算类型 */ + /** + * 高精度计算类型 + */ public static final String TYPE_BIGDECIMAL = "BigDecimal"; - /** 时间类型 */ + /** + * 时间类型 + */ public static final String TYPE_DATE = "Date"; - /** 模糊查询 */ + /** + * 模糊查询 + */ public static final String QUERY_LIKE = "LIKE"; - /** 需要 */ + /** + * 需要 + */ public static final String REQUIRE = "1"; } diff --git a/pear-common/src/main/java/com/pearadmin/common/constant/SystemConstant.java b/pear-common/src/main/java/com/pearadmin/common/constant/SystemConstant.java index f0ab77cb60b6d8b7fcbe3a7a0603fcf6d08de6fd..06e2365d2dd33b8536c6cbc6874cc23116e2d9c3 100644 --- a/pear-common/src/main/java/com/pearadmin/common/constant/SystemConstant.java +++ b/pear-common/src/main/java/com/pearadmin/common/constant/SystemConstant.java @@ -2,33 +2,30 @@ package com.pearadmin.common.constant; /** * Describe: 系 统 常 量 - * Author: 就 眠 仪 式 + * + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ + */ public class SystemConstant { /** * Windows 系统常量标识 - * */ + */ public static String WINDOWS = "windows"; - - /** - * Linux 系统常量标识 - * */ - private static String Linux = "linux"; - /** * UTF-8 编码格式 - * */ - public static String UTF8 ="UTF-8"; - + */ + public static String UTF8 = "UTF-8"; /** * GBK 编码格式 - * */ + */ public static String GBK = "GBK"; - /** * 空串 - * */ + */ public static String EMPTY = ""; + /** + * Linux 系统常量标识 + */ + private static String Linux = "linux"; } diff --git a/pear-common/src/main/java/com/pearadmin/common/exception/GlobalExceptionHandler.java b/pear-common/src/main/java/com/pearadmin/common/exception/GlobalExceptionHandler.java index 2af08371a752d070e00932693a4c688cc073d5b8..da02ce5ad3062ad9a9dd874a6647f09d2d0dd06e 100644 --- a/pear-common/src/main/java/com/pearadmin/common/exception/GlobalExceptionHandler.java +++ b/pear-common/src/main/java/com/pearadmin/common/exception/GlobalExceptionHandler.java @@ -2,7 +2,6 @@ package com.pearadmin.common.exception; import com.pearadmin.common.exception.base.BusinessException; import com.pearadmin.common.tools.servlet.ServletUtil; -import com.pearadmin.common.web.base.BaseController; import com.pearadmin.common.web.domain.response.Result; import lombok.extern.slf4j.Slf4j; import org.springframework.security.access.AccessDeniedException; @@ -10,23 +9,25 @@ import org.springframework.web.HttpRequestMethodNotSupportedException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; import org.springframework.web.servlet.ModelAndView; + import javax.servlet.http.HttpServletRequest; /** * Describe: 全局异常处理类 - * Author: 就 眠 仪 式 + * + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ + */ @Slf4j @RestControllerAdvice public class GlobalExceptionHandler { /** * 不 支 持 的 请 求 类 型 - * */ + */ @ExceptionHandler({HttpRequestMethodNotSupportedException.class}) - public Result handleException(HttpRequestMethodNotSupportedException e){ - log.error(e.getMessage(),e); + public Result handleException(HttpRequestMethodNotSupportedException e) { + log.error(e.getMessage(), e); return Result.failure("不支持' " + e.getMethod() + "'请求"); } @@ -34,20 +35,18 @@ public class GlobalExceptionHandler { * 拦 截 未 知 的 运 行 时 异 常 */ @ExceptionHandler({RuntimeException.class}) - public Result notFount(RuntimeException e) - { + public Result notFount(RuntimeException e) { log.error("运行时异常:", e); return Result.failure("运行时异常:" + e.getMessage()); } /** * 权 限 异 常 处 理 - * */ + */ @ExceptionHandler({AccessDeniedException.class}) - public Object access(HttpServletRequest request,AccessDeniedException e){ + public Object access(HttpServletRequest request, AccessDeniedException e) { e.printStackTrace(); - if (ServletUtil.isAjax(request)) - { + if (ServletUtil.isAjax(request)) { return Result.failure("暂无权限"); } else { @@ -62,8 +61,7 @@ public class GlobalExceptionHandler { * 系统异常 */ @ExceptionHandler(Exception.class) - public Result handleException(Exception e) - { + public Result handleException(Exception e) { log.error(e.getMessage(), e); return Result.failure("服务器错误,请联系管理员"); } @@ -72,15 +70,11 @@ public class GlobalExceptionHandler { * 业务异常 */ @ExceptionHandler(BusinessException.class) - public Object businessException(HttpServletRequest request, BusinessException e) - { + public Object businessException(HttpServletRequest request, BusinessException e) { log.error(e.getMessage(), e); - if (ServletUtil.isAjax(request)) - { + if (ServletUtil.isAjax(request)) { return Result.failure(e.getMessage()); - } - else - { + } else { ModelAndView modelAndView = new ModelAndView(); modelAndView.addObject("errorMessage", e.getMessage()); modelAndView.setViewName("error/500"); diff --git a/pear-common/src/main/java/com/pearadmin/common/exception/auth/CaptchaException.java b/pear-common/src/main/java/com/pearadmin/common/exception/auth/CaptchaException.java index d4f01132baaad454cc83498f041a1d6b66611d6f..5274b18913fbb5851380c60a1bde15ff12c2fc60 100644 --- a/pear-common/src/main/java/com/pearadmin/common/exception/auth/CaptchaException.java +++ b/pear-common/src/main/java/com/pearadmin/common/exception/auth/CaptchaException.java @@ -4,15 +4,16 @@ import org.springframework.security.core.AuthenticationException; /** * Describe: 验 证 码 异 常 类 - * Author: 就 眠 仪 式 + * + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ + */ public class CaptchaException extends AuthenticationException { /** * 验 证 码 异 常 - * */ - public CaptchaException(String message){ + */ + public CaptchaException(String message) { super(message); } diff --git a/pear-common/src/main/java/com/pearadmin/common/exception/base/BusinessException.java b/pear-common/src/main/java/com/pearadmin/common/exception/base/BusinessException.java index 353437ad36d7492b0dfba386ac57142e316dde78..f9d7597f2691a58a1c03991fe5715e1bb3a27737 100644 --- a/pear-common/src/main/java/com/pearadmin/common/exception/base/BusinessException.java +++ b/pear-common/src/main/java/com/pearadmin/common/exception/base/BusinessException.java @@ -2,26 +2,27 @@ package com.pearadmin.common.exception.base; /** * Describe: 业 务 异 常 - * Author: 就 眠 仪 式 + * + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ + */ public class BusinessException extends RuntimeException { /** * 异常消息 - * */ + */ protected final String message; /** * 业务异常 - * */ - public BusinessException(String message){ + */ + public BusinessException(String message) { this.message = message; } /** * 异常获取 - * */ + */ @Override public String getMessage() { return message; diff --git a/pear-common/src/main/java/com/pearadmin/common/listener/SetupMailConfigListener.java b/pear-common/src/main/java/com/pearadmin/common/listener/SetupMailConfigListener.java index b23807deae14041cf4fd40c6839a684a740b07f6..7b160faec7f3fee8b0436f0630f129c7451684b2 100644 --- a/pear-common/src/main/java/com/pearadmin/common/listener/SetupMailConfigListener.java +++ b/pear-common/src/main/java/com/pearadmin/common/listener/SetupMailConfigListener.java @@ -10,10 +10,10 @@ import org.springframework.context.ApplicationListener; import org.springframework.stereotype.Component; - /** * Describe: 邮 件 配 置 监 听 器 - * Author: BoscoKuo + * + * @author BoscoKuo * CreateTime: 2021/2/4 11:22 */ @Component diff --git a/pear-common/src/main/java/com/pearadmin/common/listener/event/MailConfigEvent.java b/pear-common/src/main/java/com/pearadmin/common/listener/event/MailConfigEvent.java index b09e87c6c70a550250afa80f8c5a09bd60a44359..0b8e9de7e1dd1ac4f33099475004563ec0ddacb2 100644 --- a/pear-common/src/main/java/com/pearadmin/common/listener/event/MailConfigEvent.java +++ b/pear-common/src/main/java/com/pearadmin/common/listener/event/MailConfigEvent.java @@ -7,7 +7,8 @@ import java.util.Map; /** * Describe: 添 加 邮 箱 配 置 之 后,发 布 邮 箱 配 置 事 件 - * Author: BoscoKuo + * + * @author BoscoKuo * CreateTime: 2021/2/4 11:23 */ public class MailConfigEvent extends ApplicationEvent { diff --git a/pear-common/src/main/java/com/pearadmin/common/plugins/logging/aop/LoggingAspect.java b/pear-common/src/main/java/com/pearadmin/common/plugins/logging/aop/LoggingAspect.java index 8e9eb3f47609521b1d0cb6624084855609537b33..7d240ef85e0f84a1ee906e993be8efd360ce7706 100644 --- a/pear-common/src/main/java/com/pearadmin/common/plugins/logging/aop/LoggingAspect.java +++ b/pear-common/src/main/java/com/pearadmin/common/plugins/logging/aop/LoggingAspect.java @@ -1,9 +1,9 @@ package com.pearadmin.common.plugins.logging.aop; import com.pearadmin.common.plugins.logging.aop.annotation.Logging; -import com.pearadmin.common.plugins.system.domain.SysBaseLog; import com.pearadmin.common.plugins.logging.aop.enums.LoggingType; import com.pearadmin.common.plugins.logging.async.LoggingFactory; +import com.pearadmin.common.plugins.system.domain.SysBaseLog; import com.pearadmin.common.tools.sequence.SequenceUtil; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; @@ -11,14 +11,16 @@ import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.stereotype.Component; + import javax.annotation.Resource; import java.lang.reflect.Method; /** * Describe: 日 志 切 面 实 现 - * Author: 就 眠 仪 式 + * + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ + */ @Aspect @Component public class LoggingAspect { @@ -28,16 +30,16 @@ public class LoggingAspect { /** * 切 面 编 程 - * */ + */ @Pointcut("@annotation(com.pearadmin.common.plugins.logging.aop.annotation.Logging) || @within(com.pearadmin.common.plugins.logging.aop.annotation.Logging)") - public void dsPointCut() { } + public void dsPointCut() { + } /** * 处 理 系 统 日 志 - * */ + */ @Around("dsPointCut()") - private Object around(ProceedingJoinPoint joinPoint) throws Throwable - { + private Object around(ProceedingJoinPoint joinPoint) throws Throwable { SysBaseLog sysLog = new SysBaseLog(); Object result; try { @@ -50,11 +52,11 @@ public class LoggingAspect { sysLog.setSuccess(true); sysLog.setLoggingType(LoggingType.OPERATE); result = joinPoint.proceed(); - }catch (Exception exception){ + } catch (Exception exception) { sysLog.setSuccess(false); sysLog.setErrorMsg(exception.getMessage()); throw exception; - }finally { + } finally { loggingFactory.record(sysLog); } return result; @@ -62,12 +64,12 @@ public class LoggingAspect { /** * 获 取 注 解 - * */ + */ public com.pearadmin.common.plugins.logging.aop.annotation.Logging getLogging(ProceedingJoinPoint point) { MethodSignature signature = (MethodSignature) point.getSignature(); Class targetClass = point.getTarget().getClass(); com.pearadmin.common.plugins.logging.aop.annotation.Logging targetLogging = targetClass.getAnnotation(com.pearadmin.common.plugins.logging.aop.annotation.Logging.class); - if ( targetLogging != null) { + if (targetLogging != null) { return targetLogging; } else { Method method = signature.getMethod(); diff --git a/pear-common/src/main/java/com/pearadmin/common/plugins/logging/aop/annotation/Logging.java b/pear-common/src/main/java/com/pearadmin/common/plugins/logging/aop/annotation/Logging.java index 610753b4ce2fa548b82344eae9f3acdf6f03cb37..fbef5d491b62fcd974d58296c18dfa1478e03c0b 100644 --- a/pear-common/src/main/java/com/pearadmin/common/plugins/logging/aop/annotation/Logging.java +++ b/pear-common/src/main/java/com/pearadmin/common/plugins/logging/aop/annotation/Logging.java @@ -6,9 +6,10 @@ import java.lang.annotation.*; /** * Describe: 系 统 日 志 注 解 - * Author: 就 眠 仪 式 + * + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ + */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE, ElementType.METHOD}) @Documented @@ -16,21 +17,21 @@ public @interface Logging { /** * 默认无参输入 - * */ + */ String value() default "暂无标题"; /** * Title 默认输入 - * */ + */ String title() default "暂无标题"; /** * Describe 默认输入 - * */ + */ String describe() default "暂无介绍"; /** * 业 务 类 型 默认Query - * */ + */ BusinessType type() default BusinessType.QUERY; } diff --git a/pear-common/src/main/java/com/pearadmin/common/plugins/logging/aop/enums/BusinessType.java b/pear-common/src/main/java/com/pearadmin/common/plugins/logging/aop/enums/BusinessType.java index 77c5aea1efc9f6382b5f88001a99cf9b2b91831d..54314a2a3ff8d84dddcf7db774e006ed3dfc27c6 100644 --- a/pear-common/src/main/java/com/pearadmin/common/plugins/logging/aop/enums/BusinessType.java +++ b/pear-common/src/main/java/com/pearadmin/common/plugins/logging/aop/enums/BusinessType.java @@ -2,38 +2,39 @@ package com.pearadmin.common.plugins.logging.aop.enums; /** * Describe: 日 志 业 务 类 型 - * Author: 就 眠 仪 式 + * + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ -public enum BusinessType { + */ +public enum BusinessType { - /** - * 新增 - * */ - ADD, + /** + * 新增 + */ + ADD, /** * 修改 - * */ - EDIT, + */ + EDIT, /** * 删除 - * */ - REMOVE, + */ + REMOVE, /** * 查询 - * */ - QUERY, + */ + QUERY, /** * 导出 - * */ - EXPORT, + */ + EXPORT, /** * 其他 - * */ - OTHER; + */ + OTHER; } diff --git a/pear-common/src/main/java/com/pearadmin/common/plugins/logging/aop/enums/LoggingType.java b/pear-common/src/main/java/com/pearadmin/common/plugins/logging/aop/enums/LoggingType.java index c30deb395d0cf82ce96203d7360f6dda38ec1ff2..13238eb27a03e3c831267ea278ccb5cf342350f4 100644 --- a/pear-common/src/main/java/com/pearadmin/common/plugins/logging/aop/enums/LoggingType.java +++ b/pear-common/src/main/java/com/pearadmin/common/plugins/logging/aop/enums/LoggingType.java @@ -2,18 +2,19 @@ package com.pearadmin.common.plugins.logging.aop.enums; /** * Describe: 日 志 类 型 - * Author: 就 眠 仪 式 + * + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ + */ public enum LoggingType { /** * 操 作 日 志 - * */ + */ OPERATE, /** * 登 录 日 志 - * */ + */ LOGIN } diff --git a/pear-common/src/main/java/com/pearadmin/common/plugins/logging/aop/enums/RequestMethod.java b/pear-common/src/main/java/com/pearadmin/common/plugins/logging/aop/enums/RequestMethod.java index 6c534f913e67cb809c79b012b7df9a016014c75e..3f8e63c8b1fd6d4a2122be358db2c7b8a3be19fa 100644 --- a/pear-common/src/main/java/com/pearadmin/common/plugins/logging/aop/enums/RequestMethod.java +++ b/pear-common/src/main/java/com/pearadmin/common/plugins/logging/aop/enums/RequestMethod.java @@ -2,29 +2,30 @@ package com.pearadmin.common.plugins.logging.aop.enums; /** * Describe: 请 求 方 式 - * Author: 就 眠 仪 式 + * + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ -public enum RequestMethod { + */ +public enum RequestMethod { /** * Get 请求 - * */ + */ GET, /** * Post 请求 - * */ + */ POST, /** * Put 请求 - * */ + */ PUT, /** * Delete 请求 - * */ + */ DELETE; } diff --git a/pear-common/src/main/java/com/pearadmin/common/plugins/logging/async/LoggingFactory.java b/pear-common/src/main/java/com/pearadmin/common/plugins/logging/async/LoggingFactory.java index c71620393fa07d77291e548592792c4b4186d569..33a3d8820ca018c5ba23a476c4a95a1adb93753b 100644 --- a/pear-common/src/main/java/com/pearadmin/common/plugins/logging/async/LoggingFactory.java +++ b/pear-common/src/main/java/com/pearadmin/common/plugins/logging/async/LoggingFactory.java @@ -4,27 +4,29 @@ import com.pearadmin.common.plugins.system.domain.SysBaseLog; import com.pearadmin.common.plugins.system.service.SysContext; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; + import javax.annotation.Resource; /** * Describe: 日 志 异 步 工 厂 - * Author: 就 眠 仪 式 + * + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ + */ @Component public class LoggingFactory { /** * 引 入 日 志 服 务 - * */ + */ @Resource private SysContext sysContext; /** * 执 行 日 志 入 库 操 作 - * */ + */ @Async - public void record(SysBaseLog sysLog){ + public void record(SysBaseLog sysLog) { sysContext.saveLog(sysLog); } } diff --git a/pear-common/src/main/java/com/pearadmin/common/plugins/repeat/RepeatSubmitInterceptor.java b/pear-common/src/main/java/com/pearadmin/common/plugins/repeat/RepeatSubmitInterceptor.java index 69d712ce362a5ea2ebb54fa82c100ecef194ed50..9e480647061406e007b7674976fb9acc884c0bc4 100644 --- a/pear-common/src/main/java/com/pearadmin/common/plugins/repeat/RepeatSubmitInterceptor.java +++ b/pear-common/src/main/java/com/pearadmin/common/plugins/repeat/RepeatSubmitInterceptor.java @@ -6,47 +6,42 @@ import com.pearadmin.common.web.domain.response.Result; import org.springframework.stereotype.Component; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; + import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.lang.reflect.Method; /** * Describe: 防止重复提交拦截器 - * Author: 就 眠 仪 式 + * + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ + */ @Component -public abstract class RepeatSubmitInterceptor extends HandlerInterceptorAdapter -{ +public abstract class RepeatSubmitInterceptor extends HandlerInterceptorAdapter { /** * 前置拦截,进入处理活力前判断当前提交的内容是否重复 - * */ + */ @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception - { - if (handler instanceof HandlerMethod) - { + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + if (handler instanceof HandlerMethod) { HandlerMethod handlerMethod = (HandlerMethod) handler; Method method = handlerMethod.getMethod(); RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class); - if (annotation != null) - { - if (this.isRepeatSubmit(request)) - { + if (annotation != null) { + if (this.isRepeatSubmit(request)) { Result result = new Result(); result.setSuccess(false); result.setMsg("不允许重复提交,请稍后再试"); result.setCode(500); - response.setHeader("Content-type","application/json;charset=UTF-8"); + response.setHeader("Content-type", "application/json;charset=UTF-8"); response.setCharacterEncoding("UTF-8"); response.getWriter().write(JSON.toJSONString(result)); return false; } } return true; - } - else - { + } else { return super.preHandle(request, response, handler); } } diff --git a/pear-common/src/main/java/com/pearadmin/common/plugins/repeat/annotation/RepeatSubmit.java b/pear-common/src/main/java/com/pearadmin/common/plugins/repeat/annotation/RepeatSubmit.java index d84457761c9b7b08d82513e894464b23ce8b5bf2..c6f2675ec3d6d80f7efe51e76407b80f78bf5f97 100644 --- a/pear-common/src/main/java/com/pearadmin/common/plugins/repeat/annotation/RepeatSubmit.java +++ b/pear-common/src/main/java/com/pearadmin/common/plugins/repeat/annotation/RepeatSubmit.java @@ -4,13 +4,14 @@ import java.lang.annotation.*; /** * Describe: 表单重复提交注解 - * Author: 就 眠 仪 式 + * + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ + */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface RepeatSubmit { // @annotation -} \ No newline at end of file +} diff --git a/pear-common/src/main/java/com/pearadmin/common/plugins/repeat/impl/SameUrlDataInterceptor.java b/pear-common/src/main/java/com/pearadmin/common/plugins/repeat/impl/SameUrlDataInterceptor.java index a073ea57edee543873c5d824ce09f14bcb7498a2..fa21f614bd5e96da2e307e344a1f37cfd8e3591d 100644 --- a/pear-common/src/main/java/com/pearadmin/common/plugins/repeat/impl/SameUrlDataInterceptor.java +++ b/pear-common/src/main/java/com/pearadmin/common/plugins/repeat/impl/SameUrlDataInterceptor.java @@ -3,6 +3,7 @@ package com.pearadmin.common.plugins.repeat.impl; import com.alibaba.fastjson.JSONObject; import com.pearadmin.common.plugins.repeat.RepeatSubmitInterceptor; import org.springframework.stereotype.Component; + import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import java.util.HashMap; @@ -10,15 +11,15 @@ import java.util.Map; /** * Describe: 判断请求url和数据是否和上一次相同,如果和上次相同,则是重复提交表单。 有效时间为10秒内。 - * Author: 就 眠 仪 式 + * + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ + */ @Component -public class SameUrlDataInterceptor extends RepeatSubmitInterceptor -{ +public class SameUrlDataInterceptor extends RepeatSubmitInterceptor { /** * 常用字符串标识 - * */ + */ public final String REPEAT_PARAMS = "repeatParams"; public final String REPEAT_TIME = "repeatTime"; @@ -27,19 +28,17 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor /** * 间隔时间,单位:秒 默认10秒 - * + *

* 两次相同参数的请求,如果间隔时间大于该参数,系统不会认定为重复提交的数据 */ private int intervalTime = 10; - public void setIntervalTime(int intervalTime) - { + public void setIntervalTime(int intervalTime) { this.intervalTime = intervalTime; } @Override - public boolean isRepeatSubmit(HttpServletRequest request) - { + public boolean isRepeatSubmit(HttpServletRequest request) { // 本次参数及系统时间 String nowParams = JSONObject.toJSONString(request.getParameterMap()); Map nowDataMap = new HashMap(); @@ -51,14 +50,11 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor HttpSession session = request.getSession(); Object sessionObj = session.getAttribute(SESSION_REPEAT_KEY); - if (sessionObj != null) - { + if (sessionObj != null) { Map sessionMap = (Map) sessionObj; - if (sessionMap.containsKey(url)) - { + if (sessionMap.containsKey(url)) { Map preDataMap = (Map) sessionMap.get(url); - if (compareParams(nowDataMap, preDataMap) && compareTime(nowDataMap, preDataMap)) - { + if (compareParams(nowDataMap, preDataMap) && compareTime(nowDataMap, preDataMap)) { return true; } } @@ -71,12 +67,12 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor /** * 判断参数是否相同 + * * @param nowMap 本次参数 * @param preMap 上次参数 * @return boolean 是否相同 */ - private boolean compareParams(Map nowMap, Map preMap) - { + private boolean compareParams(Map nowMap, Map preMap) { String nowParams = (String) nowMap.get(REPEAT_PARAMS); String preParams = (String) preMap.get(REPEAT_PARAMS); return nowParams.equals(preParams); @@ -84,12 +80,12 @@ public class SameUrlDataInterceptor extends RepeatSubmitInterceptor /** * 判断两次间隔时间 + * * @param nowMap 本次时间 * @param preMap 上次时间 * @return 注释 */ - private boolean compareTime(Map nowMap, Map preMap) - { + private boolean compareTime(Map nowMap, Map preMap) { long time1 = (Long) nowMap.get(REPEAT_TIME); long time2 = (Long) preMap.get(REPEAT_TIME); return (time1 - time2) < (this.intervalTime * 1000L); diff --git a/pear-common/src/main/java/com/pearadmin/common/plugins/system/domain/SysBaseConfig.java b/pear-common/src/main/java/com/pearadmin/common/plugins/system/domain/SysBaseConfig.java index 7638833b21d81ba3b7241fa5a20db02c8d7fe2f8..7ee671784cfb74ae8da942b245b9fc2f12f2e7bd 100644 --- a/pear-common/src/main/java/com/pearadmin/common/plugins/system/domain/SysBaseConfig.java +++ b/pear-common/src/main/java/com/pearadmin/common/plugins/system/domain/SysBaseConfig.java @@ -4,27 +4,27 @@ public class SysBaseConfig { /** * 配置标识 - * */ + */ private String configId; /** * 配置名称 - * */ + */ private String configName; /** * 配置类型 - * */ + */ private String configType; /** * 配置标识 - * */ + */ private String configCode; /** * 配置值 - * */ + */ private String configValue; } diff --git a/pear-common/src/main/java/com/pearadmin/common/plugins/system/domain/SysBaseDict.java b/pear-common/src/main/java/com/pearadmin/common/plugins/system/domain/SysBaseDict.java index b424de87210444040e9fa85a4791b52d498321ec..a68fa33b3afe1004a1aba5dc99905876ec0344c5 100644 --- a/pear-common/src/main/java/com/pearadmin/common/plugins/system/domain/SysBaseDict.java +++ b/pear-common/src/main/java/com/pearadmin/common/plugins/system/domain/SysBaseDict.java @@ -5,40 +5,41 @@ import lombok.Data; /** * Describe: 字典值领域模型 - * Author: 就 眠 仪 式 + * + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ + */ @Data public class SysBaseDict extends BaseDomain { /** - * id 编号 - * */ + * id 编号 + */ private String dataId; /** - * 字典显示 - * */ + * 字典显示 + */ private String dataLabel; /** * 字典值 - * */ + */ private String dataValue; /** * 字典类型 - * */ + */ private String typeCode; /** * 是否为默认 - * */ + */ private String isDefault; /** * 是否启用 - * */ + */ private String enable; } diff --git a/pear-common/src/main/java/com/pearadmin/common/plugins/system/domain/SysBaseLog.java b/pear-common/src/main/java/com/pearadmin/common/plugins/system/domain/SysBaseLog.java index 4193882a0403316d7a311d5901fef23b03191cb3..9c258aa2704e5e8c8e32ee03a8de02ff4dc39a81 100644 --- a/pear-common/src/main/java/com/pearadmin/common/plugins/system/domain/SysBaseLog.java +++ b/pear-common/src/main/java/com/pearadmin/common/plugins/system/domain/SysBaseLog.java @@ -4,6 +4,7 @@ import com.pearadmin.common.plugins.logging.aop.enums.BusinessType; import com.pearadmin.common.plugins.logging.aop.enums.LoggingType; import com.pearadmin.common.plugins.logging.aop.enums.RequestMethod; import lombok.Data; + import java.time.LocalDateTime; import java.util.HashMap; import java.util.Map; diff --git a/pear-common/src/main/java/com/pearadmin/common/plugins/system/domain/SysBasePower.java b/pear-common/src/main/java/com/pearadmin/common/plugins/system/domain/SysBasePower.java index d36ebe06808463c2f69c08d42270aacce11efaf4..b3a5ed7406a01c5c1c9e7deeb601fac3470c06d7 100644 --- a/pear-common/src/main/java/com/pearadmin/common/plugins/system/domain/SysBasePower.java +++ b/pear-common/src/main/java/com/pearadmin/common/plugins/system/domain/SysBasePower.java @@ -5,65 +5,66 @@ import lombok.Data; /** * Describe: 权限领域模型 - * Author: 就 眠 仪 式 + * + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ + */ @Data public class SysBasePower extends BaseDomain { /** * 编号 - * */ + */ private String powerId; /** * 权限名称 - * */ + */ private String powerName; /** * 类型 - * */ + */ private String powerType; /** * 标识 - * */ + */ private String powerCode; /** * 路径 - * */ + */ private String powerUrl; /** * 打开方式 - * */ + */ private String openType; /** * 父级编号 - * */ + */ private String parentId; /** * 图标 - * */ + */ private String icon; /** * 排序 - * */ + */ private Integer sort; /** * 开启 - * */ + */ private Boolean enable; /** * 计算列 提供给前端组件 - * */ + */ private String checkArr = "0"; } diff --git a/pear-common/src/main/java/com/pearadmin/common/plugins/system/domain/SysBaseRole.java b/pear-common/src/main/java/com/pearadmin/common/plugins/system/domain/SysBaseRole.java index 78ccd170bb417d536fa32db12f803b68837a9390..a8f6dd637c35527b2651c9f0b14ee482e1046dfc 100644 --- a/pear-common/src/main/java/com/pearadmin/common/plugins/system/domain/SysBaseRole.java +++ b/pear-common/src/main/java/com/pearadmin/common/plugins/system/domain/SysBaseRole.java @@ -5,30 +5,31 @@ import lombok.Data; /** * Describe: 角色领域模型 - * Author: 就 眠 仪 式 + * + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ + */ @Data public class SysBaseRole extends BaseDomain { /** * 编号 - * */ + */ private String roleId; /** * 角色名称 - * */ + */ private String roleName; /** * 角色值 - * */ + */ private String roleCode; /** * 状态 - * */ + */ private String enable; /** @@ -38,11 +39,11 @@ public class SysBaseRole extends BaseDomain { /** * 排序 - * */ + */ private Integer sort; /** * 提供前端 显示 - * */ + */ private boolean checked = false; } diff --git a/pear-common/src/main/java/com/pearadmin/common/plugins/system/domain/SysBaseUser.java b/pear-common/src/main/java/com/pearadmin/common/plugins/system/domain/SysBaseUser.java index ca15810f92b052abd1f9b8a24a6569d406dcefb1..0d320920e3510ae3ed959fea32a516e97a02212c 100644 --- a/pear-common/src/main/java/com/pearadmin/common/plugins/system/domain/SysBaseUser.java +++ b/pear-common/src/main/java/com/pearadmin/common/plugins/system/domain/SysBaseUser.java @@ -1,103 +1,102 @@ package com.pearadmin.common.plugins.system.domain; +import com.pearadmin.common.web.base.BaseDomain; import lombok.Data; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.userdetails.UserDetails; -import com.pearadmin.common.web.base.BaseDomain; + import java.time.LocalDateTime; import java.util.Collection; import java.util.List; /** * Describe: 用户领域模型 - * Author: 就 眠 仪 式 + * + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ + */ @Data public class SysBaseUser extends BaseDomain implements UserDetails { /** * 编号 - * */ + */ private String userId; /** * 账户 - * */ + */ private String username; /** * 密码 - * */ + */ private String password; /** * 盐 - * */ + */ private String salt; /** * 状态 - * */ + */ private String status; /** * 姓名 - * */ + */ private String realName; /** * 邮箱 - * */ + */ private String email; /** * 头像 - * */ + */ private String avatar; /** * 性别 - * */ + */ private String sex; /** * 电话 - * */ + */ private String phone; /** * 所属部门 - * */ + */ private String deptId; /** * 是否启用 - * */ + */ private String enable; /** * 是否登录 - * */ + */ private String login; /** * 计算列 - * */ + */ private String roleIds; /** * 最后一次登录时间 - * - * */ + */ private LocalDateTime lastTime; /** - * * 权限 这里暂时不用 security 的 Authorities - * */ private List powerList; @@ -113,7 +112,7 @@ public class SysBaseUser extends BaseDomain implements UserDetails { @Override public boolean isAccountNonLocked() { - return "1".equals(this.getStatus())?true:false; + return "1".equals(this.getStatus()) ? true : false; } @Override @@ -123,7 +122,7 @@ public class SysBaseUser extends BaseDomain implements UserDetails { @Override public boolean isEnabled() { - return "1".equals(this.getEnable())?true:false; + return "1".equals(this.getEnable()) ? true : false; } } diff --git a/pear-common/src/main/java/com/pearadmin/common/plugins/system/service/SysContext.java b/pear-common/src/main/java/com/pearadmin/common/plugins/system/service/SysContext.java index 6739bbe7c469ad2915d7cf2f036111bf9e0e1b12..7c74af3dfcdc3bee905b13dd63f4096d894a2584 100644 --- a/pear-common/src/main/java/com/pearadmin/common/plugins/system/service/SysContext.java +++ b/pear-common/src/main/java/com/pearadmin/common/plugins/system/service/SysContext.java @@ -1,85 +1,95 @@ package com.pearadmin.common.plugins.system.service; -import com.pearadmin.common.plugins.logging.aop.enums.BusinessType; -import com.pearadmin.common.plugins.logging.aop.enums.LoggingType; -import com.pearadmin.common.plugins.system.domain.*; +import com.pearadmin.common.plugins.system.domain.SysBaseDict; +import com.pearadmin.common.plugins.system.domain.SysBaseLog; +import com.pearadmin.common.plugins.system.domain.SysBaseRole; +import com.pearadmin.common.plugins.system.domain.SysBaseUser; + import java.util.List; /** * Describe: 系统基础 API - * Author: 就 眠 仪 式 + * + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ + */ public interface SysContext { - - /** - * 根据用户账号查询用户信息 - * @param username - * @return - */ - SysBaseUser getUserByName(String username); + /** + * 根据用户账号查询用户信息 + * + * @param username + * @return + */ + SysBaseUser getUserByName(String username); + + + /** + * 根据用户id查询用户信息 + * + * @param id + * @return + */ + SysBaseUser getUserById(String id); - /** - * 根据用户id查询用户信息 - * @param id - * @return - */ - SysBaseUser getUserById(String id); - - /** - * 通过用户账号查询角色集合 - * @param username - * @return - */ - List getRolesByUsername(String username); + /** + * 通过用户账号查询角色集合 + * + * @param username + * @return + */ + List getRolesByUsername(String username); - /** - * 根据字典code获取可用的字典列表数据 - * @param typeCode - * @return - */ - List selectDictByCode(String typeCode); + /** + * 根据字典code获取可用的字典列表数据 + * + * @param typeCode + * @return + */ + List selectDictByCode(String typeCode); - /** - * 查询表字典通过查询指定table的 text code key 获取字典值 - * @param table 表名 - * @param text label - * @param code value - * @return - */ + /** + * 查询表字典通过查询指定table的 text code key 获取字典值 + * + * @param table 表名 + * @param text label + * @param code value + * @return + */ List queryTableDictItemsByCode(String table, String text, String code); - /** - * 查询表字典 通过查询指定table的 text code 获取字典(指定查询条件) - * @param table 表名 - * @param text label - * @param code value - * @return - */ - List queryTableDictItemsByCodeAndFilter(String table, String text, String code, String filterSql); + /** + * 查询表字典 通过查询指定table的 text code 获取字典(指定查询条件) + * + * @param table 表名 + * @param text label + * @param code value + * @return + */ + List queryTableDictItemsByCodeAndFilter(String table, String text, String code, String filterSql); - /** - * 查询表字典 通过查询指定table的 text code key 获取字典值,包含value - * @param table 表名 - * @param text label - * @param code value - * @param keyArray values - * @return - */ - ListqueryTableDictByKeys(String table, String text, String code, String[] keyArray); + /** + * 查询表字典 通过查询指定table的 text code key 获取字典值,包含value + * + * @param table 表名 + * @param text label + * @param code value + * @param keyArray values + * @return + */ + List queryTableDictByKeys(String table, String text, String code, String[] keyArray); - /** - * 查询系统配置 - * - * @param code - * */ - String getConfig(String code); + /** + * 查询系统配置 + * + * @param code + */ + String getConfig(String code); - /** - * 存储日志 - * */ - Boolean saveLog(SysBaseLog log); + /** + * 存储日志 + */ + Boolean saveLog(SysBaseLog log); } diff --git a/pear-common/src/main/java/com/pearadmin/common/tools/common/FileUtil.java b/pear-common/src/main/java/com/pearadmin/common/tools/common/FileUtil.java index 9c9369cc8d8405f21557945b71c270968815e5ef..f42ab65595c78c041e281a22b951881c684f9bfe 100644 --- a/pear-common/src/main/java/com/pearadmin/common/tools/common/FileUtil.java +++ b/pear-common/src/main/java/com/pearadmin/common/tools/common/FileUtil.java @@ -2,9 +2,10 @@ package com.pearadmin.common.tools.common; /** * Describe: 文 件 工 具 类 - * Author: 就 眠 仪 式 + * + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ + */ public class FileUtil { public static String getPrintSize(long size) { diff --git a/pear-common/src/main/java/com/pearadmin/common/tools/database/SqlInjectionUtil.java b/pear-common/src/main/java/com/pearadmin/common/tools/database/SqlInjectionUtil.java index ebe6902f7c2c8f79b34b5888fc98305aecd37a0a..341cdbbe084c0d8242cc3cb41ab477fde810176d 100644 --- a/pear-common/src/main/java/com/pearadmin/common/tools/database/SqlInjectionUtil.java +++ b/pear-common/src/main/java/com/pearadmin/common/tools/database/SqlInjectionUtil.java @@ -12,153 +12,150 @@ import java.security.MessageDigest; */ @Slf4j public class SqlInjectionUtil { - /** - * sign 用于表字典加签的盐值【SQL漏洞】 - * (上线修改值 20200501,同步修改前端的盐值) - */ - private final static String TABLE_DICT_SIGN_SALT = "20200501"; - private final static String xssStr = "'|and |exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |;|or |+|,"; + /** + * sign 用于表字典加签的盐值【SQL漏洞】 + * (上线修改值 20200501,同步修改前端的盐值) + */ + private final static String TABLE_DICT_SIGN_SALT = "20200501"; + private final static String xssStr = "'|and |exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |;|or |+|,"; - /* - * 针对表字典进行额外的sign签名校验(增加安全机制) - * @param dictCode: - * @param sign: - * @param request: - * @Return: void - */ - public static void checkDictTableSign(String dictCode, String sign, HttpServletRequest request) { - //表字典SQL注入漏洞,签名校验 - String accessToken = request.getHeader("X-Access-Token"); - String signStr = dictCode + SqlInjectionUtil.TABLE_DICT_SIGN_SALT + accessToken; - String javaSign = MD5(signStr.getBytes()); - if (!javaSign.equals(sign)) { - log.error("表字典,SQL注入漏洞签名校验失败 :" + sign + "!=" + javaSign+ ",dictCode=" + dictCode); - throw new RuntimeException("无权限访问!"); - } - log.info(" 表字典,SQL注入漏洞签名校验成功!sign=" + sign + ",dictCode=" + dictCode); - } + /* + * 针对表字典进行额外的sign签名校验(增加安全机制) + * @param dictCode: + * @param sign: + * @param request: + * @Return: void + */ + public static void checkDictTableSign(String dictCode, String sign, HttpServletRequest request) { + //表字典SQL注入漏洞,签名校验 + String accessToken = request.getHeader("X-Access-Token"); + String signStr = dictCode + SqlInjectionUtil.TABLE_DICT_SIGN_SALT + accessToken; + String javaSign = MD5(signStr.getBytes()); + if (!javaSign.equals(sign)) { + log.error("表字典,SQL注入漏洞签名校验失败 :" + sign + "!=" + javaSign + ",dictCode=" + dictCode); + throw new RuntimeException("无权限访问!"); + } + log.info(" 表字典,SQL注入漏洞签名校验成功!sign=" + sign + ",dictCode=" + dictCode); + } - /** 字节数组,计算MD5值 */ - public static String MD5(byte[] data) - { - try - { - // 获取data的MD5摘要 - MessageDigest digest = MessageDigest.getInstance("MD5"); - // mdInst.update(content.getBytes()); - digest.update(data); - byte[] array = digest.digest(); + /** + * 字节数组,计算MD5值 + */ + public static String MD5(byte[] data) { + try { + // 获取data的MD5摘要 + MessageDigest digest = MessageDigest.getInstance("MD5"); + // mdInst.update(content.getBytes()); + digest.update(data); + byte[] array = digest.digest(); - // 转换为十六进制的字符串形式 - StringBuffer buf = new StringBuffer(); - for (int i = 0; i < array.length; i++) - { - String shaHex = Integer.toHexString(array[i] & 0xFF); - if (shaHex.length() < 2) - { - buf.append(0); - } - buf.append(shaHex); - } - return buf.toString(); - } - catch (Exception e) - { - e.printStackTrace(); - return ""; - } - } - /** - * sql注入过滤处理,遇到注入关键字抛异常 - * - * @param value - * @return - */ - public static void filterContent(String value) { - if (value == null || "".equals(value)) { - return; - } - // 统一转为小写 - value = value.toLowerCase(); - String[] xssArr = xssStr.split("\\|"); - for (String s : xssArr) { - if (value.contains(s)) { - log.error("请注意,存在SQL注入关键词---> {}", s); - log.error("请注意,值可能存在SQL注入风险!---> {}", value); - throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value); - } - } - } + // 转换为十六进制的字符串形式 + StringBuffer buf = new StringBuffer(); + for (int i = 0; i < array.length; i++) { + String shaHex = Integer.toHexString(array[i] & 0xFF); + if (shaHex.length() < 2) { + buf.append(0); + } + buf.append(shaHex); + } + return buf.toString(); + } catch (Exception e) { + e.printStackTrace(); + return ""; + } + } - /** - * sql注入过滤处理,遇到注入关键字抛异常 - * - * @param values - * @return - */ - public static void filterContent(String[] values) { - String[] xssArr = xssStr.split("\\|"); - for (String value : values) { - if (value == null || "".equals(value)) { - return; - } - // 统一转为小写 - value = value.toLowerCase(); - for (String s : xssArr) { - if (value.contains(s)) { - log.error("请注意,存在SQL注入关键词---> {}", s); - log.error("请注意,值可能存在SQL注入风险!---> {}", value); - throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value); - } - } - } - } + /** + * sql注入过滤处理,遇到注入关键字抛异常 + * + * @param value + * @return + */ + public static void filterContent(String value) { + if (value == null || "".equals(value)) { + return; + } + // 统一转为小写 + value = value.toLowerCase(); + String[] xssArr = xssStr.split("\\|"); + for (String s : xssArr) { + if (value.contains(s)) { + log.error("请注意,存在SQL注入关键词---> {}", s); + log.error("请注意,值可能存在SQL注入风险!---> {}", value); + throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value); + } + } + } - /** - * @特殊方法(不通用) 仅用于字典条件SQL参数,注入过滤 - * @param value - * @return - */ + /** + * sql注入过滤处理,遇到注入关键字抛异常 + * + * @param values + * @return + */ + public static void filterContent(String[] values) { + String[] xssArr = xssStr.split("\\|"); + for (String value : values) { + if (value == null || "".equals(value)) { + return; + } + // 统一转为小写 + value = value.toLowerCase(); + for (String s : xssArr) { + if (value.contains(s)) { + log.error("请注意,存在SQL注入关键词---> {}", s); + log.error("请注意,值可能存在SQL注入风险!---> {}", value); + throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value); + } + } + } + } - public static void specialFilterContent(String value) { - String specialXssStr = " exec | insert | select | delete | update | drop | count | chr | mid | master | truncate | char | declare |;|+|"; - String[] xssArr = specialXssStr.split("\\|"); - if (value == null || "".equals(value)) { - return; - } - // 统一转为小写 - value = value.toLowerCase(); - for (String s : xssArr) { - if (value.contains(s) || value.startsWith(s.trim())) { - log.error("请注意,存在SQL注入关键词---> {}", s); - log.error("请注意,值可能存在SQL注入风险!---> {}", value); - throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value); - } - } - } + /** + * @param value + * @return + * @特殊方法(不通用) 仅用于字典条件SQL参数,注入过滤 + */ + + public static void specialFilterContent(String value) { + String specialXssStr = " exec | insert | select | delete | update | drop | count | chr | mid | master | truncate | char | declare |;|+|"; + String[] xssArr = specialXssStr.split("\\|"); + if (value == null || "".equals(value)) { + return; + } + // 统一转为小写 + value = value.toLowerCase(); + for (String s : xssArr) { + if (value.contains(s) || value.startsWith(s.trim())) { + log.error("请注意,存在SQL注入关键词---> {}", s); + log.error("请注意,值可能存在SQL注入风险!---> {}", value); + throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value); + } + } + } /** - * @特殊方法(不通用) 仅用于Online报表SQL解析,注入过滤 * @param value * @return + * @特殊方法(不通用) 仅用于Online报表SQL解析,注入过滤 */ - @Deprecated - public static void specialFilterContentForOnlineReport(String value) { - String specialXssStr = " exec | insert | delete | update | drop | chr | mid | master | truncate | char | declare |"; - String[] xssArr = specialXssStr.split("\\|"); - if (value == null || "".equals(value)) { - return; - } - // 统一转为小写 - value = value.toLowerCase(); - for (String s : xssArr) { - if (value.contains(s) || value.startsWith(s.trim())) { - log.error("请注意,存在SQL注入关键词---> {}", s); - log.error("请注意,值可能存在SQL注入风险!---> {}", value); - throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value); - } - } - } + @Deprecated + public static void specialFilterContentForOnlineReport(String value) { + String specialXssStr = " exec | insert | delete | update | drop | chr | mid | master | truncate | char | declare |"; + String[] xssArr = specialXssStr.split("\\|"); + if (value == null || "".equals(value)) { + return; + } + // 统一转为小写 + value = value.toLowerCase(); + for (String s : xssArr) { + if (value.contains(s) || value.startsWith(s.trim())) { + log.error("请注意,存在SQL注入关键词---> {}", s); + log.error("请注意,值可能存在SQL注入风险!---> {}", value); + throw new RuntimeException("请注意,值可能存在SQL注入风险!--->" + value); + } + } + } } diff --git a/pear-common/src/main/java/com/pearadmin/common/tools/datetime/DateUtil.java b/pear-common/src/main/java/com/pearadmin/common/tools/datetime/DateUtil.java index 026a06da1d209be51f26aa4e7643540d0e902ccf..27b80dbb80d8ef13f9b5b6e521996b8258623b67 100644 --- a/pear-common/src/main/java/com/pearadmin/common/tools/datetime/DateUtil.java +++ b/pear-common/src/main/java/com/pearadmin/common/tools/datetime/DateUtil.java @@ -1,6 +1,7 @@ package com.pearadmin.common.tools.datetime; import org.apache.commons.lang3.time.DateFormatUtils; + import java.lang.management.ManagementFactory; import java.text.ParseException; import java.text.SimpleDateFormat; @@ -8,11 +9,11 @@ import java.util.Date; /** * Describe: 日 期 工 具 类 - * Author: 就 眠 仪 式 + * + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ -public class DateUtil extends org.apache.commons.lang3.time.DateUtils -{ + */ +public class DateUtil extends org.apache.commons.lang3.time.DateUtils { public static String YYYY = "yyyy"; public static String YYYY_MM = "yyyy-MM"; @@ -22,58 +23,48 @@ public class DateUtil extends org.apache.commons.lang3.time.DateUtils public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss"; private static String[] parsePatterns = { - "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", + "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM", "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM", "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"}; /** * 获取当前Date型日期 - * + * * @return Date() 当前日期 */ - public static Date getNowDate() - { + public static Date getNowDate() { return new Date(); } /** * 获取当前日期, 默认格式为yyyy-MM-dd - * + * * @return String */ - public static String getDate() - { + public static String getDate() { return dateTimeNow(YYYY_MM_DD); } - public static final String getTime() - { + public static final String getTime() { return dateTimeNow(YYYY_MM_DD_HH_MM_SS); } - public static final String dateTimeNow(final String format) - { + public static final String dateTimeNow(final String format) { return parseDateToStr(format, new Date()); } - public static final String dateTime(final Date date) - { + public static final String dateTime(final Date date) { return parseDateToStr(YYYY_MM_DD, date); } - public static final String parseDateToStr(final String format, final Date date) - { + public static final String parseDateToStr(final String format, final Date date) { return new SimpleDateFormat(format).format(date); } - public static final Date dateTime(final String format, final String ts) - { - try - { + public static final Date dateTime(final String format, final String ts) { + try { return new SimpleDateFormat(format).parse(ts); - } - catch (ParseException e) - { + } catch (ParseException e) { throw new RuntimeException(e); } } @@ -81,8 +72,7 @@ public class DateUtil extends org.apache.commons.lang3.time.DateUtils /** * 日期路径 即年/月/日 如2018/08/08 */ - public static final String datePath() - { + public static final String datePath() { Date now = new Date(); return DateFormatUtils.format(now, "yyyy/MM/dd"); } @@ -90,8 +80,7 @@ public class DateUtil extends org.apache.commons.lang3.time.DateUtils /** * 日期路径 即年/月/日 如20180808 */ - public static final String dateTime() - { + public static final String dateTime() { Date now = new Date(); return DateFormatUtils.format(now, "yyyyMMdd"); } @@ -99,18 +88,13 @@ public class DateUtil extends org.apache.commons.lang3.time.DateUtils /** * 日期型字符串转化为日期 格式 */ - public static Date parseDate(Object str) - { - if (str == null) - { + public static Date parseDate(Object str) { + if (str == null) { return null; } - try - { + try { return parseDate(str.toString(), parsePatterns); - } - catch (ParseException e) - { + } catch (ParseException e) { return null; } } @@ -118,8 +102,7 @@ public class DateUtil extends org.apache.commons.lang3.time.DateUtils /** * 获取服务器启动时间 */ - public static Date getServerStartDate() - { + public static Date getServerStartDate() { long time = ManagementFactory.getRuntimeMXBean().getStartTime(); return new Date(time); } @@ -127,8 +110,7 @@ public class DateUtil extends org.apache.commons.lang3.time.DateUtils /** * 计算两个时间差 */ - public static String getDatePoor(Date endDate, Date nowDate) - { + public static String getDatePoor(Date endDate, Date nowDate) { long nd = 1000 * 24 * 60 * 60; long nh = 1000 * 60 * 60; long nm = 1000 * 60; diff --git a/pear-common/src/main/java/com/pearadmin/common/tools/jsoup/JsoupUtil.java b/pear-common/src/main/java/com/pearadmin/common/tools/jsoup/JsoupUtil.java index f8804895db0806f4da00f400055f745a06a63293..5d6125e2fb9cd40ac5b0d48f0595a3f6ad2c3cc6 100644 --- a/pear-common/src/main/java/com/pearadmin/common/tools/jsoup/JsoupUtil.java +++ b/pear-common/src/main/java/com/pearadmin/common/tools/jsoup/JsoupUtil.java @@ -5,6 +5,9 @@ import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.safety.Whitelist; +/** + * @author 就 眠 仪 式 + */ public class JsoupUtil { private static final Whitelist whitelist = Whitelist.basicWithImages(); diff --git a/pear-common/src/main/java/com/pearadmin/common/tools/secure/SecurityUtil.java b/pear-common/src/main/java/com/pearadmin/common/tools/secure/SecurityUtil.java index 0cad31ebe11534036d35492c774f6846e9b0b486..7f45ae0b0fbe04916d2e3e4b4729215176596a1d 100644 --- a/pear-common/src/main/java/com/pearadmin/common/tools/secure/SecurityUtil.java +++ b/pear-common/src/main/java/com/pearadmin/common/tools/secure/SecurityUtil.java @@ -6,16 +6,17 @@ import org.springframework.security.core.context.SecurityContextHolder; /** * Describe: Security 工 具 类 - * Author: 就 眠 仪 式 + * + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ + */ public class SecurityUtil { /** * 获取当前登录用户的信息 * return Authentication 权鉴对象 - * */ - public static Authentication currentUser(){ + */ + public static Authentication currentUser() { Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (!(authentication instanceof AnonymousAuthenticationToken)) { return authentication; @@ -25,9 +26,10 @@ public class SecurityUtil { /** * 验证当前用户是否登录 + * * @return boolean 是否登录 - * */ - public static boolean isAuthentication(){ + */ + public static boolean isAuthentication() { // if security session eq s-id is not null to index Authentication auth = SecurityContextHolder.getContext().getAuthentication(); return !(auth instanceof AnonymousAuthenticationToken); diff --git a/pear-common/src/main/java/com/pearadmin/common/tools/sequence/SequenceUtil.java b/pear-common/src/main/java/com/pearadmin/common/tools/sequence/SequenceUtil.java index 5ff3203695bf55b1f6f9badbaa19728ef2f2c51b..90267b56f5001cfaa3ecb2f93f72fe4ba122ae49 100644 --- a/pear-common/src/main/java/com/pearadmin/common/tools/sequence/SequenceUtil.java +++ b/pear-common/src/main/java/com/pearadmin/common/tools/sequence/SequenceUtil.java @@ -7,35 +7,47 @@ import java.util.Set; /** * Describe: Sequence 工具类 - * Author: 就 眠 仪 式 + * + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ + */ public class SequenceUtil { - /*** 机 器 Id */ - private static long workerId = 0; - /*** 数 据 中 心 */ - private static long centerId = 0; - /*** 毫 秒 内 序 列 */ - private static long sequence = 0L; - /*** 上 次 Id 生 成 的 时 间 戳 */ - private static long lastTimestamp = -1L; - /** 机 器 编 号 所 占 位 数 */ + /** + * 机 器 编 号 所 占 位 数 + */ private static final long workerIdBits = 5L; - /** 数 据 标 识 所 占 位 数 */ + /** + * 数 据 标 识 所 占 位 数 + */ private static final long centerIdBits = 5L; - /** 开 始 时 间 戳 */ + /** + * 开 始 时 间 戳 + */ private static final long poc = 1288834974657L; - /** 序 列 在 Id 中 所 占 的 位 数 */ + /** + * 序 列 在 Id 中 所 占 的 位 数 + */ private static final long sequenceBits = 12L; - /** 为 算 法 提 供 可 用 配 置 */ + /** + * 为 算 法 提 供 可 用 配 置 + */ private static final long workerIdShift = sequenceBits; private static final long maxWorkerId = ~(-1L << workerIdBits); private static final long maxCenterId = ~(-1L << centerIdBits); private static final long centerIdShift = sequenceBits + workerIdBits; private static final long timestampLeftShift = sequenceBits + workerIdBits + centerIdBits; private static final long sequenceMask = ~(-1L << sequenceBits); - public static synchronized long makeSequence() throws Exception{ + /*** 机 器 Id */ + private static long workerId = 0; + /*** 数 据 中 心 */ + private static long centerId = 0; + /*** 毫 秒 内 序 列 */ + private static long sequence = 0L; + /*** 上 次 Id 生 成 的 时 间 戳 */ + private static long lastTimestamp = -1L; + + public static synchronized long makeSequence() throws Exception { long timestamp = timeGen(); // 当 前 时 间 小 于 上 次 Id 生 成 时 间 ,说 明 系 统 时 钟 回 退, 应 会 抛 出 异 常 if (timestamp < lastTimestamp) { @@ -62,11 +74,11 @@ public class SequenceUtil { /** * 获 取 下 一 个 Id - * */ - public static long makeId(){ + */ + public static long makeId() { try { return makeSequence(); - }catch (Exception e){ + } catch (Exception e) { e.printStackTrace(); } return -1; @@ -74,34 +86,23 @@ public class SequenceUtil { /** * 获 取 下 一 个 Id ( String 类型 ) - * */ - public static String makeStringId(){ + */ + public static String makeStringId() { return "" + makeId(); } - public static List makeStringIds(int size){ + public static List makeStringIds(int size) { List ids = new ArrayList(); - for (int i = 0;i makeId(int initSize) throws Exception{ - Set ids = new HashSet(initSize); - for (long current = 0; current < initSize; current++){ - ids.add(makeId()); - } - return ids; - } - /** * 时 间 戳 比 对 - * */ + */ protected static long tilNextMillis(long lastTimestamp) { long timestamp = timeGen(); while (timestamp <= lastTimestamp) { @@ -112,9 +113,20 @@ public class SequenceUtil { /** * 当 前 系 统 时 间 毫 秒 - * */ + */ protected static long timeGen() { return System.currentTimeMillis(); } + + /** + * 根 据 一 定 数 量 的 Id + */ + public Set makeId(int initSize) throws Exception { + Set ids = new HashSet(initSize); + for (long current = 0; current < initSize; current++) { + ids.add(makeId()); + } + return ids; + } } diff --git a/pear-common/src/main/java/com/pearadmin/common/tools/servlet/ServletUtil.java b/pear-common/src/main/java/com/pearadmin/common/tools/servlet/ServletUtil.java index f62a3b8c71aae080317b0f67c9bc5b902cbf0f00..6683e5d8c06e4a7c674805503561a2cd9c2b67da 100644 --- a/pear-common/src/main/java/com/pearadmin/common/tools/servlet/ServletUtil.java +++ b/pear-common/src/main/java/com/pearadmin/common/tools/servlet/ServletUtil.java @@ -11,9 +11,10 @@ import java.io.IOException; /** * Describe: Servlet 工具类 - * Author: 就 眠 仪 式 + * + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ + */ public class ServletUtil { @@ -21,8 +22,8 @@ public class ServletUtil { * Describe: 获取 HttpServletRequest 对象 * Param null * Return HttpServletRequest - * */ - public static HttpServletRequest getRequest(){ + */ + public static HttpServletRequest getRequest() { ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); return servletRequestAttributes.getRequest(); } @@ -31,8 +32,8 @@ public class ServletUtil { * Describe: 获取 HttpServletResponse 对象 * Param null * Return HttpServletResponse - * */ - public static HttpServletResponse getResponse(){ + */ + public static HttpServletResponse getResponse() { ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); return servletRequestAttributes.getResponse(); } @@ -41,8 +42,8 @@ public class ServletUtil { * Describe: 获取 HttpServletSession 对象 * Param null * Return HttpServletSession - * */ - public static HttpSession getSession(){ + */ + public static HttpSession getSession() { ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); return servletRequestAttributes.getRequest().getSession(); } @@ -51,12 +52,12 @@ public class ServletUtil { * Describe: 判断是否为 Ajax 请求 * Param null * Return HttpServletSession - * */ - public static Boolean isAjax(HttpServletRequest request){ + */ + public static Boolean isAjax(HttpServletRequest request) { String requestType = request.getHeader("X-Requested-With"); - if("XMLHttpRequest".equals(requestType)){ + if ("XMLHttpRequest".equals(requestType)) { return true; - }else{ + } else { return false; } } @@ -65,90 +66,90 @@ public class ServletUtil { * Describe: Response 对象写出数据 * Param: msg 消息数据 * Return null - * */ - public static void write(String msg) throws IOException{ + */ + public static void write(String msg) throws IOException { HttpServletResponse response = getResponse(); - response.setHeader("Content-type","application/json;charset=UTF-8"); + response.setHeader("Content-type", "application/json;charset=UTF-8"); response.setCharacterEncoding(SystemConstant.UTF8); response.getWriter().write(msg); } /** * 获取查询参数 - * */ - public static String getQueryParam(){ + */ + public static String getQueryParam() { return getRequest().getQueryString(); } /** * 获取请求地址 - * */ + */ public static String getRequestURI() { return getRequest().getRequestURI(); } /** * 获取客户端地址 - * */ - public static String getRemoteHost(){ + */ + public static String getRemoteHost() { String remoteHost = getRequest().getRemoteHost(); - if(remoteHost.equals("0:0:0:0:0:0:0:1")){ + if (remoteHost.equals("0:0:0:0:0:0:0:1")) { remoteHost = "127.0.0.1"; } - return remoteHost ; + return remoteHost; } /** * 获取当前请求方法 - * */ - public static String getMethod(){ + */ + public static String getMethod() { return getRequest().getMethod(); } /** * 获取请求头 - * */ - public static String getHeader(String name){ + */ + public static String getHeader(String name) { return getRequest().getHeader(name); } /** * 获取 UserAgent - * */ - public static String getAgent(){ + */ + public static String getAgent() { return getHeader("User-Agent"); } /** * 获取浏览器类型 - * */ - public static String getBrowser(){ + */ + public static String getBrowser() { String userAgent = getAgent(); - if (userAgent.contains("Firefox")){ + if (userAgent.contains("Firefox")) { return "火狐浏览器"; - }else if (userAgent.contains("Chrome")){ + } else if (userAgent.contains("Chrome")) { return "谷歌浏览器"; - }else if (userAgent.contains("Trident")){ + } else if (userAgent.contains("Trident")) { return "IE 浏览器"; - }else{ + } else { return "你用啥浏览器"; } } /** * 获取浏览器类型 - * */ - public static String getSystem(){ + */ + public static String getSystem() { String userAgent = getAgent(); - if (userAgent.toLowerCase().contains("windows" )) { + if (userAgent.toLowerCase().contains("windows")) { return "Windows"; - } else if (userAgent.toLowerCase().contains("mac" )) { + } else if (userAgent.toLowerCase().contains("mac")) { return "Mac"; - } else if (userAgent.toLowerCase().contains("x11" )) { + } else if (userAgent.toLowerCase().contains("x11")) { return "Unix"; - } else if (userAgent.toLowerCase().contains("android" )) { + } else if (userAgent.toLowerCase().contains("android")) { return "Android"; - } else if (userAgent.toLowerCase().contains("iphone" )) { + } else if (userAgent.toLowerCase().contains("iphone")) { return "IPhone"; } else { return "UnKnown, More-Info: " + userAgent; diff --git a/pear-common/src/main/java/com/pearadmin/common/tools/spring/SpringUtil.java b/pear-common/src/main/java/com/pearadmin/common/tools/spring/SpringUtil.java index a0d7fe9c3385f523075f058f4dd82b0ff8fcd95e..05b0a5d69207ead1c33a4e1de2d5f72b6de3aee6 100644 --- a/pear-common/src/main/java/com/pearadmin/common/tools/spring/SpringUtil.java +++ b/pear-common/src/main/java/com/pearadmin/common/tools/spring/SpringUtil.java @@ -7,20 +7,15 @@ import org.springframework.stereotype.Component; /** * Describe: Spring 工 具 类 - * Author: 就 眠 仪 式 + * + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ + */ @Component public class SpringUtil implements ApplicationContextAware { public static ApplicationContext applicationContext; - @Override - public void setApplicationContext(ApplicationContext applicationContext) - throws BeansException { - SpringUtil.applicationContext = applicationContext; - } - public static Object getBean(String name) { return applicationContext.getBean(name); } @@ -41,4 +36,10 @@ public class SpringUtil implements ApplicationContextAware { return applicationContext.getType(name); } + @Override + public void setApplicationContext(ApplicationContext applicationContext) + throws BeansException { + SpringUtil.applicationContext = applicationContext; + } + } diff --git a/pear-common/src/main/java/com/pearadmin/common/tools/string/CharsetKit.java b/pear-common/src/main/java/com/pearadmin/common/tools/string/CharsetKit.java index c6dc22e0f9885caadb7bc76fe54c2de05503ec70..cd43663c1b728f6c297a2b733b7feb51e0c4bcd2 100644 --- a/pear-common/src/main/java/com/pearadmin/common/tools/string/CharsetKit.java +++ b/pear-common/src/main/java/com/pearadmin/common/tools/string/CharsetKit.java @@ -6,21 +6,34 @@ import java.nio.charset.StandardCharsets; /** * 字符集工具类 + * + * @author 就 眠 仪 式 */ -public class CharsetKit -{ - /** ISO-8859-1 */ +public class CharsetKit { + /** + * ISO-8859-1 + */ public static final String ISO_8859_1 = "ISO-8859-1"; - /** UTF-8 */ + /** + * UTF-8 + */ public static final String UTF_8 = "UTF-8"; - /** GBK */ + /** + * GBK + */ public static final String GBK = "GBK"; - /** ISO-8859-1 */ + /** + * ISO-8859-1 + */ public static final Charset CHARSET_ISO_8859_1 = StandardCharsets.ISO_8859_1; - /** UTF-8 */ + /** + * UTF-8 + */ public static final Charset CHARSET_UTF_8 = StandardCharsets.UTF_8; - /** GBK */ + /** + * GBK + */ public static final Charset CHARSET_GBK = Charset.forName(GBK); /** @@ -29,46 +42,40 @@ public class CharsetKit * @param charset 字符集,为空则返回默认字符集 * @return Charset */ - public static Charset charset(String charset) - { + public static Charset charset(String charset) { return StringUtil.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset); } /** * 转换字符串的字符集编码 * - * @param source 字符串 - * @param srcCharset 源字符集,默认ISO-8859-1 + * @param source 字符串 + * @param srcCharset 源字符集,默认ISO-8859-1 * @param destCharset 目标字符集,默认UTF-8 * @return 转换后的字符集 */ - public static String convert(String source, String srcCharset, String destCharset) - { + public static String convert(String source, String srcCharset, String destCharset) { return convert(source, Charset.forName(srcCharset), Charset.forName(destCharset)); } /** * 转换字符串的字符集编码 * - * @param source 字符串 - * @param srcCharset 源字符集,默认ISO-8859-1 + * @param source 字符串 + * @param srcCharset 源字符集,默认ISO-8859-1 * @param destCharset 目标字符集,默认UTF-8 * @return 转换后的字符集 */ - public static String convert(String source, Charset srcCharset, Charset destCharset) - { - if (null == srcCharset) - { + public static String convert(String source, Charset srcCharset, Charset destCharset) { + if (null == srcCharset) { srcCharset = StandardCharsets.ISO_8859_1; } - if (null == destCharset) - { + if (null == destCharset) { srcCharset = StandardCharsets.UTF_8; } - if (StringUtil.isEmpty(source) || srcCharset.equals(destCharset)) - { + if (StringUtil.isEmpty(source) || srcCharset.equals(destCharset)) { return source; } return new String(source.getBytes(srcCharset), destCharset); @@ -77,8 +84,7 @@ public class CharsetKit /** * @return 系统字符集编码 */ - public static String systemCharset() - { + public static String systemCharset() { return Charset.defaultCharset().name(); } } diff --git a/pear-common/src/main/java/com/pearadmin/common/tools/string/Convert.java b/pear-common/src/main/java/com/pearadmin/common/tools/string/Convert.java index 86ef4cf098b0c87126a6fc6a3a65f1ff43b56c2b..56138c5bc3d833e424dad1168644a7946f20186f 100644 --- a/pear-common/src/main/java/com/pearadmin/common/tools/string/Convert.java +++ b/pear-common/src/main/java/com/pearadmin/common/tools/string/Convert.java @@ -9,26 +9,24 @@ import java.util.Set; /** * 类型转换器 + * + * @author 就 眠 仪 式 */ -public class Convert -{ +public class Convert { /** * 转换为字符串
* 如果给定的值为null,或者转换失败,返回默认值
* 转换失败不会报错 * - * @param value 被转换的值 + * @param value 被转换的值 * @param defaultValue 转换错误时的默认值 * @return 结果 */ - public static String toStr(Object value, String defaultValue) - { - if (null == value) - { + public static String toStr(Object value, String defaultValue) { + if (null == value) { return defaultValue; } - if (value instanceof String) - { + if (value instanceof String) { return (String) value; } return value.toString(); @@ -42,8 +40,7 @@ public class Convert * @param value 被转换的值 * @return 结果 */ - public static String toStr(Object value) - { + public static String toStr(Object value) { return toStr(value, null); } @@ -52,18 +49,15 @@ public class Convert * 如果给定的值为null,或者转换失败,返回默认值
* 转换失败不会报错 * - * @param value 被转换的值 + * @param value 被转换的值 * @param defaultValue 转换错误时的默认值 * @return 结果 */ - public static Character toChar(Object value, Character defaultValue) - { - if (null == value) - { + public static Character toChar(Object value, Character defaultValue) { + if (null == value) { return defaultValue; } - if (value instanceof Character) - { + if (value instanceof Character) { return (Character) value; } @@ -79,8 +73,7 @@ public class Convert * @param value 被转换的值 * @return 结果 */ - public static Character toChar(Object value) - { + public static Character toChar(Object value) { return toChar(value, null); } @@ -89,35 +82,27 @@ public class Convert * 如果给定的值为null,或者转换失败,返回默认值
* 转换失败不会报错 * - * @param value 被转换的值 + * @param value 被转换的值 * @param defaultValue 转换错误时的默认值 * @return 结果 */ - public static Byte toByte(Object value, Byte defaultValue) - { - if (value == null) - { + public static Byte toByte(Object value, Byte defaultValue) { + if (value == null) { return defaultValue; } - if (value instanceof Byte) - { + if (value instanceof Byte) { return (Byte) value; } - if (value instanceof Number) - { + if (value instanceof Number) { return ((Number) value).byteValue(); } final String valueStr = toStr(value, null); - if (StringUtil.isEmpty(valueStr)) - { + if (StringUtil.isEmpty(valueStr)) { return defaultValue; } - try - { + try { return Byte.parseByte(valueStr); - } - catch (Exception e) - { + } catch (Exception e) { return defaultValue; } } @@ -130,8 +115,7 @@ public class Convert * @param value 被转换的值 * @return 结果 */ - public static Byte toByte(Object value) - { + public static Byte toByte(Object value) { return toByte(value, null); } @@ -140,35 +124,27 @@ public class Convert * 如果给定的值为null,或者转换失败,返回默认值
* 转换失败不会报错 * - * @param value 被转换的值 + * @param value 被转换的值 * @param defaultValue 转换错误时的默认值 * @return 结果 */ - public static Short toShort(Object value, Short defaultValue) - { - if (value == null) - { + public static Short toShort(Object value, Short defaultValue) { + if (value == null) { return defaultValue; } - if (value instanceof Short) - { + if (value instanceof Short) { return (Short) value; } - if (value instanceof Number) - { + if (value instanceof Number) { return ((Number) value).shortValue(); } final String valueStr = toStr(value, null); - if (StringUtil.isEmpty(valueStr)) - { + if (StringUtil.isEmpty(valueStr)) { return defaultValue; } - try - { + try { return Short.parseShort(valueStr.trim()); - } - catch (Exception e) - { + } catch (Exception e) { return defaultValue; } } @@ -181,8 +157,7 @@ public class Convert * @param value 被转换的值 * @return 结果 */ - public static Short toShort(Object value) - { + public static Short toShort(Object value) { return toShort(value, null); } @@ -191,31 +166,24 @@ public class Convert * 如果给定的值为空,或者转换失败,返回默认值
* 转换失败不会报错 * - * @param value 被转换的值 + * @param value 被转换的值 * @param defaultValue 转换错误时的默认值 * @return 结果 */ - public static Number toNumber(Object value, Number defaultValue) - { - if (value == null) - { + public static Number toNumber(Object value, Number defaultValue) { + if (value == null) { return defaultValue; } - if (value instanceof Number) - { + if (value instanceof Number) { return (Number) value; } final String valueStr = toStr(value, null); - if (StringUtil.isEmpty(valueStr)) - { + if (StringUtil.isEmpty(valueStr)) { return defaultValue; } - try - { + try { return NumberFormat.getInstance().parse(valueStr); - } - catch (Exception e) - { + } catch (Exception e) { return defaultValue; } } @@ -228,8 +196,7 @@ public class Convert * @param value 被转换的值 * @return 结果 */ - public static Number toNumber(Object value) - { + public static Number toNumber(Object value) { return toNumber(value, null); } @@ -238,35 +205,27 @@ public class Convert * 如果给定的值为空,或者转换失败,返回默认值
* 转换失败不会报错 * - * @param value 被转换的值 + * @param value 被转换的值 * @param defaultValue 转换错误时的默认值 * @return 结果 */ - public static Integer toInt(Object value, Integer defaultValue) - { - if (value == null) - { + public static Integer toInt(Object value, Integer defaultValue) { + if (value == null) { return defaultValue; } - if (value instanceof Integer) - { + if (value instanceof Integer) { return (Integer) value; } - if (value instanceof Number) - { + if (value instanceof Number) { return ((Number) value).intValue(); } final String valueStr = toStr(value, null); - if (StringUtil.isEmpty(valueStr)) - { + if (StringUtil.isEmpty(valueStr)) { return defaultValue; } - try - { + try { return Integer.parseInt(valueStr.trim()); - } - catch (Exception e) - { + } catch (Exception e) { return defaultValue; } } @@ -279,8 +238,7 @@ public class Convert * @param value 被转换的值 * @return 结果 */ - public static Integer toInt(Object value) - { + public static Integer toInt(Object value) { return toInt(value, null); } @@ -290,8 +248,7 @@ public class Convert * @param str 被转换的值 * @return 结果 */ - public static Integer[] toIntArray(String str) - { + public static Integer[] toIntArray(String str) { return toIntArray(",", str); } @@ -301,8 +258,7 @@ public class Convert * @param str 被转换的值 * @return 结果 */ - public static Long[] toLongArray(String str) - { + public static Long[] toLongArray(String str) { return toLongArray(",", str); } @@ -313,16 +269,13 @@ public class Convert * @param split 被转换的值 * @return 结果 */ - public static Integer[] toIntArray(String split, String str) - { - if (StringUtil.isEmpty(str)) - { - return new Integer[] {}; + public static Integer[] toIntArray(String split, String str) { + if (StringUtil.isEmpty(str)) { + return new Integer[]{}; } String[] arr = str.split(split); final Integer[] ints = new Integer[arr.length]; - for (int i = 0; i < arr.length; i++) - { + for (int i = 0; i < arr.length; i++) { final Integer v = toInt(arr[i], 0); ints[i] = v; } @@ -333,19 +286,16 @@ public class Convert * 转换为Long数组
* * @param split 分隔符 - * @param str 被转换的值 + * @param str 被转换的值 * @return 结果 */ - public static Long[] toLongArray(String split, String str) - { - if (StringUtil.isEmpty(str)) - { - return new Long[] {}; + public static Long[] toLongArray(String split, String str) { + if (StringUtil.isEmpty(str)) { + return new Long[]{}; } String[] arr = str.split(split); final Long[] longs = new Long[arr.length]; - for (int i = 0; i < arr.length; i++) - { + for (int i = 0; i < arr.length; i++) { final Long v = toLong(arr[i], null); longs[i] = v; } @@ -358,8 +308,7 @@ public class Convert * @param str 被转换的值 * @return 结果 */ - public static String[] toStrArray(String str) - { + public static String[] toStrArray(String str) { return toStrArray(",", str); } @@ -370,8 +319,7 @@ public class Convert * @param split 被转换的值 * @return 结果 */ - public static String[] toStrArray(String split, String str) - { + public static String[] toStrArray(String split, String str) { return str.split(split); } @@ -380,36 +328,28 @@ public class Convert * 如果给定的值为空,或者转换失败,返回默认值
* 转换失败不会报错 * - * @param value 被转换的值 + * @param value 被转换的值 * @param defaultValue 转换错误时的默认值 * @return 结果 */ - public static Long toLong(Object value, Long defaultValue) - { - if (value == null) - { + public static Long toLong(Object value, Long defaultValue) { + if (value == null) { return defaultValue; } - if (value instanceof Long) - { + if (value instanceof Long) { return (Long) value; } - if (value instanceof Number) - { + if (value instanceof Number) { return ((Number) value).longValue(); } final String valueStr = toStr(value, null); - if (StringUtil.isEmpty(valueStr)) - { + if (StringUtil.isEmpty(valueStr)) { return defaultValue; } - try - { + try { // 支持科学计数法 return new BigDecimal(valueStr.trim()).longValue(); - } - catch (Exception e) - { + } catch (Exception e) { return defaultValue; } } @@ -422,8 +362,7 @@ public class Convert * @param value 被转换的值 * @return 结果 */ - public static Long toLong(Object value) - { + public static Long toLong(Object value) { return toLong(value, null); } @@ -432,36 +371,28 @@ public class Convert * 如果给定的值为空,或者转换失败,返回默认值
* 转换失败不会报错 * - * @param value 被转换的值 + * @param value 被转换的值 * @param defaultValue 转换错误时的默认值 * @return 结果 */ - public static Double toDouble(Object value, Double defaultValue) - { - if (value == null) - { + public static Double toDouble(Object value, Double defaultValue) { + if (value == null) { return defaultValue; } - if (value instanceof Double) - { + if (value instanceof Double) { return (Double) value; } - if (value instanceof Number) - { + if (value instanceof Number) { return ((Number) value).doubleValue(); } final String valueStr = toStr(value, null); - if (StringUtil.isEmpty(valueStr)) - { + if (StringUtil.isEmpty(valueStr)) { return defaultValue; } - try - { + try { // 支持科学计数法 return new BigDecimal(valueStr.trim()).doubleValue(); - } - catch (Exception e) - { + } catch (Exception e) { return defaultValue; } } @@ -474,8 +405,7 @@ public class Convert * @param value 被转换的值 * @return 结果 */ - public static Double toDouble(Object value) - { + public static Double toDouble(Object value) { return toDouble(value, null); } @@ -484,35 +414,27 @@ public class Convert * 如果给定的值为空,或者转换失败,返回默认值
* 转换失败不会报错 * - * @param value 被转换的值 + * @param value 被转换的值 * @param defaultValue 转换错误时的默认值 * @return 结果 */ - public static Float toFloat(Object value, Float defaultValue) - { - if (value == null) - { + public static Float toFloat(Object value, Float defaultValue) { + if (value == null) { return defaultValue; } - if (value instanceof Float) - { + if (value instanceof Float) { return (Float) value; } - if (value instanceof Number) - { + if (value instanceof Number) { return ((Number) value).floatValue(); } final String valueStr = toStr(value, null); - if (StringUtil.isEmpty(valueStr)) - { + if (StringUtil.isEmpty(valueStr)) { return defaultValue; } - try - { + try { return Float.parseFloat(valueStr.trim()); - } - catch (Exception e) - { + } catch (Exception e) { return defaultValue; } } @@ -525,8 +447,7 @@ public class Convert * @param value 被转换的值 * @return 结果 */ - public static Float toFloat(Object value) - { + public static Float toFloat(Object value) { return toFloat(value, null); } @@ -535,28 +456,23 @@ public class Convert * String支持的值为:true、false、yes、ok、no,1,0 如果给定的值为空,或者转换失败,返回默认值
* 转换失败不会报错 * - * @param value 被转换的值 + * @param value 被转换的值 * @param defaultValue 转换错误时的默认值 * @return 结果 */ - public static Boolean toBool(Object value, Boolean defaultValue) - { - if (value == null) - { + public static Boolean toBool(Object value, Boolean defaultValue) { + if (value == null) { return defaultValue; } - if (value instanceof Boolean) - { + if (value instanceof Boolean) { return (Boolean) value; } String valueStr = toStr(value, null); - if (StringUtil.isEmpty(valueStr)) - { + if (StringUtil.isEmpty(valueStr)) { return defaultValue; } valueStr = valueStr.trim().toLowerCase(); - switch (valueStr) - { + switch (valueStr) { case "true": return true; case "false": @@ -584,8 +500,7 @@ public class Convert * @param value 被转换的值 * @return 结果 */ - public static Boolean toBool(Object value) - { + public static Boolean toBool(Object value) { return toBool(value, null); } @@ -593,34 +508,27 @@ public class Convert * 转换为Enum对象
* 如果给定的值为空,或者转换失败,返回默认值
* - * @param clazz Enum的Class - * @param value 值 + * @param clazz Enum的Class + * @param value 值 * @param defaultValue 默认值 * @return Enum */ - public static > E toEnum(Class clazz, Object value, E defaultValue) - { - if (value == null) - { + public static > E toEnum(Class clazz, Object value, E defaultValue) { + if (value == null) { return defaultValue; } - if (clazz.isAssignableFrom(value.getClass())) - { + if (clazz.isAssignableFrom(value.getClass())) { @SuppressWarnings("unchecked") E myE = (E) value; return myE; } final String valueStr = toStr(value, null); - if (StringUtil.isEmpty(valueStr)) - { + if (StringUtil.isEmpty(valueStr)) { return defaultValue; } - try - { + try { return Enum.valueOf(clazz, valueStr); - } - catch (Exception e) - { + } catch (Exception e) { return defaultValue; } } @@ -633,8 +541,7 @@ public class Convert * @param value 值 * @return Enum */ - public static > E toEnum(Class clazz, Object value) - { + public static > E toEnum(Class clazz, Object value) { return toEnum(clazz, value, null); } @@ -643,35 +550,27 @@ public class Convert * 如果给定的值为空,或者转换失败,返回默认值
* 转换失败不会报错 * - * @param value 被转换的值 + * @param value 被转换的值 * @param defaultValue 转换错误时的默认值 * @return 结果 */ - public static BigInteger toBigInteger(Object value, BigInteger defaultValue) - { - if (value == null) - { + public static BigInteger toBigInteger(Object value, BigInteger defaultValue) { + if (value == null) { return defaultValue; } - if (value instanceof BigInteger) - { + if (value instanceof BigInteger) { return (BigInteger) value; } - if (value instanceof Long) - { + if (value instanceof Long) { return BigInteger.valueOf((Long) value); } final String valueStr = toStr(value, null); - if (StringUtil.isEmpty(valueStr)) - { + if (StringUtil.isEmpty(valueStr)) { return defaultValue; } - try - { + try { return new BigInteger(valueStr); - } - catch (Exception e) - { + } catch (Exception e) { return defaultValue; } } @@ -684,8 +583,7 @@ public class Convert * @param value 被转换的值 * @return 结果 */ - public static BigInteger toBigInteger(Object value) - { + public static BigInteger toBigInteger(Object value) { return toBigInteger(value, null); } @@ -694,43 +592,33 @@ public class Convert * 如果给定的值为空,或者转换失败,返回默认值
* 转换失败不会报错 * - * @param value 被转换的值 + * @param value 被转换的值 * @param defaultValue 转换错误时的默认值 * @return 结果 */ - public static BigDecimal toBigDecimal(Object value, BigDecimal defaultValue) - { - if (value == null) - { + public static BigDecimal toBigDecimal(Object value, BigDecimal defaultValue) { + if (value == null) { return defaultValue; } - if (value instanceof BigDecimal) - { + if (value instanceof BigDecimal) { return (BigDecimal) value; } - if (value instanceof Long) - { + if (value instanceof Long) { return new BigDecimal((Long) value); } - if (value instanceof Double) - { + if (value instanceof Double) { return BigDecimal.valueOf((Double) value); } - if (value instanceof Integer) - { + if (value instanceof Integer) { return new BigDecimal((Integer) value); } final String valueStr = toStr(value, null); - if (StringUtil.isEmpty(valueStr)) - { + if (StringUtil.isEmpty(valueStr)) { return defaultValue; } - try - { + try { return new BigDecimal(valueStr); - } - catch (Exception e) - { + } catch (Exception e) { return defaultValue; } } @@ -743,8 +631,7 @@ public class Convert * @param value 被转换的值 * @return 结果 */ - public static BigDecimal toBigDecimal(Object value) - { + public static BigDecimal toBigDecimal(Object value) { return toBigDecimal(value, null); } @@ -755,8 +642,7 @@ public class Convert * @param obj 对象 * @return 字符串 */ - public static String utf8Str(Object obj) - { + public static String utf8Str(Object obj) { return str(obj, CharsetKit.CHARSET_UTF_8); } @@ -764,12 +650,11 @@ public class Convert * 将对象转为字符串
* 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 * - * @param obj 对象 + * @param obj 对象 * @param charsetName 字符集 * @return 字符串 */ - public static String str(Object obj, String charsetName) - { + public static String str(Object obj, String charsetName) { return str(obj, Charset.forName(charsetName)); } @@ -777,27 +662,20 @@ public class Convert * 将对象转为字符串
* 1、Byte数组和ByteBuffer会被转换为对应字符串的数组 2、对象数组会调用Arrays.toString方法 * - * @param obj 对象 + * @param obj 对象 * @param charset 字符集 * @return 字符串 */ - public static String str(Object obj, Charset charset) - { - if (null == obj) - { + public static String str(Object obj, Charset charset) { + if (null == obj) { return null; } - if (obj instanceof String) - { + if (obj instanceof String) { return (String) obj; - } - else if (obj instanceof byte[] || obj instanceof Byte[]) - { + } else if (obj instanceof byte[] || obj instanceof Byte[]) { return str((Byte[]) obj, charset); - } - else if (obj instanceof ByteBuffer) - { + } else if (obj instanceof ByteBuffer) { return str((ByteBuffer) obj, charset); } return obj.toString(); @@ -806,31 +684,27 @@ public class Convert /** * 将byte数组转为字符串 * - * @param bytes byte数组 + * @param bytes byte数组 * @param charset 字符集 * @return 字符串 */ - public static String str(byte[] bytes, String charset) - { + public static String str(byte[] bytes, String charset) { return str(bytes, StringUtil.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset)); } /** * 解码字节码 * - * @param data 字符串 + * @param data 字符串 * @param charset 字符集,如果此字段为空,则解码的结果取决于平台 * @return 解码后的字符串 */ - public static String str(byte[] data, Charset charset) - { - if (data == null) - { + public static String str(byte[] data, Charset charset) { + if (data == null) { return null; } - if (null == charset) - { + if (null == charset) { return new String(data); } return new String(data, charset); @@ -839,14 +713,12 @@ public class Convert /** * 将编码的byteBuffer数据转换为字符串 * - * @param data 数据 + * @param data 数据 * @param charset 字符集,如果为空使用当前系统字符集 * @return 字符串 */ - public static String str(ByteBuffer data, String charset) - { - if (data == null) - { + public static String str(ByteBuffer data, String charset) { + if (data == null) { return null; } @@ -856,55 +728,47 @@ public class Convert /** * 将编码的byteBuffer数据转换为字符串 * - * @param data 数据 + * @param data 数据 * @param charset 字符集,如果为空使用当前系统字符集 * @return 字符串 */ - public static String str(ByteBuffer data, Charset charset) - { - if (null == charset) - { + public static String str(ByteBuffer data, Charset charset) { + if (null == charset) { charset = Charset.defaultCharset(); } return charset.decode(data).toString(); } // ----------------------------------------------------------------------- 全角半角转换 + /** * 半角转全角 * * @param input String. * @return 全角字符串. */ - public static String toSBC(String input) - { + public static String toSBC(String input) { return toSBC(input, null); } /** * 半角转全角 * - * @param input String + * @param input String * @param notConvertSet 不替换的字符集合 * @return 全角字符串. */ - public static String toSBC(String input, Set notConvertSet) - { + public static String toSBC(String input, Set notConvertSet) { char c[] = input.toCharArray(); - for (int i = 0; i < c.length; i++) - { - if (null != notConvertSet && notConvertSet.contains(c[i])) - { + for (int i = 0; i < c.length; i++) { + if (null != notConvertSet && notConvertSet.contains(c[i])) { // 跳过不替换的字符 continue; } - if (c[i] == ' ') - { + if (c[i] == ' ') { c[i] = '\u3000'; - } - else if (c[i] < '\177') - { + } else if (c[i] < '\177') { c[i] = (char) (c[i] + 65248); } @@ -918,35 +782,28 @@ public class Convert * @param input String. * @return 半角字符串 */ - public static String toDBC(String input) - { + public static String toDBC(String input) { return toDBC(input, null); } /** * 替换全角为半角 * - * @param text 文本 + * @param text 文本 * @param notConvertSet 不替换的字符集合 * @return 替换后的字符 */ - public static String toDBC(String text, Set notConvertSet) - { + public static String toDBC(String text, Set notConvertSet) { char c[] = text.toCharArray(); - for (int i = 0; i < c.length; i++) - { - if (null != notConvertSet && notConvertSet.contains(c[i])) - { + for (int i = 0; i < c.length; i++) { + if (null != notConvertSet && notConvertSet.contains(c[i])) { // 跳过不替换的字符 continue; } - if (c[i] == '\u3000') - { + if (c[i] == '\u3000') { c[i] = ' '; - } - else if (c[i] > '\uFF00' && c[i] < '\uFF5F') - { + } else if (c[i] > '\uFF00' && c[i] < '\uFF5F') { c[i] = (char) (c[i] - 65248); } } @@ -960,31 +817,26 @@ public class Convert * @param n 数字 * @return 中文大写数字 */ - public static String digitUppercase(double n) - { - String[] fraction = { "角", "分" }; - String[] digit = { "零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖" }; - String[][] unit = { { "元", "万", "亿" }, { "", "拾", "佰", "仟" } }; + public static String digitUppercase(double n) { + String[] fraction = {"角", "分"}; + String[] digit = {"零", "壹", "贰", "叁", "肆", "伍", "陆", "柒", "捌", "玖"}; + String[][] unit = {{"元", "万", "亿"}, {"", "拾", "佰", "仟"}}; String head = n < 0 ? "负" : ""; n = Math.abs(n); StringBuilder s = new StringBuilder(); - for (int i = 0; i < fraction.length; i++) - { + for (int i = 0; i < fraction.length; i++) { s.append((digit[(int) (Math.floor(n * 10 * Math.pow(10, i)) % 10)] + fraction[i]).replaceAll("(零.)+", "")); } - if (s.length() < 1) - { + if (s.length() < 1) { s = new StringBuilder("整"); } int integerPart = (int) Math.floor(n); - for (int i = 0; i < unit[0].length && integerPart > 0; i++) - { + for (int i = 0; i < unit[0].length && integerPart > 0; i++) { StringBuilder p = new StringBuilder(); - for (int j = 0; j < unit[1].length && n > 0; j++) - { + for (int j = 0; j < unit[1].length && n > 0; j++) { p.insert(0, digit[integerPart % 10] + unit[1][j]); integerPart = integerPart / 10; } diff --git a/pear-common/src/main/java/com/pearadmin/common/tools/string/StrFormatter.java b/pear-common/src/main/java/com/pearadmin/common/tools/string/StrFormatter.java index 0880204dfbba9c2767a508d37ae9a188ffbb0f5e..4efd98c06378fc30dc13e7b4bce6489dd92bda45 100644 --- a/pear-common/src/main/java/com/pearadmin/common/tools/string/StrFormatter.java +++ b/pear-common/src/main/java/com/pearadmin/common/tools/string/StrFormatter.java @@ -4,8 +4,7 @@ package com.pearadmin.common.tools.string; /** * 字符串格式化 */ -public class StrFormatter -{ +public class StrFormatter { public static final String EMPTY_JSON = "{}"; public static final char C_BACKSLASH = '\\'; public static final char C_DELIM_START = '{'; @@ -19,15 +18,13 @@ public class StrFormatter * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b
* 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a
* 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b
- * + * * @param strPattern 字符串模板 - * @param argArray 参数列表 + * @param argArray 参数列表 * @return 结果 */ - public static String format(final String strPattern, final Object... argArray) - { - if (StringUtil.isEmpty(strPattern) || StringUtil.isEmpty(argArray)) - { + public static String format(final String strPattern, final Object... argArray) { + if (StringUtil.isEmpty(strPattern) || StringUtil.isEmpty(argArray)) { return strPattern; } final int strPatternLength = strPattern.length(); @@ -37,43 +34,30 @@ public class StrFormatter int handledPosition = 0; int delimIndex;// 占位符所在位置 - for (int argIndex = 0; argIndex < argArray.length; argIndex++) - { + for (int argIndex = 0; argIndex < argArray.length; argIndex++) { delimIndex = strPattern.indexOf(EMPTY_JSON, handledPosition); - if (delimIndex == -1) - { - if (handledPosition == 0) - { + if (delimIndex == -1) { + if (handledPosition == 0) { return strPattern; - } - else - { // 字符串模板剩余部分不再包含占位符,加入剩余部分后返回结果 + } else { // 字符串模板剩余部分不再包含占位符,加入剩余部分后返回结果 sbuf.append(strPattern, handledPosition, strPatternLength); return sbuf.toString(); } - } - else - { - if (delimIndex > 0 && strPattern.charAt(delimIndex - 1) == C_BACKSLASH) - { - if (delimIndex > 1 && strPattern.charAt(delimIndex - 2) == C_BACKSLASH) - { + } else { + if (delimIndex > 0 && strPattern.charAt(delimIndex - 1) == C_BACKSLASH) { + if (delimIndex > 1 && strPattern.charAt(delimIndex - 2) == C_BACKSLASH) { // 转义符之前还有一个转义符,占位符依旧有效 sbuf.append(strPattern, handledPosition, delimIndex - 1); sbuf.append(Convert.utf8Str(argArray[argIndex])); handledPosition = delimIndex + 2; - } - else - { + } else { // 占位符被转义 argIndex--; sbuf.append(strPattern, handledPosition, delimIndex - 1); sbuf.append(C_DELIM_START); handledPosition = delimIndex + 1; } - } - else - { + } else { // 正常占位符 sbuf.append(strPattern, handledPosition, delimIndex); sbuf.append(Convert.utf8Str(argArray[argIndex])); diff --git a/pear-common/src/main/java/com/pearadmin/common/tools/string/StringUtil.java b/pear-common/src/main/java/com/pearadmin/common/tools/string/StringUtil.java index 5af29bcd5d1572508394b8b466d13dc5e4a5be33..76b2c2fd3c76c8a7dc8c2497741049f4b80e0505 100644 --- a/pear-common/src/main/java/com/pearadmin/common/tools/string/StringUtil.java +++ b/pear-common/src/main/java/com/pearadmin/common/tools/string/StringUtil.java @@ -7,179 +7,164 @@ import java.util.Map; /** * 字符串工具类 */ -public class StringUtil extends org.apache.commons.lang3.StringUtils -{ - /** 空字符串 */ +public class StringUtil extends org.apache.commons.lang3.StringUtils { + /** + * 空字符串 + */ private static final String NULLSTR = ""; - /** 下划线 */ + /** + * 下划线 + */ private static final char SEPARATOR = '_'; /** * 获取参数不为空值 - * + * * @param value defaultValue 要判断的value * @return value 返回值 */ - public static T nvl(T value, T defaultValue) - { + public static T nvl(T value, T defaultValue) { return value != null ? value : defaultValue; } /** * * 判断一个Collection是否为空, 包含List,Set,Queue - * + * * @param coll 要判断的Collection * @return true:为空 false:非空 */ - public static boolean isEmpty(Collection coll) - { + public static boolean isEmpty(Collection coll) { return isNull(coll) || coll.isEmpty(); } /** * * 判断一个Collection是否非空,包含List,Set,Queue - * + * * @param coll 要判断的Collection * @return true:非空 false:空 */ - public static boolean isNotEmpty(Collection coll) - { + public static boolean isNotEmpty(Collection coll) { return !isEmpty(coll); } /** * * 判断一个对象数组是否为空 - * + * * @param objects 要判断的对象数组 - ** @return true:为空 false:非空 + * * @return true:为空 false:非空 */ - public static boolean isEmpty(Object[] objects) - { + public static boolean isEmpty(Object[] objects) { return isNull(objects) || (objects.length == 0); } /** * * 判断一个对象数组是否非空 - * + * * @param objects 要判断的对象数组 * @return true:非空 false:空 */ - public static boolean isNotEmpty(Object[] objects) - { + public static boolean isNotEmpty(Object[] objects) { return !isEmpty(objects); } /** * * 判断一个Map是否为空 - * + * * @param map 要判断的Map * @return true:为空 false:非空 */ - public static boolean isEmpty(Map map) - { + public static boolean isEmpty(Map map) { return isNull(map) || map.isEmpty(); } /** * * 判断一个Map是否为空 - * + * * @param map 要判断的Map * @return true:非空 false:空 */ - public static boolean isNotEmpty(Map map) - { + public static boolean isNotEmpty(Map map) { return !isEmpty(map); } /** * * 判断一个字符串是否为空串 - * + * * @param str String * @return true:为空 false:非空 */ - public static boolean isEmpty(String str) - { + public static boolean isEmpty(String str) { return isNull(str) || NULLSTR.equals(str.trim()); } /** * * 判断一个字符串是否为非空串 - * + * * @param str String * @return true:非空串 false:空串 */ - public static boolean isNotEmpty(String str) - { + public static boolean isNotEmpty(String str) { return !isEmpty(str); } /** * * 判断一个对象是否为空 - * + * * @param object Object * @return true:为空 false:非空 */ - public static boolean isNull(Object object) - { + public static boolean isNull(Object object) { return object == null; } /** * * 判断一个对象是否非空 - * + * * @param object Object * @return true:非空 false:空 */ - public static boolean isNotNull(Object object) - { + public static boolean isNotNull(Object object) { return !isNull(object); } /** * * 判断一个对象是否是数组类型(Java基本型别的数组) - * + * * @param object 对象 * @return true:是数组 false:不是数组 */ - public static boolean isArray(Object object) - { + public static boolean isArray(Object object) { return isNotNull(object) && object.getClass().isArray(); } /** * 去空格 */ - public static String trim(String str) - { + public static String trim(String str) { return (str == null ? "" : str.trim()); } /** * 截取字符串 - * - * @param str 字符串 + * + * @param str 字符串 * @param start 开始 * @return 结果 */ - public static String substring(final String str, int start) - { - if (str == null) - { + public static String substring(final String str, int start) { + if (str == null) { return NULLSTR; } - if (start < 0) - { + if (start < 0) { start = str.length() + start; } - if (start < 0) - { + if (start < 0) { start = 0; } - if (start > str.length()) - { + if (start > str.length()) { return NULLSTR; } @@ -188,44 +173,36 @@ public class StringUtil extends org.apache.commons.lang3.StringUtils /** * 截取字符串 - * - * @param str 字符串 + * + * @param str 字符串 * @param start 开始 - * @param end 结束 + * @param end 结束 * @return 结果 */ - public static String substring(final String str, int start, int end) - { - if (str == null) - { + public static String substring(final String str, int start, int end) { + if (str == null) { return NULLSTR; } - if (end < 0) - { + if (end < 0) { end = str.length() + end; } - if (start < 0) - { + if (start < 0) { start = str.length() + start; } - if (end > str.length()) - { + if (end > str.length()) { end = str.length(); } - if (start > end) - { + if (start > end) { return NULLSTR; } - if (start < 0) - { + if (start < 0) { start = 0; } - if (end < 0) - { + if (end < 0) { end = 0; } @@ -240,15 +217,13 @@ public class StringUtil extends org.apache.commons.lang3.StringUtils * 通常使用:format("this is {} for {}", "a", "b") -> this is a for b
* 转义{}: format("this is \\{} for {}", "a", "b") -> this is \{} for a
* 转义\: format("this is \\\\{} for {}", "a", "b") -> this is \a for b
- * + * * @param template 文本模板,被替换的部分用 {} 表示 - * @param params 参数值 + * @param params 参数值 * @return 格式化后的文本 */ - public static String format(String template, Object... params) - { - if (isEmpty(params) || isEmpty(template)) - { + public static String format(String template, Object... params) { + if (isEmpty(params) || isEmpty(template)) { return template; } return StrFormatter.format(template, params); @@ -257,10 +232,8 @@ public class StringUtil extends org.apache.commons.lang3.StringUtils /** * 下划线转驼峰命名 */ - public static String toUnderScoreCase(String str) - { - if (str == null) - { + public static String toUnderScoreCase(String str) { + if (str == null) { return null; } StringBuilder sb = new StringBuilder(); @@ -270,31 +243,23 @@ public class StringUtil extends org.apache.commons.lang3.StringUtils boolean curreCharIsUpperCase = true; // 下一字符是否大写 boolean nexteCharIsUpperCase = true; - for (int i = 0; i < str.length(); i++) - { + for (int i = 0; i < str.length(); i++) { char c = str.charAt(i); - if (i > 0) - { + if (i > 0) { preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1)); - } - else - { + } else { preCharIsUpperCase = false; } curreCharIsUpperCase = Character.isUpperCase(c); - if (i < (str.length() - 1)) - { + if (i < (str.length() - 1)) { nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1)); } - if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase) - { + if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase) { sb.append(SEPARATOR); - } - else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase) - { + } else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase) { sb.append(SEPARATOR); } sb.append(Character.toLowerCase(c)); @@ -305,19 +270,15 @@ public class StringUtil extends org.apache.commons.lang3.StringUtils /** * 是否包含字符串 - * - * @param str 验证字符串 + * + * @param str 验证字符串 * @param strs 字符串组 * @return 包含返回true */ - public static boolean inStringIgnoreCase(String str, String... strs) - { - if (str != null && strs != null) - { - for (String s : strs) - { - if (str.equalsIgnoreCase(trim(s))) - { + public static boolean inStringIgnoreCase(String str, String... strs) { + if (str != null && strs != null) { + for (String s : strs) { + if (str.equalsIgnoreCase(trim(s))) { return true; } } @@ -327,31 +288,25 @@ public class StringUtil extends org.apache.commons.lang3.StringUtils /** * 将下划线大写方式命名的字符串转换为驼峰式。如果转换前的下划线大写方式命名的字符串为空,则返回空字符串。 例如:HELLO_WORLD->HelloWorld - * + * * @param name 转换前的下划线大写方式命名的字符串 * @return 转换后的驼峰式命名的字符串 */ - public static String convertToCamelCase(String name) - { + public static String convertToCamelCase(String name) { StringBuilder result = new StringBuilder(); // 快速检查 - if (name == null || name.isEmpty()) - { + if (name == null || name.isEmpty()) { // 没必要转换 return ""; - } - else if (!name.contains("_")) - { + } else if (!name.contains("_")) { // 不含下划线,仅将首字母大写 return name.substring(0, 1).toUpperCase() + name.substring(1); } // 用下划线将原始字符串分割 String[] camels = name.split("_"); - for (String camel : camels) - { + for (String camel : camels) { // 跳过原始字符串中开头、结尾的下换线或双重下划线 - if (camel.isEmpty()) - { + if (camel.isEmpty()) { continue; } // 首字母大写 @@ -364,30 +319,22 @@ public class StringUtil extends org.apache.commons.lang3.StringUtils /** * 驼峰式命名法 例如:user_name->userName */ - public static String toCamelCase(String s) - { - if (s == null) - { + public static String toCamelCase(String s) { + if (s == null) { return null; } s = s.toLowerCase(); StringBuilder sb = new StringBuilder(s.length()); boolean upperCase = false; - for (int i = 0; i < s.length(); i++) - { + for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); - if (c == SEPARATOR) - { + if (c == SEPARATOR) { upperCase = true; - } - else if (upperCase) - { + } else if (upperCase) { sb.append(Character.toUpperCase(c)); upperCase = false; - } - else - { + } else { sb.append(c); } } @@ -395,8 +342,7 @@ public class StringUtil extends org.apache.commons.lang3.StringUtils } @SuppressWarnings("unchecked") - public static T cast(Object obj) - { + public static T cast(Object obj) { return (T) obj; } -} \ No newline at end of file +} diff --git a/pear-common/src/main/java/com/pearadmin/common/tools/system/CpuInfo.java b/pear-common/src/main/java/com/pearadmin/common/tools/system/CpuInfo.java index a5cf24744ffa970e0cc049692bd0172a161e7c9b..e116af25404393791f78945029d6da23a47a1d71 100644 --- a/pear-common/src/main/java/com/pearadmin/common/tools/system/CpuInfo.java +++ b/pear-common/src/main/java/com/pearadmin/common/tools/system/CpuInfo.java @@ -10,6 +10,9 @@ import java.util.Date; import java.util.LinkedList; import java.util.List; +/** + * @author 就 眠 仪 式 + */ @Data public class CpuInfo { @@ -20,7 +23,6 @@ public class CpuInfo { /** * 內存相关信息 - * */ private MemInfo memInfo; @@ -79,7 +81,7 @@ public class CpuInfo { */ private String sysInfoOsArch; - /** + /** * 当前JVM占用的内存总数(M) */ private double jvmInfoTotal; @@ -120,7 +122,9 @@ public class CpuInfo { return NumberUtil.div(jvmInfoTotal - jvmInfoFree, (1024 * 1024), 2); } - public double getJvmUsage() { return NumberUtil.mul(NumberUtil.div(jvmInfoTotal - jvmInfoFree, jvmInfoTotal, 4), 100); } + public double getJvmUsage() { + return NumberUtil.mul(NumberUtil.div(jvmInfoTotal - jvmInfoFree, jvmInfoTotal, 4), 100); + } /** * 获取JDK名称 diff --git a/pear-common/src/main/java/com/pearadmin/common/tools/system/MemInfo.java b/pear-common/src/main/java/com/pearadmin/common/tools/system/MemInfo.java index 49c4b182d5947e7af4563f70f610d34933f78508..fe11bff52a6382327f129d1fb335461d2edf88cd 100644 --- a/pear-common/src/main/java/com/pearadmin/common/tools/system/MemInfo.java +++ b/pear-common/src/main/java/com/pearadmin/common/tools/system/MemInfo.java @@ -2,8 +2,10 @@ package com.pearadmin.common.tools.system; import cn.hutool.core.util.NumberUtil; import lombok.Data; -import lombok.ToString; +/** + * @author 就 眠 仪 式 + */ @Data public class MemInfo { diff --git a/pear-common/src/main/java/com/pearadmin/common/tools/system/SysFileInfo.java b/pear-common/src/main/java/com/pearadmin/common/tools/system/SysFileInfo.java index bed1dc2534542d1bd4044e0fe1142159049276bc..59e169aaa4c4a055ade9c18519976c1ecb74d8d4 100644 --- a/pear-common/src/main/java/com/pearadmin/common/tools/system/SysFileInfo.java +++ b/pear-common/src/main/java/com/pearadmin/common/tools/system/SysFileInfo.java @@ -1,7 +1,6 @@ package com.pearadmin.common.tools.system; import lombok.Data; -import lombok.ToString; @Data public class SysFileInfo { diff --git a/pear-common/src/main/java/com/pearadmin/common/tools/system/SystemUtil.java b/pear-common/src/main/java/com/pearadmin/common/tools/system/SystemUtil.java index 3ba9f86759166df608b7e5b6c7ea734c07b3ac2d..b53b3e5bbd75a4bcd36c4f70e8eae3d9693e69b6 100644 --- a/pear-common/src/main/java/com/pearadmin/common/tools/system/SystemUtil.java +++ b/pear-common/src/main/java/com/pearadmin/common/tools/system/SystemUtil.java @@ -20,16 +20,16 @@ public class SystemUtil { private static final int WAIT_SECOND = 110; - public static CpuInfo getCpu(){ + public static CpuInfo getCpu() { CpuInfo cpu = new CpuInfo(); - SystemInfo si=new SystemInfo(); + SystemInfo si = new SystemInfo(); HardwareAbstractionLayer hal = si.getHardware(); - setCpuInfo(hal.getProcessor(),cpu); + setCpuInfo(hal.getProcessor(), cpu); MemInfo memInfo = setMemInfo(hal.getMemory()); cpu.setMemInfo(memInfo); setSysInfo(cpu); setJvmInfo(cpu); - setSysFiles(si.getOperatingSystem(),cpu); + setSysFiles(si.getOperatingSystem(), cpu); return cpu; } diff --git a/pear-common/src/main/java/com/pearadmin/common/web/base/BaseController.java b/pear-common/src/main/java/com/pearadmin/common/web/base/BaseController.java index 254d1ca05d3c0b0e66901f260103115108a132fc..bc63ac658f24508f7bec76b10a431c09f0496921 100644 --- a/pear-common/src/main/java/com/pearadmin/common/web/base/BaseController.java +++ b/pear-common/src/main/java/com/pearadmin/common/web/base/BaseController.java @@ -4,11 +4,11 @@ import com.pearadmin.common.web.domain.response.ResultController; /** * Describe: 基 础 控 制 器 类 - * Author: 就 眠 仪 式 + * + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ + */ public class BaseController extends ResultController { - } diff --git a/pear-common/src/main/java/com/pearadmin/common/web/base/BaseDomain.java b/pear-common/src/main/java/com/pearadmin/common/web/base/BaseDomain.java index 4b40eeb7846fdd16ad80caf1710c1bf53e732441..c237bead7d4aa82ff73ef3da484b3a7e39e83906 100644 --- a/pear-common/src/main/java/com/pearadmin/common/web/base/BaseDomain.java +++ b/pear-common/src/main/java/com/pearadmin/common/web/base/BaseDomain.java @@ -1,55 +1,57 @@ package com.pearadmin.common.web.base; import lombok.Data; + import java.io.Serializable; import java.time.LocalDateTime; import java.util.Map; /** * Describe: 基 础 实 体 类 - * Author: 就 眠 仪 式 + * + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ + */ @Data public class BaseDomain implements Serializable { /** * 创建时间 - * */ + */ private LocalDateTime createTime; /** * 创建人 - * */ + */ private String createBy; /** * 创建人名称 - * */ + */ private String createName; /** * 修改时间 - * */ + */ private LocalDateTime updateTime; /** * 修改人 - * */ + */ private String updateBy; /** * 修改人名称 - * */ + */ private String updateName; /** * 备注 - * */ + */ private String remark; /** - * 请求参数 - * */ + * 请求参数 + */ private Map params; } diff --git a/pear-common/src/main/java/com/pearadmin/common/web/domain/request/PageDomain.java b/pear-common/src/main/java/com/pearadmin/common/web/domain/request/PageDomain.java index 6bb86c07ff93803a511b5fcf7ae7392a7725145b..47978eec9ce99b54eb49724a12dcfb3012da2357 100644 --- a/pear-common/src/main/java/com/pearadmin/common/web/domain/request/PageDomain.java +++ b/pear-common/src/main/java/com/pearadmin/common/web/domain/request/PageDomain.java @@ -4,34 +4,35 @@ import lombok.Data; /** * Describe: 分 页 参 数 封 装 - * Author: 就 眠 仪 式 + * + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ + */ @Data public class PageDomain { /** * 当前页 - * */ + */ private Integer page; /** * 每页数量 - * */ + */ private Integer limit; /** * 获取开始的数据行 - * */ - public Integer start(){ - return (this.page-1)*this.limit; + */ + public Integer start() { + return (this.page - 1) * this.limit; } /** * 获取结束的数据行 - * */ - public Integer end(){ - return this.page*this.limit; + */ + public Integer end() { + return this.page * this.limit; } } diff --git a/pear-common/src/main/java/com/pearadmin/common/web/domain/response/Result.java b/pear-common/src/main/java/com/pearadmin/common/web/domain/response/Result.java index a34d24b12b9af8b08db48f0521d58546631adad5..3c6f94464fd50021e3283f3f0753b47c476f6b27 100644 --- a/pear-common/src/main/java/com/pearadmin/common/web/domain/response/Result.java +++ b/pear-common/src/main/java/com/pearadmin/common/web/domain/response/Result.java @@ -7,9 +7,10 @@ import java.io.Serializable; /** * Describe: Ajax 返 回 JSON 结 果 封 装 数 据 - * Author: 就 眠 仪 式 + * + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ + */ @Data @Accessors(chain = true) public class Result implements Serializable { @@ -36,43 +37,43 @@ public class Result implements Serializable { /** * 成 功 操 作 - * */ - public static Result success(){ + */ + public static Result success() { return success(null); } /** * 成 功 操 作 , 携 带 数 据 - * */ - public static Result success(T data){ - return success(ResultCode.SUCCESS.getMessage(),data); + */ + public static Result success(T data) { + return success(ResultCode.SUCCESS.getMessage(), data); } /** * 成 功 操 作, 携 带 消 息 - * */ - public static Result success(String message){ - return success(message,null); + */ + public static Result success(String message) { + return success(message, null); } /** * 成 功 操 作, 携 带 消 息 和 携 带 数 据 - * */ - public static Result success(String message,T data){ - return success(ResultCode.SUCCESS.getCode(),message,data); + */ + public static Result success(String message, T data) { + return success(ResultCode.SUCCESS.getCode(), message, data); } /** * 成 功 操 作, 携 带 自 定 义 状 态 码 和 消 息 - * */ - public static Result success(int code,String message){ - return success(code,message,null); + */ + public static Result success(int code, String message) { + return success(code, message, null); } /** * 成 功 操 作, 携 带 自 定义 状 态 码, 消 息 和 数 据 - * */ - public static Result success(int code,String message,T data){ + */ + public static Result success(int code, String message, T data) { Result result = new Result(); result.setCode(code); result.setMsg(message); @@ -83,36 +84,36 @@ public class Result implements Serializable { /** * 失 败 操 作, 默 认 数 据 - * */ - public static Result failure(){ + */ + public static Result failure() { return failure(ResultCode.SUCCESS.getMessage()); } /** * 失 败 操 作, 携 带 自 定 义 消 息 */ - public static Result failure(String message){ - return failure(message,null); + public static Result failure(String message) { + return failure(message, null); } /** * 失 败 操 作, 携 带 自 定 义 消 息 和 数 据 - * */ - public static Result failure(String message,T data){ - return failure(ResultCode.FAILURE.getCode(),message,data); + */ + public static Result failure(String message, T data) { + return failure(ResultCode.FAILURE.getCode(), message, data); } /** * 失 败 操 作, 携 带 自 定 义 状 态 码 和 自 定 义 消 息 - * */ - public static Result failure(int code ,String message){ - return failure(ResultCode.FAILURE.getCode(),message,null); + */ + public static Result failure(int code, String message) { + return failure(ResultCode.FAILURE.getCode(), message, null); } /** * 失 败 操 作, 携 带 自 定 义 状 态 码 , 消 息 和 数 据 - * */ - public static Result failure(int code,String message,T data){ + */ + public static Result failure(int code, String message, T data) { Result result = new Result(); result.setCode(code); result.setMsg(message); @@ -123,18 +124,18 @@ public class Result implements Serializable { /** * Boolean 返 回 操 作, 携 带 默 认 返 回 值 - * */ - public static Result decide(boolean b){ - return decide(b,ResultCode.SUCCESS.getMessage(),ResultCode.FAILURE.getMessage()); + */ + public static Result decide(boolean b) { + return decide(b, ResultCode.SUCCESS.getMessage(), ResultCode.FAILURE.getMessage()); } /** * Boolean 返 回 操 作, 携 带 自 定 义 消 息 - * */ - public static Result decide(boolean b,String success,String failure){ - if(b){ + */ + public static Result decide(boolean b, String success, String failure) { + if (b) { return success(success); - }else{ + } else { return failure(failure); } } diff --git a/pear-common/src/main/java/com/pearadmin/common/web/domain/response/ResultCode.java b/pear-common/src/main/java/com/pearadmin/common/web/domain/response/ResultCode.java index 7675a6bb76882498f50fa9fb92b656cb75bdd157..1bb7e3df9d07126e227b8e1a0d5598671eb494e4 100644 --- a/pear-common/src/main/java/com/pearadmin/common/web/domain/response/ResultCode.java +++ b/pear-common/src/main/java/com/pearadmin/common/web/domain/response/ResultCode.java @@ -4,35 +4,36 @@ import lombok.Getter; /** * Describe: 统 一 返 回 状 态 码 - * Author: 就 眠 仪 式 + * + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ + */ public enum ResultCode { /** * 成功 */ - SUCCESS(200,"操作成功"), + SUCCESS(200, "操作成功"), /** * 失败 */ - FAILURE(500,"操作失败"); + FAILURE(500, "操作失败"); /** * 状 态 码 - * */ + */ @Getter private final int code; /** * 携 带 消 息 - * */ + */ @Getter private final String message; /** * 构 造 方 法 - * */ + */ ResultCode(int code, String message) { this.code = code; diff --git a/pear-common/src/main/java/com/pearadmin/common/web/domain/response/ResultController.java b/pear-common/src/main/java/com/pearadmin/common/web/domain/response/ResultController.java index 168f00c2656488169c29bb5e12502838ce74ad5b..06122a5c8dab8b8051e3d3a1703cfa4aa8d816d7 100644 --- a/pear-common/src/main/java/com/pearadmin/common/web/domain/response/ResultController.java +++ b/pear-common/src/main/java/com/pearadmin/common/web/domain/response/ResultController.java @@ -1,120 +1,160 @@ package com.pearadmin.common.web.domain.response; -import com.pearadmin.common.web.domain.response.module.ResultTree; import com.pearadmin.common.web.domain.response.module.ResultTable; +import com.pearadmin.common.web.domain.response.module.ResultTree; import org.springframework.web.servlet.ModelAndView; + import java.util.Map; /** * Describe: 统一响应 Controller - * Author: 就 眠 仪 式 + * + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ + */ public class ResultController { + /** + * Describe: 返回 Tree 数据 + * Param data + * Return Tree数据 + */ + protected static ResultTree dataTree(Object data) { + ResultTree resuTree = new ResultTree(); + resuTree.setData(data); + return resuTree; + } + + /** + * Describe: 返回数据表格数据 分页 + * Param data + * Return 表格分页数据 + */ + protected static ResultTable pageTable(Object data, long count) { + return ResultTable.pageTable(count, data); + } + + /** + * Describe: 返回数据表格数据 + * Param data + * Return 表格分页数据 + */ + protected static ResultTable dataTable(Object data) { + return ResultTable.dataTable(data); + } + + /** + * Describe: 返回树状表格数据 分页 + * Param data + * Return 表格分页数据 + */ + protected static ResultTable treeTable(Object data) { + return ResultTable.dataTable(data); + } + /** * 成功操作 - * */ - public Result success(){ + */ + public Result success() { return Result.success(); } /** * 成功操作 - * */ - public Result success(String msg){ + */ + public Result success(String msg) { return Result.success(msg); } /** * 成功操作 - * */ - public Result success(Object data){ + */ + public Result success(Object data) { return Result.success(data); } /** * 成功操作 - * */ - public Result success(String msg,Object data){ - return Result.success(msg,data); + */ + public Result success(String msg, Object data) { + return Result.success(msg, data); } /** * 成功操作 - * */ - public Result success(int code,String message,Object data){ - return Result.success(code,message,data); + */ + public Result success(int code, String message, Object data) { + return Result.success(code, message, data); } /** * 失败操作 - * */ - public Result failure(){ + */ + public Result failure() { return Result.failure(); } /** * 失败操作 - * */ - public Result failure(String msg){ + */ + public Result failure(String msg) { return Result.failure(msg); } /** * 失败操作 - * */ - public Result failure(String msg,Object data){ - return Result.failure(msg,data); + */ + public Result failure(String msg, Object data) { + return Result.failure(msg, data); } /** * 失败操作 - * */ - public Result failure(int code,String msg,Object data){ - return Result.failure(code,msg,data); + */ + public Result failure(int code, String msg, Object data) { + return Result.failure(code, msg, data); } /** * 选择返回 - * */ - public Result decide(Boolean b){ + */ + public Result decide(Boolean b) { return Result.decide(b); } /** * 选择返回 - * */ - public Result decide(Boolean b,String success,String failure){ - return Result.decide(b,success,failure); + */ + public Result decide(Boolean b, String success, String failure) { + return Result.decide(b, success, failure); } /** * 选择返回 - * */ - public Result decide(int result){ - if(result>0){ + */ + public Result decide(int result) { + if (result > 0) { return Result.decide(true); - }else{ + } else { return Result.decide(false); } } /** * 选择返回 - * */ - public Result decide(int result,String success,String failure){ - if(result>0){ - return Result.decide(true,success,failure); - }else{ - return Result.decide(false,success,failure); + */ + public Result decide(int result, String success, String failure) { + if (result > 0) { + return Result.decide(true, success, failure); + } else { + return Result.decide(false, success, failure); } } /** * 页面跳转 - * */ - public ModelAndView jumpPage(String path){ + */ + public ModelAndView jumpPage(String path) { ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName(path); return modelAndView; @@ -122,50 +162,12 @@ public class ResultController { /** * 带参数的页面跳转 - * */ - public ModelAndView jumpPage(String path, Map params){ + */ + public ModelAndView jumpPage(String path, Map params) { ModelAndView modelAndView = new ModelAndView(); modelAndView.setViewName(path); modelAndView.addAllObjects(params); return modelAndView; } - /** - * Describe: 返回 Tree 数据 - * Param data - * Return Tree数据 - * */ - protected static ResultTree dataTree(Object data){ - ResultTree resuTree = new ResultTree(); - resuTree.setData(data); - return resuTree; - } - - /** - * Describe: 返回数据表格数据 分页 - * Param data - * Return 表格分页数据 - * */ - protected static ResultTable pageTable(Object data, long count){ - return ResultTable.pageTable(count,data); - } - - /** - * Describe: 返回数据表格数据 - * Param data - * Return 表格分页数据 - * */ - protected static ResultTable dataTable(Object data){ - return ResultTable.dataTable(data); - } - - /** - * Describe: 返回树状表格数据 分页 - * Param data - * Return 表格分页数据 - * */ - protected static ResultTable treeTable(Object data){ - return ResultTable.dataTable(data); - } - } diff --git a/pear-common/src/main/java/com/pearadmin/common/web/domain/response/module/ResultSelect.java b/pear-common/src/main/java/com/pearadmin/common/web/domain/response/module/ResultSelect.java index 3c94e9ec52ed7060341abd351c1bb71978167531..0cd352257f8eae112aba1f49d346fc3409894b1b 100644 --- a/pear-common/src/main/java/com/pearadmin/common/web/domain/response/module/ResultSelect.java +++ b/pear-common/src/main/java/com/pearadmin/common/web/domain/response/module/ResultSelect.java @@ -5,11 +5,11 @@ import java.util.List; /** * Describe: 前 端 下 拉 树 - * Author: 就 眠 仪 式 + * + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ -public class ResultSelect implements Serializable -{ + */ +public class ResultSelect implements Serializable { private static final long serialVersionUID = 1L; /** @@ -27,43 +27,35 @@ public class ResultSelect implements Serializable */ private List s; - public ResultSelect() - { + public ResultSelect() { } - public ResultSelect(String v, String n) - { + public ResultSelect(String v, String n) { this.v = v; this.n = n; } - public List getS() - { + public List getS() { return s; } - public void setN(String n) - { - this.n = n; + public void setS(List s) { + this.s = s; } - public String getN() - { + public String getN() { return n; } - public void setS(List s) - { - this.s = s; + public void setN(String n) { + this.n = n; } - public String getV() - { + public String getV() { return v; } - public void setV(String v) - { + public void setV(String v) { this.v = v; } } diff --git a/pear-common/src/main/java/com/pearadmin/common/web/domain/response/module/ResultTable.java b/pear-common/src/main/java/com/pearadmin/common/web/domain/response/module/ResultTable.java index 11d78c03ba7ff2ac6681bb478e50e0b03b21bec9..639ba60aad327c6399f89d6f8f8553021b85cffd 100644 --- a/pear-common/src/main/java/com/pearadmin/common/web/domain/response/module/ResultTable.java +++ b/pear-common/src/main/java/com/pearadmin/common/web/domain/response/module/ResultTable.java @@ -5,36 +5,37 @@ import lombok.Data; /** * Describe: 前 端 表 格 数 据 封 装 - * Author: 就 眠 仪 式 + * + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ + */ @Data public class ResultTable extends BaseDomain { /** * 状态码 - * */ + */ private Integer code; /** * 提示消息 - * */ + */ private String msg; /** * 消息总量 - * */ + */ private Long count; /** * 数据对象 - * */ + */ private Object data; /** * 构 建 - * */ - public static ResultTable pageTable(long count,Object data){ + */ + public static ResultTable pageTable(long count, Object data) { ResultTable resultTable = new ResultTable(); resultTable.setData(data); resultTable.setCode(0); @@ -42,7 +43,7 @@ public class ResultTable extends BaseDomain { return resultTable; } - public static ResultTable dataTable(Object data){ + public static ResultTable dataTable(Object data) { ResultTable resultTable = new ResultTable(); resultTable.setData(data); resultTable.setCode(0); diff --git a/pear-common/src/main/java/com/pearadmin/common/web/domain/response/module/ResultTree.java b/pear-common/src/main/java/com/pearadmin/common/web/domain/response/module/ResultTree.java index 454f8a1590543de48aa7b1f2c5c59d2602255560..1a481215a43aa6618d9d00af20b00b5c32dfe572 100644 --- a/pear-common/src/main/java/com/pearadmin/common/web/domain/response/module/ResultTree.java +++ b/pear-common/src/main/java/com/pearadmin/common/web/domain/response/module/ResultTree.java @@ -4,27 +4,28 @@ import lombok.Data; /** * Describe: 前端 tree 结果封装数据 - * Author: 就 眠 仪 式 + * + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 - * */ + */ @Data public class ResultTree { /** * 状态信息 - * */ + */ private Status status = new Status(); /** * 返回数据 - * */ + */ private Object data; /** * 所需内部类 - * */ + */ @Data - public class Status{ + public class Status { private Integer code = 200; diff --git a/pear-common/src/main/java/com/pearadmin/common/web/session/HttpSessionContext.java b/pear-common/src/main/java/com/pearadmin/common/web/session/HttpSessionContext.java index 8c3048d58791997b839473169b2d6323f4f6d929..e8a6f49f49887e0b373381c14c3315fdd0b92980 100644 --- a/pear-common/src/main/java/com/pearadmin/common/web/session/HttpSessionContext.java +++ b/pear-common/src/main/java/com/pearadmin/common/web/session/HttpSessionContext.java @@ -7,7 +7,8 @@ import java.util.concurrent.ConcurrentHashMap; /** * Describe: 单例模式 HttpSessionContext - * Author: Heiky + * + * @author Heiky * CreateTime: 2020/12/17 */ public class HttpSessionContext { diff --git a/pear-common/src/main/java/com/pearadmin/common/web/session/HttpSessionContextHolder.java b/pear-common/src/main/java/com/pearadmin/common/web/session/HttpSessionContextHolder.java index 0ee9294feaf0574c4cbe0f62fbeb1be65857f4c5..1333fa897be6e6eb645c1cc19fbcae83ad6ef3d6 100644 --- a/pear-common/src/main/java/com/pearadmin/common/web/session/HttpSessionContextHolder.java +++ b/pear-common/src/main/java/com/pearadmin/common/web/session/HttpSessionContextHolder.java @@ -3,7 +3,8 @@ package com.pearadmin.common.web.session; /** * Describe: HttpSessionContext对象持有者 - * Author: Heiky + * + * @author Heiky * CreateTime: 2020/12/17 */ public class HttpSessionContextHolder { diff --git a/pear-common/src/main/java/com/pearadmin/common/xss/XssRequest.java b/pear-common/src/main/java/com/pearadmin/common/xss/XssRequest.java index f08f9fa391f355f0ebe3fbbb741e4f49ddb6fb36..f0f461aa9872a9c97d2d0523dd155d0b80ce5769 100644 --- a/pear-common/src/main/java/com/pearadmin/common/xss/XssRequest.java +++ b/pear-common/src/main/java/com/pearadmin/common/xss/XssRequest.java @@ -2,6 +2,7 @@ package com.pearadmin.common.xss; import com.pearadmin.common.tools.jsoup.JsoupUtil; import com.pearadmin.common.tools.string.StringUtil; + import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequestWrapper; @@ -16,9 +17,16 @@ public class XssRequest extends HttpServletRequestWrapper { this.isIncludeRichText = isIncludeRichText; } + public static HttpServletRequest getOrgRequest(HttpServletRequest req) { + if (req instanceof XssRequest) { + return ((XssRequest) req).getOrgRequest(); + } + return req; + } + @Override public String getParameter(String name) { - if(("content".equals(name) || name.endsWith("WithHtml")) && !isIncludeRichText){ + if (("content".equals(name) || name.endsWith("WithHtml")) && !isIncludeRichText) { return super.getParameter(name); } name = JsoupUtil.clean(name); @@ -32,8 +40,8 @@ public class XssRequest extends HttpServletRequestWrapper { @Override public String[] getParameterValues(String name) { String[] arr = super.getParameterValues(name); - if(arr != null){ - for (int i=0;i excludes = new ArrayList(); + @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException { - if(log.isDebugEnabled()){ + if (log.isDebugEnabled()) { log.debug("xss filter is open"); } HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse resp = (HttpServletResponse) response; - if(handleExcludeURL(req, resp)){ + if (handleExcludeURL(req, resp)) { filterChain.doFilter(request, response); return; } - XssRequest xssRequest = new XssRequest((HttpServletRequest) request,IS_INCLUDE_RICH_TEXT); + XssRequest xssRequest = new XssRequest((HttpServletRequest) request, IS_INCLUDE_RICH_TEXT); filterChain.doFilter(xssRequest, response); } @@ -53,11 +55,11 @@ public class XssSupport implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { - if(log.isDebugEnabled()){ + if (log.isDebugEnabled()) { log.debug("xss filter init~~~~~~~~~~~~"); } String isIncludeRichText = filterConfig.getInitParameter("isIncludeRichText"); - if(StringUtil.isNotBlank(isIncludeRichText)){ + if (StringUtil.isNotBlank(isIncludeRichText)) { IS_INCLUDE_RICH_TEXT = BooleanUtils.toBoolean(isIncludeRichText); } String temp = filterConfig.getInitParameter("excludes"); diff --git a/pear-entrance/src/main/java/com/pearadmin/PearEntranceApplication.java b/pear-entrance/src/main/java/com/pearadmin/PearEntranceApplication.java index f24c7a5148861c2f95875dc7010c281779c80428..b8e9c461ce0c091104080528a495b3b9f457bd72 100644 --- a/pear-entrance/src/main/java/com/pearadmin/PearEntranceApplication.java +++ b/pear-entrance/src/main/java/com/pearadmin/PearEntranceApplication.java @@ -8,7 +8,7 @@ import org.springframework.boot.web.servlet.ServletComponentScan; /** * Describe: 入 口 启 动 类 - * Author: 就 眠 仪 式 + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 */ diff --git a/pear-entrance/src/main/java/com/pearadmin/api/common/CaptchaController.java b/pear-entrance/src/main/java/com/pearadmin/api/common/CaptchaController.java index a054585c08864556ae5a5dd46b9353395d794875..2f17bce4c91a8adbc89ff91f6e1404dd6669a5cd 100644 --- a/pear-entrance/src/main/java/com/pearadmin/api/common/CaptchaController.java +++ b/pear-entrance/src/main/java/com/pearadmin/api/common/CaptchaController.java @@ -10,7 +10,7 @@ import javax.servlet.http.HttpServletRequest; /** * Describe: 验证码控制器 - * Author: 就 眠 仪 式 + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 * */ @RestController diff --git a/pear-entrance/src/main/java/com/pearadmin/api/common/MonitorController.java b/pear-entrance/src/main/java/com/pearadmin/api/common/MonitorController.java index bc29993cd1a5f9588165a22815c734b0f669de46..c7167da00cca7fb4cf1f9ce90e52354ab2a2c5e0 100644 --- a/pear-entrance/src/main/java/com/pearadmin/api/common/MonitorController.java +++ b/pear-entrance/src/main/java/com/pearadmin/api/common/MonitorController.java @@ -10,7 +10,9 @@ import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.servlet.ModelAndView; - +/** + * @author 就 眠 仪 式 + * */ @RestController @RequestMapping(ControllerConstant.API_SYSTEM_PREFIX + "monitor") public class MonitorController extends BaseController { diff --git a/pear-entrance/src/main/java/com/pearadmin/api/modules/EntranceController.java b/pear-entrance/src/main/java/com/pearadmin/api/modules/EntranceController.java index 97e7a40de27a6a90b1832ef67b607e91650dd417..e0ca9cfb8e45dbae4c46eb9fae162361c89e9249 100644 --- a/pear-entrance/src/main/java/com/pearadmin/api/modules/EntranceController.java +++ b/pear-entrance/src/main/java/com/pearadmin/api/modules/EntranceController.java @@ -21,7 +21,7 @@ import java.time.LocalTime; /** * Describe: 入 口 控 制 器 - * Author: 就 眠 仪 式 + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 * */ @RestController diff --git a/pear-entrance/src/main/java/com/pearadmin/secure/SecureConfiguration.java b/pear-entrance/src/main/java/com/pearadmin/secure/SecureConfiguration.java index 7f04da9513bb7082de8be252efa60ce3d7118ebc..18c86dd28e70c13b9aa752ab08a761c61abf4859 100644 --- a/pear-entrance/src/main/java/com/pearadmin/secure/SecureConfiguration.java +++ b/pear-entrance/src/main/java/com/pearadmin/secure/SecureConfiguration.java @@ -20,7 +20,7 @@ import javax.annotation.Resource; /** * Describe: Security 安全配置 - * Author: 就眠仪式 + * @author 就眠仪式 * CreateTime: 2019/10/23 */ @Configuration diff --git a/pear-entrance/src/main/java/com/pearadmin/secure/SecureExtendConfiguration.java b/pear-entrance/src/main/java/com/pearadmin/secure/SecureExtendConfiguration.java index 9df08669d5a2b8b61ec5a9ec78ff4e52ad28fec8..f1d4c5e2254c5509fb4ca47cd107a1e58000e144 100644 --- a/pear-entrance/src/main/java/com/pearadmin/secure/SecureExtendConfiguration.java +++ b/pear-entrance/src/main/java/com/pearadmin/secure/SecureExtendConfiguration.java @@ -18,7 +18,7 @@ import java.util.concurrent.ScheduledThreadPoolExecutor; /** * Describe: Security 扩展配置 - * Author: 就眠仪式 + * @author 就眠仪式 * CreateTime: 2019/10/23 */ @Configuration diff --git a/pear-entrance/src/main/java/com/pearadmin/secure/domain/SecureUserDetailsService.java b/pear-entrance/src/main/java/com/pearadmin/secure/domain/SecureUserDetailsService.java index dea52dd6392a7f978beb733553024190e049ad5d..cef8c5f4adb2a9ac0f7f1833ca5462549c827637 100644 --- a/pear-entrance/src/main/java/com/pearadmin/secure/domain/SecureUserDetailsService.java +++ b/pear-entrance/src/main/java/com/pearadmin/secure/domain/SecureUserDetailsService.java @@ -13,7 +13,7 @@ import java.util.List; /** * Describe: Security 用户服务 - * Author: 就 眠 仪 式 + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 * */ @Component diff --git a/pear-entrance/src/main/java/com/pearadmin/secure/domain/SecureUserTokenService.java b/pear-entrance/src/main/java/com/pearadmin/secure/domain/SecureUserTokenService.java index 6245bb01723da0c40ad29cd246a17de5f7cf706c..f6c6ef4b0aabf27ea0f394958f3ad1a106388756 100644 --- a/pear-entrance/src/main/java/com/pearadmin/secure/domain/SecureUserTokenService.java +++ b/pear-entrance/src/main/java/com/pearadmin/secure/domain/SecureUserTokenService.java @@ -16,7 +16,7 @@ import java.util.List; /** * Describe: Token 记录服务 - * Author: 就 眠 仪 式 + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 */ @Component diff --git a/pear-entrance/src/main/java/com/pearadmin/secure/process/SecureAccessDeniedHandler.java b/pear-entrance/src/main/java/com/pearadmin/secure/process/SecureAccessDeniedHandler.java index ba6a34ab1f8ff015d87e1d16fba9d2319ca406d6..c914075c4579ab14bd7f19d910823486bdd89796 100644 --- a/pear-entrance/src/main/java/com/pearadmin/secure/process/SecureAccessDeniedHandler.java +++ b/pear-entrance/src/main/java/com/pearadmin/secure/process/SecureAccessDeniedHandler.java @@ -13,7 +13,7 @@ import java.io.IOException; /** * Describe: 自定义 Security 用户暂无权限处理类 - * Author: 就 眠 仪 式 + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 * */ @Component diff --git a/pear-entrance/src/main/java/com/pearadmin/secure/process/SecureAuthenticationEntryPoint.java b/pear-entrance/src/main/java/com/pearadmin/secure/process/SecureAuthenticationEntryPoint.java index 099e25890064642ca6378d2f3380ebe93e1ee10c..20ab5d68c36f54a50be266323974cdcd322dba5a 100644 --- a/pear-entrance/src/main/java/com/pearadmin/secure/process/SecureAuthenticationEntryPoint.java +++ b/pear-entrance/src/main/java/com/pearadmin/secure/process/SecureAuthenticationEntryPoint.java @@ -13,7 +13,7 @@ import java.io.IOException; /** * Describe: 自定义 Security 用户未登陆处理类 - * Author: 就 眠 仪 式 + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 * */ @Component diff --git a/pear-entrance/src/main/java/com/pearadmin/secure/process/SecureAuthenticationFailureHandler.java b/pear-entrance/src/main/java/com/pearadmin/secure/process/SecureAuthenticationFailureHandler.java index 0f7ea3ae9d65ad4cc1c7fd0d3ce28326db8bb665..13dda636b7f0321eee996fea353da730ebfc9331 100644 --- a/pear-entrance/src/main/java/com/pearadmin/secure/process/SecureAuthenticationFailureHandler.java +++ b/pear-entrance/src/main/java/com/pearadmin/secure/process/SecureAuthenticationFailureHandler.java @@ -24,7 +24,7 @@ import java.io.IOException; /** * Describe: 自定义 Security 用户登录失败处理类 - * Author: 就 眠 仪 式 + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 * */ @Component diff --git a/pear-entrance/src/main/java/com/pearadmin/secure/process/SecureAuthenticationSuccessHandler.java b/pear-entrance/src/main/java/com/pearadmin/secure/process/SecureAuthenticationSuccessHandler.java index 87bc2a48012d63e11e0ad22b111657afcdaa93f5..7ca263f99a0838794917479cb6b3f596eb04dce0 100644 --- a/pear-entrance/src/main/java/com/pearadmin/secure/process/SecureAuthenticationSuccessHandler.java +++ b/pear-entrance/src/main/java/com/pearadmin/secure/process/SecureAuthenticationSuccessHandler.java @@ -23,7 +23,7 @@ import java.time.LocalDateTime; /** * Describe: 自定义 Security 用户未登陆处理类 - * Author: 就 眠 仪 式 + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 */ @Component diff --git a/pear-entrance/src/main/java/com/pearadmin/secure/process/SecureLogoutHandler.java b/pear-entrance/src/main/java/com/pearadmin/secure/process/SecureLogoutHandler.java index f05b42403b27874567f8012512128eb869352ed1..80be311f67546291f46bb6ff3330320c9b351b2d 100644 --- a/pear-entrance/src/main/java/com/pearadmin/secure/process/SecureLogoutHandler.java +++ b/pear-entrance/src/main/java/com/pearadmin/secure/process/SecureLogoutHandler.java @@ -16,7 +16,7 @@ import javax.servlet.http.HttpSessionEvent; /** * Describe: 自定义用户注销处理类 - * Author: Heiky + * @author Heiky * CreateTime: 2020/12/17 */ @Slf4j diff --git a/pear-entrance/src/main/java/com/pearadmin/secure/process/SecureLogoutSuccessHandler.java b/pear-entrance/src/main/java/com/pearadmin/secure/process/SecureLogoutSuccessHandler.java index 6ed58197c3d80b0bf2bbfd1beb2f0614e2426568..10c82090c39810f4b0dbd814931d2bb1d1218cc2 100644 --- a/pear-entrance/src/main/java/com/pearadmin/secure/process/SecureLogoutSuccessHandler.java +++ b/pear-entrance/src/main/java/com/pearadmin/secure/process/SecureLogoutSuccessHandler.java @@ -14,7 +14,7 @@ import java.io.IOException; /** * Describe: 自定义 Security 注销成功处理类 - * Author: 就 眠 仪 式 + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 * */ @Component diff --git a/pear-entrance/src/main/java/com/pearadmin/secure/process/SecureSessionExpiredHandler.java b/pear-entrance/src/main/java/com/pearadmin/secure/process/SecureSessionExpiredHandler.java index 247838c941618d074abe800be166916fcaa3da8d..8eb9da7151db91f6e90f4919a6451ffdc589b112 100644 --- a/pear-entrance/src/main/java/com/pearadmin/secure/process/SecureSessionExpiredHandler.java +++ b/pear-entrance/src/main/java/com/pearadmin/secure/process/SecureSessionExpiredHandler.java @@ -10,7 +10,7 @@ import java.io.IOException; /** * Describe: 自定义 Security 同账号多端登录挤下线 跳转地址 - * Author: John Ming + * @author John Ming * CreateTime: 2019/10/23 * */ @Component diff --git a/pear-entrance/src/main/java/com/pearadmin/secure/session/SecureInvalidSession.java b/pear-entrance/src/main/java/com/pearadmin/secure/session/SecureInvalidSession.java index f41f555170ab519b5546981ff2b4a52b469e97d2..90dfc534b78a4cb518b7678f1b460e01afc0fc26 100644 --- a/pear-entrance/src/main/java/com/pearadmin/secure/session/SecureInvalidSession.java +++ b/pear-entrance/src/main/java/com/pearadmin/secure/session/SecureInvalidSession.java @@ -21,7 +21,7 @@ import java.util.concurrent.TimeUnit; /** * Describe: Security 在线用户监测任务 - * Author: 就眠仪式 + * @author 就眠仪式 * CreateTime: 2019/10/23 */ @Slf4j diff --git a/pear-entrance/src/main/java/com/pearadmin/secure/session/SecureSessionService.java b/pear-entrance/src/main/java/com/pearadmin/secure/session/SecureSessionService.java index 7cffe70bfe4aea8793276e69d80e14c2d256adaa..1c933221ac334920d66fcc8699def095419915ab 100644 --- a/pear-entrance/src/main/java/com/pearadmin/secure/session/SecureSessionService.java +++ b/pear-entrance/src/main/java/com/pearadmin/secure/session/SecureSessionService.java @@ -11,7 +11,7 @@ import java.util.List; /** * Describe: Security Session 操作服务 - * Author: 就眠仪式 + * @author 就眠仪式 * CreateTime: 2019/10/23 */ public class SecureSessionService { diff --git a/pear-entrance/src/main/java/com/pearadmin/secure/support/SecurePermissionSupport.java b/pear-entrance/src/main/java/com/pearadmin/secure/support/SecurePermissionSupport.java index 6d8a082c30a8da93af841e051f777553c4c80f06..21fe9159876820bfaef97db4912b3a4d7a02e4da 100644 --- a/pear-entrance/src/main/java/com/pearadmin/secure/support/SecurePermissionSupport.java +++ b/pear-entrance/src/main/java/com/pearadmin/secure/support/SecurePermissionSupport.java @@ -15,7 +15,7 @@ import java.util.Set; /** * Describe: 自定义 Security 权限注解实现 - * Author: 就 眠 仪 式 + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 */ @Component diff --git a/pear-entrance/src/main/resources/static/component/pear/module/eleTree.js b/pear-entrance/src/main/resources/static/component/pear/module/eleTree.js index ab5ff2ce3929d4ac266549bdf085a20d519b494b..e69c5a688a0d69c764d7b4760b81b37fe612be08 100644 --- a/pear-entrance/src/main/resources/static/component/pear/module/eleTree.js +++ b/pear-entrance/src/main/resources/static/component/pear/module/eleTree.js @@ -1,6 +1,6 @@ /** * 基于layui的tree重写 - * author: hsianglee + * @author hsianglee * 最近修改时间: 2019/01/07 */ @@ -10,7 +10,7 @@ layui.define(["jquery","laytpl"], function (exports) { var hint = layui.hint(); var MOD_NAME="eleTree"; - + //外部接口 var eleTree={ //事件监听 @@ -189,7 +189,7 @@ layui.define(["jquery","laytpl"], function (exports) { contentType: "", headers: {}, done: null, - + response: { statusName: "code", statusCode: 0, @@ -217,7 +217,7 @@ layui.define(["jquery","laytpl"], function (exports) { this.filter=options.elem.attr("lay-filter"); // load加载框 options.elem.append('

') - + // 判断加载方式 if(options.data.length===0){ this.ajaxGetData(); @@ -230,7 +230,7 @@ layui.define(["jquery","laytpl"], function (exports) { // 渲染第一层 laytpl(TPL_ELEM(options,0)).render(options.data, function(string){ options.elem.html(string).children().show(); - }); + }); // 懒加载 > 展开所有 > 初始展开项 > 初始渲染所有子节点 > 初始选中项 > 每次点击只渲染当前层(默认) // 判断所有dom是否全部加载 if(!options.lazy){ @@ -255,7 +255,7 @@ layui.define(["jquery","laytpl"], function (exports) { if(!options.url) { laytpl(TPL_NoText()).render(options, function(string){ options.elem.html(string); - }); + }); return; } var data = $.extend({}, options.where); @@ -313,7 +313,7 @@ layui.define(["jquery","laytpl"], function (exports) { if(options.highlightCurrent) eleTreeNodeContent.addClass("eleTree-node-content-active"); _self.prevClickEle=eleTreeNodeContent; - + if(el.hasClass("icon-rotate")){ // 合并 @@ -396,7 +396,7 @@ layui.define(["jquery","laytpl"], function (exports) { if(_self.prevClickEle) _self.prevClickEle.removeClass("eleTree-node-content-active"); if(options.highlightCurrent) eleTreeNodeContent.addClass("eleTree-node-content-active"); _self.prevClickEle=eleTreeNodeContent; - + if(!inp){ return; } @@ -409,7 +409,7 @@ layui.define(["jquery","laytpl"], function (exports) { childNode.prop("checked",false); childNode.attr("eleTree-status","0"); } - + }else{ // 反选自身 $(inp).prop("checked",true).attr("eleTree-status","1"); @@ -426,7 +426,7 @@ layui.define(["jquery","laytpl"], function (exports) { // 点击子孙层选中祖父层(递归) _self.selectParents(inp,eleNode,siblingNode); } - + _self.checkboxRender(); if(type==="default") return; @@ -451,7 +451,7 @@ layui.define(["jquery","laytpl"], function (exports) { childNode.prop("checked","checked").attr("eleTree-status","1"); childNode.siblings(".eleTree-checkbox").addClass("eleTree-checkbox-checked"); childNode.siblings(".eleTree-checkbox").children("i").addClass("layui-icon-ok").removeClass("eleTree-checkbox-line"); - + // 选择祖父 var eleNode=checkboxEl.parent(".eleTree-node-content").parent(".eleTree-node"); var siblingNode=eleNode.siblings(".eleTree-node"); @@ -549,7 +549,7 @@ layui.define(["jquery","laytpl"], function (exports) { arr.pop(); }) - + }, // 初始默认选中 defaultChecked: function() { @@ -610,7 +610,7 @@ layui.define(["jquery","laytpl"], function (exports) { checkbox.addClass("eleTree-checkbox-checked"); checkbox.children("i").removeClass("layui-icon-ok").addClass("eleTree-checkbox-line"); } - + }) }, // 通过dom节点找对应数据 @@ -674,7 +674,7 @@ layui.define(["jquery","laytpl"], function (exports) { var node=options.elem.find("[data-"+options.request.key+"='"+key+"']"); var floor=Number(node.attr("eletree-floor"))+1; var _self=this; - + this.keySearchToOpera(key,function(d,obj) { // 数据更新 d[obj.i][options.request.children]=data; @@ -682,7 +682,7 @@ layui.define(["jquery","laytpl"], function (exports) { node.length!==0 && laytpl(TPL_ELEM(options,floor)).render(data, function(string){ $(node).children(".eleTree-node-group").empty().append(string); options.defaultExpandAll && $(node).children(".eleTree-node-group").children().show(); - }); + }); _self.unCheckNodes(); _self.defaultChecked(); }); @@ -741,7 +741,7 @@ layui.define(["jquery","laytpl"], function (exports) { eletreeStatus=eletreeStatus==="2" ? "0" : eletreeStatus; node.length!==0 && laytpl(TPL_ELEM(options,floor,eletreeStatus)).render([arr[len-1]], function(string){ node.children(".eleTree-node-group").append(string).children().show(); - }); + }); }); this.checkboxRender(); }, @@ -759,7 +759,7 @@ layui.define(["jquery","laytpl"], function (exports) { eletreeStatus=eletreeStatus==="2" ? "0" : eletreeStatus; node.length!==0 && laytpl(TPL_ELEM(options,floor,eletreeStatus)).render([data], function(string){ node.before(string).prev(".eleTree-node").show(); - }); + }); }); this.checkboxRender(); }, @@ -777,7 +777,7 @@ layui.define(["jquery","laytpl"], function (exports) { eletreeStatus=eletreeStatus==="2" ? "0" : eletreeStatus; node.length!==0 && laytpl(TPL_ELEM(options,floor,eletreeStatus)).render([data], function(string){ $(node).after(string).next(".eleTree-node").show(); - }); + }); }); this.checkboxRender(); // if(!options.lazy){ @@ -903,7 +903,7 @@ layui.define(["jquery","laytpl"], function (exports) { cloneNode.remove(); options.elem.css("user-select","auto"); - + // 当前点击的是否时最外层 var isCurrentOuterMost=eleNode.parent().get(0).isEqualNode(options.elem.get(0)) // 目标是否时最外层 @@ -1058,7 +1058,7 @@ layui.define(["jquery","laytpl"], function (exports) { var obj={}; obj[options.request.key]=_self.addKeyIndex; obj[options.request.name]="未命名"+_self.nameIndex; - + var arr=["Append","InsertBefore","InsertAfter"]; arr.forEach(function(val) { var s=val[0].toLocaleLowerCase()+val.slice(1,val.length); @@ -1087,7 +1087,7 @@ layui.define(["jquery","laytpl"], function (exports) { _self.addKeyIndex++; }) }) - + // 编辑 $("#tree-menu li.edit").off().on("click",function(e) { e.stopPropagation(); @@ -1204,12 +1204,12 @@ layui.define(["jquery","laytpl"], function (exports) { })){ laytpl(TPL_NoText()).render(options, function(string){ options.elem.append(string); - }); + }); }else{ options.elem.children(".eleTree-noText").remove(); } } } - + exports(MOD_NAME,eleTree); -}) \ No newline at end of file +}) diff --git a/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/config/GenConfig.java b/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/config/GenConfig.java index 982f71b4790de4c6bf4128e41e3a0e47c5e2858e..f391aee697ce45ee2af0150aae9c3766efd931fb 100644 --- a/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/config/GenConfig.java +++ b/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/config/GenConfig.java @@ -7,7 +7,7 @@ import org.springframework.stereotype.Component; /** * Describe: 读取代码相关配置 - * Author: 就 眠 仪 式 + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 * */ @Component diff --git a/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/controller/GenController.java b/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/controller/GenController.java index 29a30a4e80a53ffcdadeea114c685953e808d65e..3d608aa3588aaeb554d9d88a9396c0289b3dcc28 100644 --- a/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/controller/GenController.java +++ b/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/controller/GenController.java @@ -35,7 +35,7 @@ import com.pearadmin.generate.service.IGenTableColumnService; /** * Describe: 代码生成控制器 - * Author: 就 眠 仪 式 + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 * */ @Controller @@ -205,4 +205,4 @@ public class GenController extends BaseController { response.setContentType("application/octet-stream; charset=UTF-8"); IOUtils.write(data, response.getOutputStream()); } -} \ No newline at end of file +} diff --git a/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/domain/GenTable.java b/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/domain/GenTable.java index 23f09fe0b20b2da19598a5e16b868b6bb165f9a0..c59fa3aaac349256901d284e26b12219935d4579 100644 --- a/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/domain/GenTable.java +++ b/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/domain/GenTable.java @@ -10,7 +10,7 @@ import org.apache.ibatis.type.Alias; /** * Describe: 业务表实体 - * Author: 就 眠 仪 式 + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 * */ @ToString @@ -362,4 +362,4 @@ public class GenTable extends BaseDomain } return StringUtils.equalsAnyIgnoreCase(javaField, GenerateConstant.BASE_ENTITY); } -} \ No newline at end of file +} diff --git a/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/domain/GenTableColumn.java b/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/domain/GenTableColumn.java index ea5b9a89131b81eb0a3b3c737da0280aac48c991..56d3b3b564f14282d1d5f729d5f1473b06819e27 100644 --- a/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/domain/GenTableColumn.java +++ b/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/domain/GenTableColumn.java @@ -6,7 +6,7 @@ import org.apache.ibatis.type.Alias; /** * Describe: 业务表字段实体 - * Author: 就 眠 仪 式 + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 * */ @Alias("GenTableColumn") @@ -370,4 +370,4 @@ public class GenTableColumn extends BaseDomain return this.columnComment; } } -} \ No newline at end of file +} diff --git a/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/mapper/GenTableColumnMapper.java b/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/mapper/GenTableColumnMapper.java index a5f833661a9ef51edf23d1efbc81dec822505a2c..a8c210c707fcd551824f4caab268c36201eb393e 100644 --- a/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/mapper/GenTableColumnMapper.java +++ b/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/mapper/GenTableColumnMapper.java @@ -6,7 +6,7 @@ import java.util.List; /** * Describe: 业务表字段接口 - * Author: 就眠仪式 + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 * */ @Mapper @@ -14,15 +14,15 @@ public interface GenTableColumnMapper { /** * 根据表名称查询列信息 - * + * * @param tableName 表名称 * @return 列信息 */ List selectDbTableColumnsByName(String tableName); - + /** * 查询业务字段列表 - * + * * @param genTableColumn 业务字段信息 * @return 业务字段集合 */ @@ -30,7 +30,7 @@ public interface GenTableColumnMapper /** * 新增业务字段 - * + * * @param genTableColumn 业务字段信息 * @return 结果 */ @@ -38,7 +38,7 @@ public interface GenTableColumnMapper /** * 修改业务字段 - * + * * @param genTableColumn 业务字段信息 * @return 结果 */ @@ -46,9 +46,9 @@ public interface GenTableColumnMapper /** * 批量删除业务字段 - * + * * @param ids 需要删除的数据ID * @return 结果 */ int deleteGenTableColumnByIds(String[] ids); -} \ No newline at end of file +} diff --git a/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/mapper/GenTableMapper.java b/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/mapper/GenTableMapper.java index 4d5d3caec4788c32bd0328b4252c2017c3a44e21..e0183c35fbd39d9d7c32c61ba001af55f1ade818 100644 --- a/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/mapper/GenTableMapper.java +++ b/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/mapper/GenTableMapper.java @@ -7,7 +7,7 @@ import java.util.List; /** * Describe: 业务表接口 - * Author: 就眠仪式 + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 * */ @Mapper @@ -15,7 +15,7 @@ public interface GenTableMapper { /** * 查询业务列表 - * + * * @param genTable 业务信息 * @return 业务集合 */ @@ -23,7 +23,7 @@ public interface GenTableMapper /** * 查询据库列表 - * + * * @param genTable 业务信息 * @return 数据库表集合 */ @@ -31,7 +31,7 @@ public interface GenTableMapper /** * 查询据库列表 - * + * * @param tableNames 表名称组 * @return 数据库表集合 */ @@ -39,14 +39,14 @@ public interface GenTableMapper /** * 查询所有表信息 - * + * * @return 表信息集合 */ List selectGenTableAll(); /** * 查询表ID业务信息 - * + * * @param id 业务ID * @return 业务信息 */ @@ -62,7 +62,7 @@ public interface GenTableMapper /** * 查询表名称业务信息 - * + * * @param tableName 表名称 * @return 业务信息 */ @@ -70,7 +70,7 @@ public interface GenTableMapper /** * 新增业务 - * + * * @param genTable 业务信息 * @return 结果 */ @@ -78,7 +78,7 @@ public interface GenTableMapper /** * 修改业务 - * + * * @param genTable 业务信息 * @return 结果 */ @@ -86,9 +86,9 @@ public interface GenTableMapper /** * 批量删除业务 - * + * * @param ids 需要删除的数据ID * @return 结果 */ int deleteGenTableByIds(String[] ids); -} \ No newline at end of file +} diff --git a/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/service/IGenTableColumnService.java b/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/service/IGenTableColumnService.java index 923f1af3c2076ff5f6a7be4c8a7cc4d68e317ab0..da4337e2db041a5217ba263b8f9dac70c6a0f4eb 100644 --- a/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/service/IGenTableColumnService.java +++ b/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/service/IGenTableColumnService.java @@ -5,14 +5,14 @@ import java.util.List; /** * Describe: 业务表字段服务层 - * Author: 就眠仪式 + * @@author 就眠仪式 * CreateTime: 2019/10/23 * */ public interface IGenTableColumnService { /** * 查询业务字段列表 - * + * * @param genTableColumn 业务字段信息 * @return 业务字段集合 */ @@ -20,7 +20,7 @@ public interface IGenTableColumnService /** * 新增业务字段 - * + * * @param genTableColumn 业务字段信息 * @return 结果 */ @@ -28,7 +28,7 @@ public interface IGenTableColumnService /** * 修改业务字段 - * + * * @param genTableColumn 业务字段信息 * @return 结果 */ @@ -36,7 +36,7 @@ public interface IGenTableColumnService /** * 删除业务字段信息 - * + * * @param ids 需要删除的数据ID * @return 结果 */ diff --git a/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/service/IGenTableService.java b/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/service/IGenTableService.java index 88a8d78b16a875d5e9f33c61280f9255fff1dc4d..2d865180a95822f3bc0eb8bfdae64ab5f215b5ff 100644 --- a/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/service/IGenTableService.java +++ b/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/service/IGenTableService.java @@ -6,14 +6,14 @@ import java.util.Map; /** * Describe: 业务表服务接口 - * Author: 就眠仪式 + * @@author 就眠仪式 * CreateTime: 2019/10/23 * */ public interface IGenTableService { /** * 查询业务列表 - * + * * @param genTable 业务信息 * @return 业务集合 */ @@ -21,7 +21,7 @@ public interface IGenTableService /** * 查询据库列表 - * + * * @param genTable 业务信息 * @return 数据库表集合 */ @@ -29,7 +29,7 @@ public interface IGenTableService /** * 查询据库列表 - * + * * @param tableNames 表名称组 * @return 数据库表集合 */ @@ -37,14 +37,14 @@ public interface IGenTableService /** * 查询所有表信息 - * + * * @return 表信息集合 */ List selectGenTableAll(); /** * 查询业务信息 - * + * * @param id 业务ID * @return 业务信息 */ @@ -52,7 +52,7 @@ public interface IGenTableService /** * 修改业务 - * + * * @param genTable 业务信息 * @return 结果 */ @@ -60,7 +60,7 @@ public interface IGenTableService /** * 删除业务信息 - * + * * @param ids 需要删除的数据ID * @return 结果 */ @@ -68,7 +68,7 @@ public interface IGenTableService /** * 导入表结构 - * + * * @param tableList 导入表列表 * @param operName 操作人员 */ @@ -76,7 +76,7 @@ public interface IGenTableService /** * 预览代码 - * + * * @param tableId 表编号 * @return 预览数据列表 */ @@ -84,7 +84,7 @@ public interface IGenTableService /** * 生成代码(下载方式) - * + * * @param tableName 表名称 * @return 数据 */ @@ -92,7 +92,7 @@ public interface IGenTableService /** * 生成代码(自定义路径) - * + * * @param tableName 表名称 * @return 数据 */ @@ -100,7 +100,7 @@ public interface IGenTableService /** * 批量生成代码(下载方式) - * + * * @param tableNames 表数组 * @return 数据 */ @@ -108,7 +108,7 @@ public interface IGenTableService /** * 修改保存参数校验 - * + * * @param genTable 业务信息 */ void validateEdit(GenTable genTable); diff --git a/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/service/impl/GenTableColumnServiceImpl.java b/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/service/impl/GenTableColumnServiceImpl.java index 1baa3d750fa4f463e09bff6482af39d95bc25abd..e7708bd1c8e8923b5ab17ce0c7e9fda6d05bffe0 100644 --- a/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/service/impl/GenTableColumnServiceImpl.java +++ b/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/service/impl/GenTableColumnServiceImpl.java @@ -10,7 +10,7 @@ import javax.annotation.Resource; /** * Describe: 业务表字段服务实现 - * Author: 就眠仪式 + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 * */ @Service @@ -21,7 +21,7 @@ public class GenTableColumnServiceImpl implements IGenTableColumnService /** * 查询业务字段列表 - * + * * @param genTableColumn 业务字段信息 * @return 业务字段集合 */ @@ -33,7 +33,7 @@ public class GenTableColumnServiceImpl implements IGenTableColumnService /** * 新增业务字段 - * + * * @param genTableColumn 业务字段信息 * @return 结果 */ @@ -45,7 +45,7 @@ public class GenTableColumnServiceImpl implements IGenTableColumnService /** * 修改业务字段 - * + * * @param genTableColumn 业务字段信息 * @return 结果 */ @@ -57,7 +57,7 @@ public class GenTableColumnServiceImpl implements IGenTableColumnService /** * 删除业务字段对象 - * + * * @param ids 需要删除的数据ID * @return 结果 */ @@ -66,4 +66,4 @@ public class GenTableColumnServiceImpl implements IGenTableColumnService { return genTableColumnMapper.deleteGenTableColumnByIds(Convert.toStrArray(ids)); } -} \ No newline at end of file +} diff --git a/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/service/impl/GenTableServiceImpl.java b/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/service/impl/GenTableServiceImpl.java index 6d57b06fd1b522d81b137b1779307e71bb36b793..f22599c38f264d028f02a71c05e2f9029a64593e 100644 --- a/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/service/impl/GenTableServiceImpl.java +++ b/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/service/impl/GenTableServiceImpl.java @@ -41,7 +41,7 @@ import javax.annotation.Resource; /** * Describe: 业务表服务实现 - * Author: 就眠仪式 + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 * */ @Service @@ -57,7 +57,7 @@ public class GenTableServiceImpl implements IGenTableService /** * 查询业务信息 - * + * * @param id 业务ID * @return 业务信息 */ @@ -71,7 +71,7 @@ public class GenTableServiceImpl implements IGenTableService /** * 查询业务列表 - * + * * @param genTable 业务信息 * @return 业务集合 */ @@ -83,7 +83,7 @@ public class GenTableServiceImpl implements IGenTableService /** * 查询据库列表 - * + * * @param genTable 业务信息 * @return 数据库表集合 */ @@ -95,7 +95,7 @@ public class GenTableServiceImpl implements IGenTableService /** * 查询据库列表 - * + * * @param tableNames 表名称组 * @return 数据库表集合 */ @@ -107,7 +107,7 @@ public class GenTableServiceImpl implements IGenTableService /** * 查询所有表信息 - * + * * @return 表信息集合 */ @Override @@ -118,7 +118,7 @@ public class GenTableServiceImpl implements IGenTableService /** * 修改业务 - * + * * @param genTable 业务信息 * @return 结果 */ @@ -140,7 +140,7 @@ public class GenTableServiceImpl implements IGenTableService /** * 删除业务对象 - * + * * @param ids 需要删除的数据ID * @return 结果 */ @@ -154,7 +154,7 @@ public class GenTableServiceImpl implements IGenTableService /** * 导入表结构 - * + * * @param tableList 导入表列表 * @param operName 操作人员 */ @@ -189,7 +189,7 @@ public class GenTableServiceImpl implements IGenTableService /** * 预览代码 - * + * * @param tableId 表编号 * @return 预览数据列表 */ @@ -222,7 +222,7 @@ public class GenTableServiceImpl implements IGenTableService /** * 生成代码(下载方式) - * + * * @param tableName 表名称 * @return 数据 */ @@ -235,10 +235,10 @@ public class GenTableServiceImpl implements IGenTableService IOUtils.closeQuietly(zip); return outputStream.toByteArray(); } - + /** * 生成代码(自定义路径) - * + * * @param tableName 表名称 * @return 数据 */ @@ -284,7 +284,7 @@ public class GenTableServiceImpl implements IGenTableService /** * 批量生成代码 - * + * * @param tableNames 表数组 * @return 数据 */ @@ -339,7 +339,7 @@ public class GenTableServiceImpl implements IGenTableService /** * 修改保存参数校验 - * + * * @param genTable 业务信息 */ @Override @@ -377,7 +377,7 @@ public class GenTableServiceImpl implements IGenTableService /** * 设置主键列信息 - * + * * @param table 业务表信息 */ public void setPkColumn(GenTable table) @@ -413,7 +413,7 @@ public class GenTableServiceImpl implements IGenTableService /** * 设置主子表信息 - * + * * @param table 业务表信息 */ public void setSubTable(GenTable table) @@ -427,7 +427,7 @@ public class GenTableServiceImpl implements IGenTableService /** * 设置代码生成其他选项值 - * + * * @param genTable 设置后的生成对象 */ public void setTableFromOptions(GenTable genTable) @@ -450,7 +450,7 @@ public class GenTableServiceImpl implements IGenTableService /** * 获取代码生成地址 - * + * * @param table 业务表信息 * @param template 模板文件路径 * @return 生成地址 @@ -464,4 +464,4 @@ public class GenTableServiceImpl implements IGenTableService } return genPath + File.separator + VelocityUtils.getFileName(template, table); } -} \ No newline at end of file +} diff --git a/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/util/GenUtils.java b/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/util/GenUtils.java index a4c284c1c9b9916751ebfc8ef1124cfd98ebdfd4..154e07680cd4b8cdea744f345dc61e5e94beb486 100644 --- a/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/util/GenUtils.java +++ b/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/util/GenUtils.java @@ -10,7 +10,7 @@ import org.apache.commons.lang3.RegExUtils; /** * Describe: 代码生成工具类 - * Author: 就 眠 仪 式 + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 * */ public class GenUtils diff --git a/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/util/VelocityInitializer.java b/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/util/VelocityInitializer.java index 26c71ee3dcdd5156a9d947e221002617d7175404..90b11111c16a7860e6b0d69c2ae2817be0495115 100644 --- a/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/util/VelocityInitializer.java +++ b/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/util/VelocityInitializer.java @@ -7,7 +7,7 @@ import org.apache.velocity.app.Velocity; /** * Describe: 模板引擎工厂 - * Author: 就 眠 仪 式 + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 * */ public class VelocityInitializer diff --git a/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/util/VelocityUtils.java b/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/util/VelocityUtils.java index cc6a5356833d3c17d66344c0c634e1364c83c86d..33c58d5f0d46e143833832ab92c81c8260703d95 100644 --- a/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/util/VelocityUtils.java +++ b/pear-modules/pear-generate/src/main/java/com/pearadmin/generate/util/VelocityUtils.java @@ -15,7 +15,7 @@ import com.alibaba.fastjson.JSONObject; /** * Describe: 模板引擎工具 - * Author: 就 眠 仪 式 + * @author 就 眠 仪 式 * CreateTime: 2019/10/23 * */ public class VelocityUtils diff --git a/pear-modules/pear-generate/src/main/resources/generate.yml b/pear-modules/pear-generate/src/main/resources/generate.yml index 3cbc52359359313c73d66553f6ac20f66ce5ec56..9465f589a9c008ff17dfafcaa8c1be8320d315df 100644 --- a/pear-modules/pear-generate/src/main/resources/generate.yml +++ b/pear-modules/pear-generate/src/main/resources/generate.yml @@ -1,11 +1,11 @@ # 代码生成 -gen: +gen: # 作者 - author: jmys + @author jmys # 默认生成包路径 system 需改成自己的模块名称 如 system monitor tool packageName: com.pearadmin.system # 自动去除表前缀,默认是false autoRemovePre: false # 表前缀(生成类名不会包含表前缀,多个用逗号分隔) - tablePrefix: sys_ \ No newline at end of file + tablePrefix: sys_ diff --git a/pear-modules/pear-process/src/main/java/com/pearadmin/process/controller/ProDefinedController.java b/pear-modules/pear-process/src/main/java/com/pearadmin/process/controller/ProDefinedController.java index 693c488c0ce7d7d46d5f858ce955acc036af0275..b53068631fd0b0ec78725c19daca484b28db19c2 100644 --- a/pear-modules/pear-process/src/main/java/com/pearadmin/process/controller/ProDefinedController.java +++ b/pear-modules/pear-process/src/main/java/com/pearadmin/process/controller/ProDefinedController.java @@ -23,7 +23,8 @@ import java.util.List; /** * Describe: 流程定义控制器 - * Author: 就眠仪式 + * + * @author 就 眠 仪 式 * createTime: 2019/10/23 */ @RestController diff --git a/pear-modules/pear-process/src/main/java/com/pearadmin/process/controller/ProModelController.java b/pear-modules/pear-process/src/main/java/com/pearadmin/process/controller/ProModelController.java index 1169c8a12c6b0f6d86450f74cb0c9c96adff3126..7eff9d5e5224ee7f912cf7dc316765a182bb0897 100644 --- a/pear-modules/pear-process/src/main/java/com/pearadmin/process/controller/ProModelController.java +++ b/pear-modules/pear-process/src/main/java/com/pearadmin/process/controller/ProModelController.java @@ -28,9 +28,10 @@ import java.util.List; /** * Describe: 流程模型控制器 - * Author: 就眠仪式 + * + * @author 就 眠 仪 式 * createTime: 2019/10/23 - * */ + */ @RestController @RequestMapping(ControllerConstant.API_PROCESS_PREFIX + "model") public class ProModelController extends BaseController { @@ -47,11 +48,10 @@ public class ProModelController extends BaseController { * Describe: 获取流程模型列表视图 * Param: modelAndView * Return: 流程模型列表视图 - * */ + */ @GetMapping("main") - public ModelAndView view(ModelAndView modelAndView) - { - modelAndView.setViewName(modelPath+"main"); + public ModelAndView view(ModelAndView modelAndView) { + modelAndView.setViewName(modelPath + "main"); return modelAndView; } @@ -59,10 +59,10 @@ public class ProModelController extends BaseController { * Describe: 获取流程编辑器视图 * Param: modelAndView * Return: 流程编辑视图 - * */ + */ @GetMapping("editor") - public ModelAndView editor(ModelAndView modelAndView){ - modelAndView.setViewName(modelPath+"editor"); + public ModelAndView editor(ModelAndView modelAndView) { + modelAndView.setViewName(modelPath + "editor"); return modelAndView; } @@ -70,14 +70,14 @@ public class ProModelController extends BaseController { * Describe: 获取流程模型列表数据 * Param: modelAndView * Return: ResultTable - * */ + */ @GetMapping("data") - public ResultTable list(PageDomain pageDomain,String modelName){ + public ResultTable list(PageDomain pageDomain, String modelName) { ModelQuery modelQuery = repositoryService.createModelQuery(); - if (StringUtils.hasText(modelName)){ + if (StringUtils.hasText(modelName)) { modelQuery.modelNameLike(modelName); } - List list = modelQuery.listPage(pageDomain.start(),pageDomain.end()); + List list = modelQuery.listPage(pageDomain.start(), pageDomain.end()); List data = new ArrayList<>(); list.forEach(model -> { @@ -90,17 +90,17 @@ public class ProModelController extends BaseController { }); long count = modelQuery.list().size(); - return pageTable(data,count); + return pageTable(data, count); } /** * Describe: 流程创建视图 * Param: modelAndView * Return: 流程创建视图 - * */ + */ @GetMapping("add") - public ModelAndView add(ModelAndView modelAndView){ - modelAndView.setViewName(modelPath+"add"); + public ModelAndView add(ModelAndView modelAndView) { + modelAndView.setViewName(modelPath + "add"); return modelAndView; } @@ -108,7 +108,7 @@ public class ProModelController extends BaseController { * Describe: 创建流程图 * Param: createModelParam * Return: Result - * */ + */ @PostMapping("create") public Result create(@RequestBody CreateModelParam param) throws IOException { Model model = repositoryService.newModel(); @@ -128,18 +128,18 @@ public class ProModelController extends BaseController { * Describe: 创建流程图节点信息 * Param: modelId * Return: null - * */ - private void createObjectNode(String modelId){ + */ + private void createObjectNode(String modelId) { ObjectNode editorNode = objectMapper.createObjectNode(); editorNode.put("id", "canvas"); editorNode.put("resourceId", "canvas"); ObjectNode stencilSetNode = objectMapper.createObjectNode(); - stencilSetNode.put("namespace","http://b3mn.org/stencilset/bpmn2.0#"); + stencilSetNode.put("namespace", "http://b3mn.org/stencilset/bpmn2.0#"); editorNode.put("stencilset", stencilSetNode); try { - repositoryService.addModelEditorSource(modelId,editorNode.toString().getBytes("utf-8")); + repositoryService.addModelEditorSource(modelId, editorNode.toString().getBytes("utf-8")); } catch (Exception e) { - System.out.println("创建模型时完善ModelEditorSource服务异常:"+e); + System.out.println("创建模型时完善ModelEditorSource服务异常:" + e); } System.out.println("创建模型完善ModelEditorSource结束"); } @@ -148,9 +148,9 @@ public class ProModelController extends BaseController { * Describe: 根据 Id 删除流程图 * Param: modelId * Return: Result - * */ + */ @PostMapping("deleteById") - public Result deleteById(String modelId){ + public Result deleteById(String modelId) { repositoryService.deleteModel(modelId); return success("删除成功"); } @@ -159,10 +159,10 @@ public class ProModelController extends BaseController { * Describe: 发布流程 * Param: modelId * Return: Result - * */ + */ @ResponseBody @RequestMapping("/publish") - public Result publish(String modelId){ + public Result publish(String modelId) { try { Model modelData = repositoryService.getModel(modelId); byte[] bytes = repositoryService.getModelEditorSource(modelData.getId()); @@ -173,7 +173,7 @@ public class ProModelController extends BaseController { BpmnModel model = new BpmnJsonConverter().convertToBpmnModel(modelNode); Deployment deployment = repositoryService.createDeployment() .name(modelData.getName()) - .addBpmnModel(modelData.getKey()+".bpmn20.xml", model) + .addBpmnModel(modelData.getKey() + ".bpmn20.xml", model) .deploy(); modelData.setDeploymentId(deployment.getId()); repositoryService.saveModel(modelData); diff --git a/pear-modules/pear-process/src/main/java/com/pearadmin/process/domain/ProDefined.java b/pear-modules/pear-process/src/main/java/com/pearadmin/process/domain/ProDefined.java index dddf1a91265687a08d788de91b38e62b2e3c10d4..051db61d32937fbf6df92deedb483cf7644f3ffd 100644 --- a/pear-modules/pear-process/src/main/java/com/pearadmin/process/domain/ProDefined.java +++ b/pear-modules/pear-process/src/main/java/com/pearadmin/process/domain/ProDefined.java @@ -5,45 +5,46 @@ import lombok.Data; /** * Describe: 流程定义实体 - * Author: 就眠仪式 + * + * @author 就 眠 仪 式 * createTime: 2019/10/23 - * */ + */ @Data public class ProDefined extends BaseDomain { /** * 流程定义编号 - * */ + */ private String id; /** * 流程定义名称 - * */ + */ private String name; /** * 流程定义标识 - * */ + */ private String key; /** * 流程定义版本 - * */ + */ private int version; /** * xml 资源文件名称 - * */ + */ private String bpmn; /** * png 资源文件名称 - * */ + */ private String png; /** * 部署 Id - * */ + */ private String deploymentId; } diff --git a/pear-modules/pear-process/src/main/java/com/pearadmin/process/domain/ProModel.java b/pear-modules/pear-process/src/main/java/com/pearadmin/process/domain/ProModel.java index 594cef159bb15393aa1cd157ec76d74f0eb14191..2c9f9cb7feb1f8d5280f5b9b6aa3e622ff8c360d 100644 --- a/pear-modules/pear-process/src/main/java/com/pearadmin/process/domain/ProModel.java +++ b/pear-modules/pear-process/src/main/java/com/pearadmin/process/domain/ProModel.java @@ -5,29 +5,30 @@ import lombok.Data; /** * Describe: 流程模型实体 - * Author: 就眠仪式 + * + * @author 就 眠 仪 式 * createTime: 2019/10/23 - * */ + */ @Data public class ProModel extends BaseDomain { - /** - * 编号 - * */ - private String id; + /** + * 编号 + */ + private String id; - /** - * 名称 - * */ - private String name; + /** + * 名称 + */ + private String name; - /** - * 标识 - * */ - private String key; + /** + * 标识 + */ + private String key; - /** - * 版本 - * */ - private Integer version; + /** + * 版本 + */ + private Integer version; } diff --git a/pear-modules/pear-process/src/main/java/com/pearadmin/process/param/CreateModelParam.java b/pear-modules/pear-process/src/main/java/com/pearadmin/process/param/CreateModelParam.java index a217eb9e45c22707fbf7b301f409522afa3f79d7..8fe32fc480dc83840669d01cdef0e6d83de37de7 100644 --- a/pear-modules/pear-process/src/main/java/com/pearadmin/process/param/CreateModelParam.java +++ b/pear-modules/pear-process/src/main/java/com/pearadmin/process/param/CreateModelParam.java @@ -4,30 +4,31 @@ import lombok.Data; /** * Describe: 模型创建实体 - * Author: 就眠仪式 + * + * @author 就 眠 仪 式 * createTime: 2019/10/23 - * */ + */ @Data public class CreateModelParam { - /** - * 模板名称 - * */ - private String name; + /** + * 模板名称 + */ + private String name; - /** - * 模板标识 - * */ - private String key; + /** + * 模板标识 + */ + private String key; - /** - * 模板标识 - * */ - private String description; + /** + * 模板标识 + */ + private String description; - /** - * 模板版本 - * */ - private String version; + /** + * 模板版本 + */ + private String version; } diff --git a/pear-modules/pear-process/src/main/java/com/pearadmin/process/resource/ModelEditorJsonRestResource.java b/pear-modules/pear-process/src/main/java/com/pearadmin/process/resource/ModelEditorJsonRestResource.java index be310bed095d27c1ec4b9b334eb613603e9b9184..3e4cf222f09fc340f450496cf9a34a2d33711122 100644 --- a/pear-modules/pear-process/src/main/java/com/pearadmin/process/resource/ModelEditorJsonRestResource.java +++ b/pear-modules/pear-process/src/main/java/com/pearadmin/process/resource/ModelEditorJsonRestResource.java @@ -15,7 +15,9 @@ import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; import java.nio.charset.StandardCharsets; - +/** + * @author 就 眠 仪 式 + */ @RestController @RequestMapping("service") public class ModelEditorJsonRestResource implements ModelDataJsonConstants { @@ -26,7 +28,7 @@ public class ModelEditorJsonRestResource implements ModelDataJsonConstants { @Resource private ObjectMapper objectMapper; - @RequestMapping(value="/model/{modelId}/json", method = RequestMethod.GET, produces = "application/json") + @RequestMapping(value = "/model/{modelId}/json", method = RequestMethod.GET, produces = "application/json") public ObjectNode getEditorJson(@PathVariable String modelId) { ObjectNode modelNode = null; Model model = repositoryService.getModel(modelId); diff --git a/pear-modules/pear-process/src/main/java/com/pearadmin/process/resource/ModelEditorSaveRestResource.java b/pear-modules/pear-process/src/main/java/com/pearadmin/process/resource/ModelEditorSaveRestResource.java index 8302b88dc34640da044a46493eb5098a0a11a9b0..f5ac89ab8dec5f29b66dd854692064593f31145c 100644 --- a/pear-modules/pear-process/src/main/java/com/pearadmin/process/resource/ModelEditorSaveRestResource.java +++ b/pear-modules/pear-process/src/main/java/com/pearadmin/process/resource/ModelEditorSaveRestResource.java @@ -11,12 +11,16 @@ import org.apache.batik.transcoder.TranscoderOutput; import org.apache.batik.transcoder.image.PNGTranscoder; import org.springframework.http.HttpStatus; import org.springframework.web.bind.annotation.*; + import javax.annotation.Resource; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.nio.charset.StandardCharsets; +/** + * @author 就 眠 仪 式 + */ @RestController @RequestMapping("service") public class ModelEditorSaveRestResource implements ModelDataJsonConstants { @@ -29,13 +33,14 @@ public class ModelEditorSaveRestResource implements ModelDataJsonConstants { /** * 保存流程 - * @param modelId 模型ID - * @param name 流程模型名称 + * + * @param modelId 模型ID + * @param name 流程模型名称 * @param description - * @param json_xml 流程文件 - * @param svg_xml 图片 + * @param json_xml 流程文件 + * @param svg_xml 图片 */ - @RequestMapping(value="/model/{modelId}/save", method = RequestMethod.PUT) + @RequestMapping(value = "/model/{modelId}/save", method = RequestMethod.PUT) @ResponseStatus(value = HttpStatus.OK) public void saveModel(@PathVariable String modelId, String name, String description, String json_xml, String svg_xml) { try { diff --git a/pear-modules/pear-process/src/main/java/com/pearadmin/process/resource/ModelEditorToolRestResource.java b/pear-modules/pear-process/src/main/java/com/pearadmin/process/resource/ModelEditorToolRestResource.java index 667c91499a1d13c4882628ea91da9848fd805462..0d1b8e59f39716cb3a6f0dfd1a25ae2ec8591351 100644 --- a/pear-modules/pear-process/src/main/java/com/pearadmin/process/resource/ModelEditorToolRestResource.java +++ b/pear-modules/pear-process/src/main/java/com/pearadmin/process/resource/ModelEditorToolRestResource.java @@ -2,17 +2,23 @@ package com.pearadmin.process.resource; import org.activiti.engine.ActivitiException; import org.apache.commons.io.IOUtils; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; import java.io.InputStream; import java.nio.charset.StandardCharsets; +/** + * @author 就 眠 仪 式 + */ @RestController @RequestMapping("service") public class ModelEditorToolRestResource { @ResponseBody - @GetMapping(value="/editor/stencilset", produces = "application/json;charset=utf-8") + @GetMapping(value = "/editor/stencilset", produces = "application/json;charset=utf-8") public String getStencilset() { InputStream stencilsetStream = this.getClass().getClassLoader().getResourceAsStream("stencilset.json"); try { diff --git a/pear-modules/pear-process/src/main/resources/static/editor-app/app-cfg.js b/pear-modules/pear-process/src/main/resources/static/editor-app/app-cfg.js index fef58bb28d6a85749d40cd502c5159c4b9902e9d..ec9413e81560fc9a918144d591e775a67e550a56 100644 --- a/pear-modules/pear-process/src/main/resources/static/editor-app/app-cfg.js +++ b/pear-modules/pear-process/src/main/resources/static/editor-app/app-cfg.js @@ -1,7 +1,7 @@ /* * Activiti Modeler component part of the Activiti project * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either @@ -21,5 +21,5 @@ var ACTIVITI = ACTIVITI || {}; ACTIVITI.CONFIG = { - 'contextRoot' : '/service', + 'contextRoot': '/service', }; diff --git a/pear-modules/pear-process/src/main/resources/static/editor-app/app.js b/pear-modules/pear-process/src/main/resources/static/editor-app/app.js index cd43b167e41c2996b941fe1df29288b05caa6188..c7f5b2fed85943f7eef0300cbbc146d433b56282 100644 --- a/pear-modules/pear-process/src/main/resources/static/editor-app/app.js +++ b/pear-modules/pear-process/src/main/resources/static/editor-app/app.js @@ -1,7 +1,7 @@ /* * Activiti Modeler component part of the Activiti project * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either @@ -19,29 +19,29 @@ 'use strict'; var activitiModeler = angular.module('activitiModeler', [ - 'ngCookies', - 'ngResource', - 'ngSanitize', - 'ngRoute', - 'ngDragDrop', - 'mgcrea.ngStrap', - 'ngGrid', - 'ngAnimate', - 'pascalprecht.translate', - 'duScroll' + 'ngCookies', + 'ngResource', + 'ngSanitize', + 'ngRoute', + 'ngDragDrop', + 'mgcrea.ngStrap', + 'ngGrid', + 'ngAnimate', + 'pascalprecht.translate', + 'duScroll' ]); var activitiModule = activitiModeler; activitiModeler - // Initialize routes - .config(['$selectProvider', '$translateProvider', function ($selectProvider, $translateProvider) { - - // Override caret for bs-select directive - angular.extend($selectProvider.defaults, { - caretHtml: ' ' - }); - + // Initialize routes + .config(['$selectProvider', '$translateProvider', function ($selectProvider, $translateProvider) { + + // Override caret for bs-select directive + angular.extend($selectProvider.defaults, { + caretHtml: ' ' + }); + // Initialize angular-translate $translateProvider.useStaticFilesLoader({ prefix: '../../editor-app/i18n/', @@ -52,40 +52,40 @@ activitiModeler // remember language $translateProvider.useCookieStorage(); - - }]) - .run(['$rootScope', '$timeout', '$modal', '$translate', '$location', '$window', '$http', '$q', - function($rootScope, $timeout, $modal, $translate, $location, $window, $http, $q) { - - $rootScope.config = ACTIVITI.CONFIG; - - $rootScope.editorInitialized = false; - - $rootScope.editorFactory = $q.defer(); - - $rootScope.forceSelectionRefresh = false; - - $rootScope.ignoreChanges = false; // by default never ignore changes - - $rootScope.validationErrors = []; - - $rootScope.staticIncludeVersion = Date.now(); - - /** - * A 'safer' apply that avoids concurrent updates (which $apply allows). - */ - $rootScope.safeApply = function(fn) { - var phase = this.$root.$$phase; - if(phase == '$apply' || phase == '$digest') { - if(fn && (typeof(fn) === 'function')) { - fn(); - } - } else { - this.$apply(fn); - } - }; - - + + }]) + .run(['$rootScope', '$timeout', '$modal', '$translate', '$location', '$window', '$http', '$q', + function ($rootScope, $timeout, $modal, $translate, $location, $window, $http, $q) { + + $rootScope.config = ACTIVITI.CONFIG; + + $rootScope.editorInitialized = false; + + $rootScope.editorFactory = $q.defer(); + + $rootScope.forceSelectionRefresh = false; + + $rootScope.ignoreChanges = false; // by default never ignore changes + + $rootScope.validationErrors = []; + + $rootScope.staticIncludeVersion = Date.now(); + + /** + * A 'safer' apply that avoids concurrent updates (which $apply allows). + */ + $rootScope.safeApply = function (fn) { + var phase = this.$root.$$phase; + if (phase == '$apply' || phase == '$digest') { + if (fn && (typeof (fn) === 'function')) { + fn(); + } + } else { + this.$apply(fn); + } + }; + + /** * Initialize the event bus: couple all Oryx events with a dispatch of the * event of the event bus. This way, it gets much easier to attach custom logic @@ -97,21 +97,19 @@ activitiModeler var modelUrl = KISBPM.URL.getModel(modelId); - $http({method: 'GET', url: modelUrl}). - success(function (data, status, headers, config) { - $rootScope.editor = new ORYX.Editor(data); - $rootScope.modelData = angular.fromJson(data); - $rootScope.editorFactory.resolve(); - }). - error(function (data, status, headers, config) { - console.log('Error loading model with id ' + modelId + ' ' + data); - }); + $http({method: 'GET', url: modelUrl}).success(function (data, status, headers, config) { + $rootScope.editor = new ORYX.Editor(data); + $rootScope.modelData = angular.fromJson(data); + $rootScope.editorFactory.resolve(); + }).error(function (data, status, headers, config) { + console.log('Error loading model with id ' + modelId + ' ' + data); + }); } function initScrollHandling() { var canvasSection = jQuery('#canvasSection'); - canvasSection.scroll(function() { + canvasSection.scroll(function () { // Hides the resizer and quick menu items during scrolling @@ -121,26 +119,26 @@ activitiModeler $rootScope.selectedElements = selectedElements; $rootScope.subSelectionElements = subSelectionElements; if (selectedElements && selectedElements.length > 0) { - $rootScope.selectedElementBeforeScrolling = selectedElements[0]; + $rootScope.selectedElementBeforeScrolling = selectedElements[0]; } - jQuery('.Oryx_button').each(function(i, obj) { - $rootScope.orginalOryxButtonStyle = obj.style.display; - obj.style.display = 'none'; + jQuery('.Oryx_button').each(function (i, obj) { + $rootScope.orginalOryxButtonStyle = obj.style.display; + obj.style.display = 'none'; }); - - jQuery('.resizer_southeast').each(function(i, obj) { - $rootScope.orginalResizerSEStyle = obj.style.display; + + jQuery('.resizer_southeast').each(function (i, obj) { + $rootScope.orginalResizerSEStyle = obj.style.display; obj.style.display = 'none'; }); - jQuery('.resizer_northwest').each(function(i, obj) { - $rootScope.orginalResizerNWStyle = obj.style.display; + jQuery('.resizer_northwest').each(function (i, obj) { + $rootScope.orginalResizerNWStyle = obj.style.display; obj.style.display = 'none'; }); - $rootScope.editor.handleEvents({type:ORYX.CONFIG.EVENT_CANVAS_SCROLL}); + $rootScope.editor.handleEvents({type: ORYX.CONFIG.EVENT_CANVAS_SCROLL}); }); - canvasSection.scrollStopped(function(){ + canvasSection.scrollStopped(function () { // Puts the quick menu items and resizer back when scroll is stopped. @@ -157,14 +155,14 @@ activitiModeler } } - jQuery('.Oryx_button').each(function(i, obj) { + jQuery('.Oryx_button').each(function (i, obj) { handleDisplayProperty(obj); }); - - jQuery('.resizer_southeast').each(function(i, obj) { + + jQuery('.resizer_southeast').each(function (i, obj) { handleDisplayProperty(obj); }); - jQuery('.resizer_northwest').each(function(i, obj) { + jQuery('.resizer_northwest').each(function (i, obj) { handleDisplayProperty(obj); }); @@ -175,154 +173,152 @@ activitiModeler * Initialize the Oryx Editor when the content has been loaded */ $rootScope.$on('$includeContentLoaded', function (event) { - if (!$rootScope.editorInitialized) { - - ORYX._loadPlugins(); - - var modelId = EDITOR.UTIL.getParameterByName('modelId'); - fetchModel(modelId); - - $rootScope.window = {}; - var updateWindowSize = function() { - $rootScope.window.width = $window.innerWidth; - $rootScope.window.height = $window.innerHeight; - }; - - // Window resize hook - angular.element($window).bind('resize', function() { - $rootScope.safeApply(updateWindowSize()); - }); - - $rootScope.$watch('window.forceRefresh', function(newValue) { - if(newValue) { - $timeout(function() { - updateWindowSize(); - $rootScope.window.forceRefresh = false; - }); - } - }); - - updateWindowSize(); - - // Hook in resizing of main panels when window resizes - // TODO: perhaps move to a separate JS-file? - jQuery(window).resize(function () { - - // Calculate the offset based on the bottom of the module header - var offset = jQuery("#editor-header").offset(); - var propSectionHeight = jQuery('#propertySection').height(); - var canvas = jQuery('#canvasSection'); - var mainHeader = jQuery('#main-header'); - - if (offset == undefined || offset === null - || propSectionHeight === undefined || propSectionHeight === null - || canvas === undefined || canvas === null || mainHeader === null) { - return; - } - - if ($rootScope.editor) - { - var selectedElements = $rootScope.editor.selection; - var subSelectionElements = $rootScope.editor._subSelection; - - $rootScope.selectedElements = selectedElements; - $rootScope.subSelectionElements = subSelectionElements; - if (selectedElements && selectedElements.length > 0) - { - $rootScope.selectedElementBeforeScrolling = selectedElements[0]; - - $rootScope.editor.setSelection([]); // needed cause it checks for element changes and does nothing if the elements are the same - $rootScope.editor.setSelection($rootScope.selectedElements, $rootScope.subSelectionElements); - $rootScope.selectedElements = undefined; - $rootScope.subSelectionElements = undefined; - } - } - - var totalAvailable = jQuery(window).height() - offset.top - mainHeader.height() - 21; - canvas.height(totalAvailable - propSectionHeight); - jQuery('#paletteSection').height(totalAvailable); - - // Update positions of the resize-markers, according to the canvas - - var actualCanvas = null; - if (canvas && canvas[0].children[1]) { - actualCanvas = canvas[0].children[1]; - } - - var canvasTop = canvas.position().top; - var canvasLeft = canvas.position().left; - var canvasHeight = canvas[0].clientHeight; - var canvasWidth = canvas[0].clientWidth; - var iconCenterOffset = 8; - var widthDiff = 0; - - var actualWidth = 0; - if(actualCanvas) { - // In some browsers, the SVG-element clientwidth isn't available, so we revert to the parent - actualWidth = actualCanvas.clientWidth || actualCanvas.parentNode.clientWidth; - } - - - if(actualWidth < canvas[0].clientWidth) { - widthDiff = actualWidth - canvas[0].clientWidth; - // In case the canvas is smaller than the actual viewport, the resizers should be moved - canvasLeft -= widthDiff / 2; - canvasWidth += widthDiff; - } - - var iconWidth = 17; - var iconOffset = 20; - - var north = jQuery('#canvas-grow-N'); - north.css('top', canvasTop + iconOffset + 'px'); - north.css('left', canvasLeft - 10 + (canvasWidth - iconWidth) / 2 + 'px'); - - var south = jQuery('#canvas-grow-S'); - south.css('top', (canvasTop + canvasHeight - iconOffset - iconCenterOffset) + 'px'); - south.css('left', canvasLeft - 10 + (canvasWidth - iconWidth) / 2 + 'px'); - - var east = jQuery('#canvas-grow-E'); - east.css('top', canvasTop - 10 + (canvasHeight - iconWidth) / 2 + 'px'); - east.css('left', (canvasLeft + canvasWidth - iconOffset - iconCenterOffset) + 'px'); - - var west = jQuery('#canvas-grow-W'); - west.css('top', canvasTop -10 + (canvasHeight - iconWidth) / 2 + 'px'); - west.css('left', canvasLeft + iconOffset + 'px'); - - north = jQuery('#canvas-shrink-N'); - north.css('top', canvasTop + iconOffset + 'px'); - north.css('left', canvasLeft + 10 + (canvasWidth - iconWidth) / 2 + 'px'); - - south = jQuery('#canvas-shrink-S'); - south.css('top', (canvasTop + canvasHeight - iconOffset - iconCenterOffset) + 'px'); - south.css('left', canvasLeft +10 + (canvasWidth - iconWidth) / 2 + 'px'); - - east = jQuery('#canvas-shrink-E'); - east.css('top', canvasTop + 10 + (canvasHeight - iconWidth) / 2 + 'px'); - east.css('left', (canvasLeft + canvasWidth - iconOffset - iconCenterOffset) + 'px'); - - west = jQuery('#canvas-shrink-W'); - west.css('top', canvasTop + 10 + (canvasHeight - iconWidth) / 2 + 'px'); - west.css('left', canvasLeft + iconOffset + 'px'); - }); - - jQuery(window).trigger('resize'); - - jQuery.fn.scrollStopped = function(callback) { - jQuery(this).scroll(function(){ - var self = this, $this = jQuery(self); - if ($this.data('scrollTimeout')) { - clearTimeout($this.data('scrollTimeout')); - } - $this.data('scrollTimeout', setTimeout(callback,50,self)); - }); - }; - - // Always needed, cause the DOM element on which the scroll event listeners are attached are changed for every new model - initScrollHandling(); - - $rootScope.editorInitialized = true; - } + if (!$rootScope.editorInitialized) { + + ORYX._loadPlugins(); + + var modelId = EDITOR.UTIL.getParameterByName('modelId'); + fetchModel(modelId); + + $rootScope.window = {}; + var updateWindowSize = function () { + $rootScope.window.width = $window.innerWidth; + $rootScope.window.height = $window.innerHeight; + }; + + // Window resize hook + angular.element($window).bind('resize', function () { + $rootScope.safeApply(updateWindowSize()); + }); + + $rootScope.$watch('window.forceRefresh', function (newValue) { + if (newValue) { + $timeout(function () { + updateWindowSize(); + $rootScope.window.forceRefresh = false; + }); + } + }); + + updateWindowSize(); + + // Hook in resizing of main panels when window resizes + // TODO: perhaps move to a separate JS-file? + jQuery(window).resize(function () { + + // Calculate the offset based on the bottom of the module header + var offset = jQuery("#editor-header").offset(); + var propSectionHeight = jQuery('#propertySection').height(); + var canvas = jQuery('#canvasSection'); + var mainHeader = jQuery('#main-header'); + + if (offset == undefined || offset === null + || propSectionHeight === undefined || propSectionHeight === null + || canvas === undefined || canvas === null || mainHeader === null) { + return; + } + + if ($rootScope.editor) { + var selectedElements = $rootScope.editor.selection; + var subSelectionElements = $rootScope.editor._subSelection; + + $rootScope.selectedElements = selectedElements; + $rootScope.subSelectionElements = subSelectionElements; + if (selectedElements && selectedElements.length > 0) { + $rootScope.selectedElementBeforeScrolling = selectedElements[0]; + + $rootScope.editor.setSelection([]); // needed cause it checks for element changes and does nothing if the elements are the same + $rootScope.editor.setSelection($rootScope.selectedElements, $rootScope.subSelectionElements); + $rootScope.selectedElements = undefined; + $rootScope.subSelectionElements = undefined; + } + } + + var totalAvailable = jQuery(window).height() - offset.top - mainHeader.height() - 21; + canvas.height(totalAvailable - propSectionHeight); + jQuery('#paletteSection').height(totalAvailable); + + // Update positions of the resize-markers, according to the canvas + + var actualCanvas = null; + if (canvas && canvas[0].children[1]) { + actualCanvas = canvas[0].children[1]; + } + + var canvasTop = canvas.position().top; + var canvasLeft = canvas.position().left; + var canvasHeight = canvas[0].clientHeight; + var canvasWidth = canvas[0].clientWidth; + var iconCenterOffset = 8; + var widthDiff = 0; + + var actualWidth = 0; + if (actualCanvas) { + // In some browsers, the SVG-element clientwidth isn't available, so we revert to the parent + actualWidth = actualCanvas.clientWidth || actualCanvas.parentNode.clientWidth; + } + + + if (actualWidth < canvas[0].clientWidth) { + widthDiff = actualWidth - canvas[0].clientWidth; + // In case the canvas is smaller than the actual viewport, the resizers should be moved + canvasLeft -= widthDiff / 2; + canvasWidth += widthDiff; + } + + var iconWidth = 17; + var iconOffset = 20; + + var north = jQuery('#canvas-grow-N'); + north.css('top', canvasTop + iconOffset + 'px'); + north.css('left', canvasLeft - 10 + (canvasWidth - iconWidth) / 2 + 'px'); + + var south = jQuery('#canvas-grow-S'); + south.css('top', (canvasTop + canvasHeight - iconOffset - iconCenterOffset) + 'px'); + south.css('left', canvasLeft - 10 + (canvasWidth - iconWidth) / 2 + 'px'); + + var east = jQuery('#canvas-grow-E'); + east.css('top', canvasTop - 10 + (canvasHeight - iconWidth) / 2 + 'px'); + east.css('left', (canvasLeft + canvasWidth - iconOffset - iconCenterOffset) + 'px'); + + var west = jQuery('#canvas-grow-W'); + west.css('top', canvasTop - 10 + (canvasHeight - iconWidth) / 2 + 'px'); + west.css('left', canvasLeft + iconOffset + 'px'); + + north = jQuery('#canvas-shrink-N'); + north.css('top', canvasTop + iconOffset + 'px'); + north.css('left', canvasLeft + 10 + (canvasWidth - iconWidth) / 2 + 'px'); + + south = jQuery('#canvas-shrink-S'); + south.css('top', (canvasTop + canvasHeight - iconOffset - iconCenterOffset) + 'px'); + south.css('left', canvasLeft + 10 + (canvasWidth - iconWidth) / 2 + 'px'); + + east = jQuery('#canvas-shrink-E'); + east.css('top', canvasTop + 10 + (canvasHeight - iconWidth) / 2 + 'px'); + east.css('left', (canvasLeft + canvasWidth - iconOffset - iconCenterOffset) + 'px'); + + west = jQuery('#canvas-shrink-W'); + west.css('top', canvasTop + 10 + (canvasHeight - iconWidth) / 2 + 'px'); + west.css('left', canvasLeft + iconOffset + 'px'); + }); + + jQuery(window).trigger('resize'); + + jQuery.fn.scrollStopped = function (callback) { + jQuery(this).scroll(function () { + var self = this, $this = jQuery(self); + if ($this.data('scrollTimeout')) { + clearTimeout($this.data('scrollTimeout')); + } + $this.data('scrollTimeout', setTimeout(callback, 50, self)); + }); + }; + + // Always needed, cause the DOM element on which the scroll event listeners are attached are changed for every new model + initScrollHandling(); + + $rootScope.editorInitialized = true; + } }); /** @@ -331,48 +327,50 @@ activitiModeler * to any event. */ - $rootScope.editorFactory.promise.then(function() { + $rootScope.editorFactory.promise.then(function () { KISBPM.eventBus.editor = $rootScope.editor; var eventMappings = [ - { oryxType : ORYX.CONFIG.EVENT_SELECTION_CHANGED, kisBpmType : KISBPM.eventBus.EVENT_TYPE_SELECTION_CHANGE }, - { oryxType : ORYX.CONFIG.EVENT_DBLCLICK, kisBpmType : KISBPM.eventBus.EVENT_TYPE_DOUBLE_CLICK }, - { oryxType : ORYX.CONFIG.EVENT_MOUSEOUT, kisBpmType : KISBPM.eventBus.EVENT_TYPE_MOUSE_OUT }, - { oryxType : ORYX.CONFIG.EVENT_MOUSEOVER, kisBpmType : KISBPM.eventBus.EVENT_TYPE_MOUSE_OVER } + { + oryxType: ORYX.CONFIG.EVENT_SELECTION_CHANGED, + kisBpmType: KISBPM.eventBus.EVENT_TYPE_SELECTION_CHANGE + }, + {oryxType: ORYX.CONFIG.EVENT_DBLCLICK, kisBpmType: KISBPM.eventBus.EVENT_TYPE_DOUBLE_CLICK}, + {oryxType: ORYX.CONFIG.EVENT_MOUSEOUT, kisBpmType: KISBPM.eventBus.EVENT_TYPE_MOUSE_OUT}, + {oryxType: ORYX.CONFIG.EVENT_MOUSEOVER, kisBpmType: KISBPM.eventBus.EVENT_TYPE_MOUSE_OVER} ]; - eventMappings.forEach(function(eventMapping) { - $rootScope.editor.registerOnEvent(eventMapping.oryxType, function(event) { + eventMappings.forEach(function (eventMapping) { + $rootScope.editor.registerOnEvent(eventMapping.oryxType, function (event) { KISBPM.eventBus.dispatch(eventMapping.kisBpmType, event); }); }); - + $rootScope.editor.registerOnEvent(ORYX.CONFIG.EVENT_SHAPEREMOVED, function (event) { - var validateButton = document.getElementById(event.shape.resourceId + "-validate-button"); - if (validateButton) - { - validateButton.style.display = 'none'; - } + var validateButton = document.getElementById(event.shape.resourceId + "-validate-button"); + if (validateButton) { + validateButton.style.display = 'none'; + } }); // The Oryx canvas is ready (we know since we're in this promise callback) and the // event bus is ready. The editor is now ready for use - KISBPM.eventBus.dispatch(KISBPM.eventBus.EVENT_TYPE_EDITOR_READY, {type : KISBPM.eventBus.EVENT_TYPE_EDITOR_READY}); + KISBPM.eventBus.dispatch(KISBPM.eventBus.EVENT_TYPE_EDITOR_READY, {type: KISBPM.eventBus.EVENT_TYPE_EDITOR_READY}); }); - + // Alerts $rootScope.alerts = { queue: [] }; - - $rootScope.showAlert = function(alert) { - if(alert.queue.length > 0) { + + $rootScope.showAlert = function (alert) { + if (alert.queue.length > 0) { alert.current = alert.queue.shift(); // Start timout for message-pruning - alert.timeout = $timeout(function() { + alert.timeout = $timeout(function () { if (alert.queue.length == 0) { alert.current = undefined; alert.timeout = undefined; @@ -384,8 +382,8 @@ activitiModeler $rootScope.alerts.current = undefined; } }; - - $rootScope.addAlert = function(message, type) { + + $rootScope.addAlert = function (message, type) { var newAlert = {message: message, type: type}; if (!$rootScope.alerts.timeout) { // Timeout for message queue is not running, start one @@ -395,8 +393,8 @@ activitiModeler $rootScope.alerts.queue.push(newAlert); } }; - - $rootScope.dismissAlert = function() { + + $rootScope.dismissAlert = function () { if (!$rootScope.alerts.timeout) { $rootScope.alerts.current = undefined; } else { @@ -405,21 +403,21 @@ activitiModeler $rootScope.showAlert($rootScope.alerts); } }; - - $rootScope.addAlertPromise = function(promise, type) { + + $rootScope.addAlertPromise = function (promise, type) { if (promise) { - promise.then(function(data) { + promise.then(function (data) { $rootScope.addAlert(data, type); }); } }; - + } - ]) + ]) // Moment-JS date-formatting filter - .filter('dateformat', function() { - return function(date, format) { + .filter('dateformat', function () { + return function (date, format) { if (date) { if (format) { return moment(date).format(format); diff --git a/pear-modules/pear-process/src/main/resources/static/editor-app/css/style-common.css b/pear-modules/pear-process/src/main/resources/static/editor-app/css/style-common.css index 07aab3173b56bdc8886329364db7ea44c5f0986c..142cb51b2082a169ffa74279b8b5927ad58e365b 100644 --- a/pear-modules/pear-process/src/main/resources/static/editor-app/css/style-common.css +++ b/pear-modules/pear-process/src/main/resources/static/editor-app/css/style-common.css @@ -55,18 +55,18 @@ body { } .simple-list li:hover { - background-color: #f8f8f9; + background-color: #f8f8f9; } .simple-list li.nothing-to-see:hover { - background-color: transparent; + background-color: transparent; } .simple-list li.active { - background-color: #eeeeee; + background-color: #eeeeee; } -.simple-list li >.actions { +.simple-list li > .actions { visibility: hidden; position: absolute; top: 3px; @@ -76,15 +76,15 @@ body { padding: 0 0 0 4px; } -.simple-list li >.actions a { - padding: 4px 4px 0 4px; - } +.simple-list li > .actions a { + padding: 4px 4px 0 4px; +} -.simple-list li >.actions a:hover { +.simple-list li > .actions a:hover { background-color: #ffffff; } -.simple-list li:hover >.actions { +.simple-list li:hover > .actions { visibility: visible; } @@ -138,7 +138,9 @@ label { font-size: 14px; } -[ng\:cloak], [ng-cloak], .ng-cloak { display: none; } +[ng\:cloak], [ng-cloak], .ng-cloak { + display: none; +} .nothing-to-see { padding: 5px 0 20px 0; @@ -310,35 +312,35 @@ a.dropdown-toggle { /** Subtle dropdown (eg. sort) */ .dropdown-subtle { - margin-right: 5px; - color: #606b7d; + margin-right: 5px; + color: #606b7d; } .dropdown-subtle .btn { - background: transparent; - line-height: 36px; - color: #606b7d; - padding: 0; - font-size: 14px; - border: none; - box-shadow: none; - -webkit-box-shadow: none; - -moz-box-shadow: none; + background: transparent; + line-height: 36px; + color: #606b7d; + padding: 0; + font-size: 14px; + border: none; + box-shadow: none; + -webkit-box-shadow: none; + -moz-box-shadow: none; } .dropdown-subtle .btn-group.open .dropdown-toggle { - box-shadow: none; - -webkit-box-shadow: none; - -moz-box-shadow: none; + box-shadow: none; + -webkit-box-shadow: none; + -moz-box-shadow: none; } .dropdown-subtle .btn:hover, .dropdown-subtle .btn:focus { - background: transparent; - color: #333333; + background: transparent; + color: #333333; } .dropdown-subtle a { - cursor: pointer; + cursor: pointer; } /** Popovers */ @@ -354,24 +356,25 @@ a.dropdown-toggle { .popover.bottom-left, .popover.bottom-right { margin-top: 10px; } - .popover>.arrow, .popover>.arrow { + +.popover > .arrow, .popover > .arrow { margin-left: -11px; border-top-width: 0; border-bottom-color: #999; - border-bottom-color: rgba(0,0,0,.25); + border-bottom-color: rgba(0, 0, 0, .25); top: -11px; } -.popover.bottom-left>.arrow { +.popover.bottom-left > .arrow { left: 40px; } -.popover.bottom-right>.arrow { +.popover.bottom-right > .arrow { right: 40px; } -.popover.bottom-left>.arrow:after, .popover.bottom-right>.arrow:after, .popover.bottom>.arrow:after { +.popover.bottom-left > .arrow:after, .popover.bottom-right > .arrow:after, .popover.bottom > .arrow:after { content: " "; top: 1px; margin-left: -10px; @@ -405,7 +408,7 @@ a.dropdown-toggle { font-size: 12px; } -.popover-header .actions a{ +.popover-header .actions a { display: inline-block; padding: 8px 5px; } @@ -548,7 +551,7 @@ a.dropdown-toggle { margin-top: 0px; } -.subheader .version { +.subheader .version { font-weight: bold; color: #36a7c4; font-size: 110%; @@ -558,24 +561,25 @@ a.dropdown-toggle { border-right: 1px solid #a4acb9; margin-right: 5px; } + .subheader .btn { border-color: #e8edf1; } -.subheader a.btn:hover, .subheader a.btn:focus { +.subheader a.btn:hover, .subheader a.btn:focus { border-color: #e8edf1; color: #ffffff; } .subheader .dropdown-menu .detail { - vertical-align:middle; + vertical-align: middle; color: #1a1a1a; } .subheader p { font-size: 14px; color: #1a1a1a; - word-wrap:break-word; + word-wrap: break-word; } .subheader p.hint a { @@ -619,7 +623,7 @@ a.dropdown-toggle { padding-right: 8px; } -.subheader >div>.pull-right { +.subheader > div > .pull-right { margin-top: 12px; margin-right: 5px; } @@ -689,7 +693,7 @@ a.dropdown-toggle { } .icon-pencil:before { - content: "\270f"; + content: "\270f"; } .icon-caret-up:before { @@ -829,18 +833,23 @@ a.dropdown-toggle { @-webkit-keyframes bouncedelay { - 0%, 80%, 100% { -webkit-transform: scale(0.0) } - 40% { -webkit-transform: scale(1.0) } + 0%, 80%, 100% { + -webkit-transform: scale(0.0) + } + 40% { + -webkit-transform: scale(1.0) + } } @keyframes bouncedelay { 0%, 80%, 100% { transform: scale(0.0); -webkit-transform: scale(0.0); - } 40% { - transform: scale(1.0); - -webkit-transform: scale(1.0); - } + } + 40% { + transform: scale(1.0); + -webkit-transform: scale(1.0); + } } /** Alerts */ @@ -856,7 +865,7 @@ a.dropdown-toggle { z-index: 1010; } -.alert-wrapper.no-header { +.alert-wrapper.no-header { top: 0px; } @@ -883,8 +892,8 @@ a.dropdown-toggle { .alert.ng-hide-remove { opacity: 1; - display:block!important; - } + display: block !important; +} .alert.ng-hide { @@ -902,7 +911,7 @@ a.dropdown-toggle { .alert .glyphicon { padding-right: 8px; - color: #bcd35f; + color: #bcd35f; } .alert span { @@ -915,6 +924,7 @@ a.dropdown-toggle { border-color: #e4593d; background-color: rgba(228, 89, 61, .7); } + .alert.error .glyphicon { color: #e4593d; } @@ -955,9 +965,9 @@ a.dropdown-toggle { background-color: #ffffff; margin-right: 20px; - -webkit-box-shadow: 2px 2px 2px 0px rgba(220,220,220,0.50); - -moz-box-shadow: 2px 2px 2px 0px rgba(220,220,220,0.50); - box-shadow: 2px 2px 2px 0px rgba(220,220,220,0.50); + -webkit-box-shadow: 2px 2px 2px 0px rgba(220, 220, 220, 0.50); + -moz-box-shadow: 2px 2px 2px 0px rgba(220, 220, 220, 0.50); + box-shadow: 2px 2px 2px 0px rgba(220, 220, 220, 0.50); } .main-list .sort { @@ -975,9 +985,9 @@ a.dropdown-toggle { background-color: rgba(255, 255, 255, .9); border-bottom: 1px solid #cccccc; - -webkit-box-shadow: 0px 1px 1px 0px rgba(220,220,220,0.65); - -moz-box-shadow: 0px 1px 1px 0px rgba(220,220,220,0.65); - box-shadow: 0px 1px 1px 0px rgba(220,220,220,0.65); + -webkit-box-shadow: 0px 1px 1px 0px rgba(220, 220, 220, 0.65); + -moz-box-shadow: 0px 1px 1px 0px rgba(220, 220, 220, 0.65); + box-shadow: 0px 1px 1px 0px rgba(220, 220, 220, 0.65); z-index: 2; } @@ -1018,9 +1028,9 @@ a.dropdown-toggle { padding: 6px 8px; border: 1px solid #cccccc; - -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.075); - -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075); - box-shadow: inset 0 1px 1px rgba(0,0,0,.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); background-color: #ffffff; font-size: 14px; @@ -1028,13 +1038,14 @@ a.dropdown-toggle { cursor: pointer; } -.selection .glyphicon, .selection .icon { +.selection .glyphicon, .selection .icon { padding-right: 5px; } .selection .actions { float: right; } + .selection .actions.no-upload { float: left; margin-right: 10px; @@ -1073,7 +1084,7 @@ a.dropdown-toggle { .selection.narrow .label { font-size: 13px; - padding:0 10px 0 0; + padding: 0 10px 0 0; margin: 0; color: #666666; } @@ -1102,7 +1113,7 @@ a.dropdown-toggle { color: #999999; } -.selection+.dropdown-menu { +.selection + .dropdown-menu { width: 100%; } @@ -1142,9 +1153,9 @@ button.selection:active, button.selection:focus { -webkit-border-radius: 0px; border-radius: 0px; color: #666666; - -moz-box-shadow: inset 0 1px 1px rgba(0,0,0,.075); - -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075); - box-shadow: inset 0 1px 1px rgba(0,0,0,.075); + -moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); } @@ -1184,7 +1195,7 @@ button.selection:active, button.selection:focus { .subtle-select:hover, .header .detail a.subtle-select:hover { background-color: #ffffff; text-decoration: none; - color:#1a1a1a; + color: #1a1a1a; } @@ -1197,7 +1208,7 @@ button.selection:active, button.selection:focus { } .list-wrapper { - overflow: auto; + overflow: auto; } @@ -1208,12 +1219,13 @@ button.selection:active, button.selection:focus { .main-list .nothing-to-see { text-align: center; - padding:50px 20px; + padding: 50px 20px; } .main-list .nothing-to-see span { font-size: 17px; } + .main-list .popover { width: 375px; } @@ -1257,7 +1269,7 @@ button.selection:active, button.selection:focus { padding: 2px 0px 2px 0px; } -.full-list li .badge, .simple-list li .badge{ +.full-list li .badge, .simple-list li .badge { font-size: 12px; line-height: 12px; @@ -1338,9 +1350,9 @@ button.selection:active, button.selection:focus { height: 100%; max-height: 100%; overflow: hidden; - -webkit-box-shadow: 2px 2px 2px 0px rgba(220,220,220,0.50); - -moz-box-shadow: 2px 2px 2px 0px rgba(220,220,220,0.50); - box-shadow: 2px 2px 2px 0px rgba(220,220,220,0.50); + -webkit-box-shadow: 2px 2px 2px 0px rgba(220, 220, 220, 0.50); + -moz-box-shadow: 2px 2px 2px 0px rgba(220, 220, 220, 0.50); + box-shadow: 2px 2px 2px 0px rgba(220, 220, 220, 0.50); } .main-content > .header { @@ -1355,12 +1367,12 @@ button.selection:active, button.selection:focus { font-size: 26px; } -.main-content > .header .btn:hover, .main-content > .header .btn:focus { +.main-content > .header .btn:hover, .main-content > .header .btn:focus { border-color: #e8edf1; color: #ffffff; } - .modal-header .label, .header .label { +.modal-header .label, .header .label { padding: 0 3px 0 15px; color: #1a1a1a; font-weight: normal; @@ -1368,7 +1380,7 @@ button.selection:active, button.selection:focus { color: #666666; } -.header > .detail >.label:first-child { +.header > .detail > .label:first-child { padding-left: 0; } @@ -1428,7 +1440,6 @@ button.selection:active, button.selection:focus { } - .section { margin: 10px 0; padding: 10px 0 0px 0; @@ -1468,6 +1479,7 @@ button.selection:active, button.selection:focus { background-color: rgba(100, 100, 100, .75); background-image: url('../../images/glasspane.png'); } + .modal-content { -webkit-border-radius: 0; -moz-border-radius: 0; @@ -1515,4 +1527,4 @@ button.selection:active, button.selection:focus { .fullscreen .modal-header h3 .summary { font-size: 13px; -} \ No newline at end of file +} diff --git a/pear-modules/pear-process/src/main/resources/static/editor-app/css/style-editor.css b/pear-modules/pear-process/src/main/resources/static/editor-app/css/style-editor.css index bce6fa7b83bbe0d5c6c16a3bb1a02f382d833b55..5f6021558f55421451e69c802b811c122544cc48 100644 --- a/pear-modules/pear-process/src/main/resources/static/editor-app/css/style-editor.css +++ b/pear-modules/pear-process/src/main/resources/static/editor-app/css/style-editor.css @@ -1,6 +1,6 @@ /** Colors: - + - Header: #333333 - Subheader: #e8edf1 - Subheader border: #a4acb9 @@ -11,9 +11,9 @@ */ .container-fluid { - max-width: 1400px; - min-width: 1000px; - margin: 0 auto; + max-width: 1400px; + min-width: 1000px; + margin: 0 auto; } .subtle-select .glyphicon { @@ -26,8 +26,8 @@ a.subtle-select:hover .glyphicon { } .full { - padding: 0 15px; - width: 100%; + padding: 0 15px; + width: 100%; } .inline { @@ -43,8 +43,8 @@ a.subtle-select:hover .glyphicon { } .no-pad { - margin: 0; - max-width: 1300px; + margin: 0; + max-width: 1300px; min-width: 1100px; } @@ -56,105 +56,106 @@ a.subtle-select:hover .glyphicon { .inset .col-sm-3 { margin-left: -15px; } -.no-pad > div{ - padding: 0; + +.no-pad > div { + padding: 0; } .dropdown-toggle .icon-caret-down { - padding-left: 10px; - font-size: 85%; + padding-left: 10px; + font-size: 85%; } h1 { - margin: 0 0 0 15px; - padding: 0; - font-size: 22px; - line-height: 40px; - border: none; - color: #ffffff; - font-family: 'Lato', sans-serif; + margin: 0 0 0 15px; + padding: 0; + font-size: 22px; + line-height: 40px; + border: none; + color: #ffffff; + font-family: 'Lato', sans-serif; } .truncate, .truncate > span { - white-space: nowrap; - width: 100%; - overflow: hidden; - text-overflow: ellipsis; + white-space: nowrap; + width: 100%; + overflow: hidden; + text-overflow: ellipsis; } .subheader .details .counter { - top: -1px; - line-height: 1; - display: inline-block; - padding: 2px 6px; - min-width: 20px; - background-color: #e8edf1; - color: #333333; + top: -1px; + line-height: 1; + display: inline-block; + padding: 2px 6px; + min-width: 20px; + background-color: #e8edf1; + color: #333333; } .subheader .subtle-select { - margin: -6px 0 0 -8px; + margin: -6px 0 0 -8px; } .btn .icon-and-label { - padding-right: 5px; -} + padding-right: 5px; +} .dropdown-menu .title { - margin: 5px 10px 0px 10px; - font-size: 17px; - min-width: 250px; + margin: 5px 10px 0px 10px; + font-size: 17px; + min-width: 250px; } .dropdown-menu ul { - list-style: none; - list-style-position: inside; - padding: 5px 10px; + list-style: none; + list-style-position: inside; + padding: 5px 10px; } .input-group-addon { - background-color: transparent; + background-color: transparent; } /* List Filter */ .filter-wrapper { - min-height: 400px; - margin-top: 10px; + min-height: 400px; + margin-top: 10px; margin-left: -15px; } ul.filter-list { - list-style: none; - list-style-position: inside; - padding-left: 0px; - padding-top: 10px; + list-style: none; + list-style-position: inside; + padding-left: 0px; + padding-top: 10px; } ul.filter-list li a { - display: block; - color: #373e48; - font-size: 17px; - margin: 10px 5px 10px 0px; - padding-left: 10px; + display: block; + color: #373e48; + font-size: 17px; + margin: 10px 5px 10px 0px; + padding-left: 10px; } ul.filter-list li.current a { - color: #36a7c4; - padding-left: 5px; - border-left: 4px solid #36a7c4; + color: #36a7c4; + padding-left: 5px; + border-left: 4px solid #36a7c4; } ul.filter-list li a:hover, ul.filter-list li a:focus { - text-decoration: none; - background-color: #e8edf1; + text-decoration: none; + background-color: #e8edf1; } ul.filter-list li.current a:hover, ul.filter-list li.current a:focus { - background-color: transparent; - color: #36a7c4; - cursor: default; - text-decoration: none; + background-color: transparent; + color: #36a7c4; + cursor: default; + text-decoration: none; } @@ -162,160 +163,163 @@ ul.filter-list li.current a:hover, ul.filter-list li.current a:focus { .item-wrapper { - padding-left: 0; - margin-top: 5px; + padding-left: 0; + margin-top: 5px; } .item-wrapper .message { - text-align: left; - margin-left: 5px; - line-height: 40px; - color: #606b7d; + text-align: left; + margin-left: 5px; + line-height: 40px; + color: #606b7d; } + .item-wrapper .message span { - font-size: 14px; + font-size: 14px; } .item-wrapper .item { - width: 25%; - padding: 0; - margin: 0; - float: left; + width: 25%; + padding: 0; + margin: 0; + float: left; } -.item-wrapper .item .btn-default.disabled, +.item-wrapper .item .btn-default.disabled, .item-wrapper .item .btn-default[disabled], .item-wrapper .item .btn-default[disabled]:active, .item-wrapper .item .btn-default[disabled]:hover { - border-color: #ffffff; - cursor: default; + border-color: #ffffff; + cursor: default; } .item-wrapper .item .item-box { - margin: 5px; - border: 1px solid #e8edf1; - height: 250px; - overflow: hidden; - cursor: pointer; - background-repeat: no-repeat; - background-position: center 20px; - background-size: auto; + margin: 5px; + border: 1px solid #e8edf1; + height: 250px; + overflow: hidden; + cursor: pointer; + background-repeat: no-repeat; + background-position: center 20px; + background-size: auto; position: relative; } .item-box .details { position: relative; - background-color: #e8edf1; - height: 160px; - margin-top: 120px; - padding: 5px; - color: #373e48; - font-size: 13px; - - transition: margin-top .5s ease; - -moz-transition: margin-top .5s ease; - -webkit-transition: margin-top .5s ease; - -o-transition: margin-top .5s ease; + background-color: #e8edf1; + height: 160px; + margin-top: 120px; + padding: 5px; + color: #373e48; + font-size: 13px; + + transition: margin-top .5s ease; + -moz-transition: margin-top .5s ease; + -webkit-transition: margin-top .5s ease; + -o-transition: margin-top .5s ease; } .item-box:hover .details, .item-box.active .details { - margin-top: 50px; + margin-top: 50px; } .item-box .actions { - padding: 5px; - height: 45px; + padding: 5px; + height: 45px; } .item-box .actions .btn-group { - visibility: hidden; + visibility: hidden; } .item-box:hover .actions .btn-group, .item-box.active .actions .btn-group { - visibility: inherit; + visibility: inherit; } .item-box .details h3 { - font-size: 14px; - margin: 0; - padding: 2px; - color: #373e48; + font-size: 14px; + margin: 0; + padding: 2px; + color: #373e48; } .item-box .details span { - display: block; - margin-top: 5px; + display: block; + margin-top: 5px; } .item-box .details span i { - padding-right: 10px; - padding-left: 5px; + padding-right: 10px; + padding-left: 5px; } .item-box .details .basic-details { - min-height: 60px; + min-height: 60px; } .item-box .details p { - width: 100%; - height: 70px; - font-size: 12px; - overflow: hidden; + width: 100%; + height: 70px; + font-size: 12px; + overflow: hidden; } .create-inline { - padding: 100px 20px 80px 20px; - border: 1px solid #e8edf1; + padding: 100px 20px 80px 20px; + border: 1px solid #e8edf1; } + .create-inline span { - display: block; - font-size: 18px; - color: #1a1a1a; - text-align: center; - margin-bottom: 20px; -} + display: block; + font-size: 18px; + color: #1a1a1a; + text-align: center; + margin-bottom: 20px; +} .create-inline .glyphicon { - margin-right: 10px; + margin-right: 10px; } .show-more { - clear: both; - height: 50px; - text-align: center; - padding-top: 5px; - margin: 5px; + clear: both; + height: 50px; + text-align: center; + padding-top: 5px; + margin: 5px; } .show-more a { - display: block; - padding: 5px; - font-size: 15px; - text-decoration: none; - cursor: pointer; - color: #666666; + display: block; + padding: 5px; + font-size: 15px; + text-decoration: none; + cursor: pointer; + color: #666666; } .show-more a:hover { - color: #1a1a1a; - background: #e8edf1; + color: #1a1a1a; + background: #e8edf1; } .content-canvas-wrapper { - -moz-box-shadow: inset 0 3px 3px -4px #ababab; - -webkit-box-shadow: inset 0 3px 3px -4px #ababab; - box-shadow: inset 0 3px 3px -4px #ababab; + -moz-box-shadow: inset 0 3px 3px -4px #ababab; + -webkit-box-shadow: inset 0 3px 3px -4px #ababab; + box-shadow: inset 0 3px 3px -4px #ababab; margin: 15px 7px 0 7px; z-index: 0; } + .content-canvas { background-color: #f9f9f9; margin: 0 3px 0 3px; - -moz-box-shadow: inset 0 3px 3px -4px #ababab; - -webkit-box-shadow: inset 0 3px 3px -4px #ababab; - box-shadow: inset 0 3px 3px -4px #ababab; + -moz-box-shadow: inset 0 3px 3px -4px #ababab; + -webkit-box-shadow: inset 0 3px 3px -4px #ababab; + box-shadow: inset 0 3px 3px -4px #ababab; padding: 20px; } @@ -325,7 +329,7 @@ ul.filter-list li.current a:hover, ul.filter-list li.current a:focus { margin-bottom: 5px; } -.content-canvas .no-results{ +.content-canvas .no-results { color: #999999; font-size: 16px; margin: 10px 0px; @@ -337,104 +341,106 @@ ul.filter-list li.current a:hover, ul.filter-list li.current a:focus { /* History */ table.history { - margin: 0; - padding: 0; + margin: 0; + padding: 0; } .subheader table.history { - min-width: 250px; + min-width: 250px; } table.history td { - vertical-align: middle; + vertical-align: middle; } table.history tr td:last-child { - width: 90%; + width: 90%; } table.history tr:hover { - background-color: #f3f6f8; - cursor: pointer; + background-color: #f3f6f8; + cursor: pointer; } + table.history tr.current:hover { - background-color: #e8edf1; - cursor: inherit; + background-color: #e8edf1; + cursor: inherit; } table.history a:hover { - text-decoration: none; - + text-decoration: none; + } table.history .version { - font-size: 30px; - display: inline-block; - color: #36a7c4; - padding: 5px 10px; - vertical-align:middle; - color: #36a7c4; + font-size: 30px; + display: inline-block; + color: #36a7c4; + padding: 5px 10px; + vertical-align: middle; + color: #36a7c4; } table.history .detail { - padding: 5px 5px; - font-size: 15px; - color: #1a1a1a; - display: inline-block; + padding: 5px 5px; + font-size: 15px; + color: #1a1a1a; + display: inline-block; } table.history tr.current { - font-weight: bold; - background-color: #e8edf1; + font-weight: bold; + background-color: #e8edf1; } + table.history tr.current td { - background-color: #e8edf1; + background-color: #e8edf1; } .comments { - clear: both; - width: 350px; - border-top: 1px solid #eeeeee; - margin-top: 5px; - max-height: 350px; - overflow: auto; + clear: both; + width: 350px; + border-top: 1px solid #eeeeee; + margin-top: 5px; + max-height: 350px; + overflow: auto; } .comment { - margin: 10px 0px 20px 0px; - font-size: 12px; + margin: 10px 0px 20px 0px; + font-size: 12px; } .comment .date { - color: #999999; - font-size: 12px; + color: #999999; + font-size: 12px; } .comment .author { - color: #36a7c4; - font-size: 18px; + color: #36a7c4; + font-size: 18px; } .comment p { - word-wrap: break-word; + word-wrap: break-word; } .modal.modal-wide .modal-dialog { - width: 1000px; + width: 1000px; } .modal-dialog.modal-wide { - width: 1000px; + width: 1000px; } .modal-body p { - font-size: 15px; + font-size: 15px; } .modal-body p.danger { - color: #d35f5f; - margin-top: 10px; + color: #d35f5f; + margin-top: 10px; } .form-group .inline-help { @@ -452,6 +458,7 @@ table.history tr.current td { width: 100%; text-align: left; } + .popup-wrapper .people-select { max-height: 160px; } @@ -476,6 +483,7 @@ table.history tr.current td { .center-pane .content { overflow: hidden; } + .center-pane .tab-actions { padding: 8px; } @@ -483,6 +491,7 @@ table.history tr.current td { .center-pane .tabs-wrapper > .pull-right { margin-right: 5px; } + .center-pane .content { padding: 10px; } @@ -502,13 +511,13 @@ table.history tr.current td { .center-pane .header h1 { font-size: 30px; margin: 0; - padding:0; + padding: 0; } .center-pane .header h2 { font-size: 24px; margin: 0 0 5px 0; - padding:0; + padding: 0; } .center-pane .header { @@ -570,54 +579,56 @@ ul.list { margin-bottom: 3px; } -ul.list>li { +ul.list > li { line-height: 30px; margin: 0; padding: 4px; cursor: pointer; } -.popup-wrapper ul.list>li { +.popup-wrapper ul.list > li { border-top: 1px solid #eeeeee; } -.popup-wrapper ul.list>li:last-child { +.popup-wrapper ul.list > li:last-child { border-bottom: 1px solid #eeeeee; } -ul.list>li:hover, ul.list>li.active { +ul.list > li:hover, ul.list > li.active { background-color: #f2f2f2; } -ul.list >li .actions { - float:right; +ul.list > li .actions { + float: right; margin: 0px 0px 0px 5px; visibility: hidden; } -ul.list>li:hover .actions { +ul.list > li:hover .actions { visibility: inherit; } /** Animations **/ -.fadein.ng-enter, +.fadein.ng-enter, .fadein.ng-move { - -webkit-transition: 0.5s linear opacity; - transition: 0.5s linear all; + -webkit-transition: 0.5s linear opacity; + transition: 0.5s linear all; } .fadein.ng-enter { - opacity:0; + opacity: 0; } + .fadein.ng-enter.ng-enter-active { - opacity:1; + opacity: 1; } .fadein.ng-move { - opacity:0.5; + opacity: 0.5; } + .fadein.ng-move.ng-move-active { - opacity:1; + opacity: 1; } .popup-error { @@ -634,6 +645,6 @@ ul.list>li:hover .actions { /** LOADING */ .message .loading { - line-height: 40px; - margin-left: 0px; -} \ No newline at end of file + line-height: 40px; + margin-left: 0px; +} diff --git a/pear-modules/pear-process/src/main/resources/static/editor-app/css/style.css b/pear-modules/pear-process/src/main/resources/static/editor-app/css/style.css index b4916936fcef7c8e9fc902d7146ef8be2423fa21..8ebedb6df695bea1be803dd0da07b6afaede0213 100644 --- a/pear-modules/pear-process/src/main/resources/static/editor-app/css/style.css +++ b/pear-modules/pear-process/src/main/resources/static/editor-app/css/style.css @@ -2,23 +2,23 @@ font-family: 'ActivitiModeler'; src: url('../fonts/activiti-admin-webfont.eot'); src: url('../fonts/activiti-admin-webfont.eot?#iefix') format('embedded-opentype'), - url('../fonts/activiti-admin-webfont.woff') format('woff'), - url('../fonts/activiti-admin-webfont.ttf') format('truetype'), - url('../fonts/activiti-admin-webfont.svg#activitimodelerregular') format('svg'); + url('../fonts/activiti-admin-webfont.woff') format('woff'), + url('../fonts/activiti-admin-webfont.ttf') format('truetype'), + url('../fonts/activiti-admin-webfont.svg#activitimodelerregular') format('svg'); font-weight: normal; font-style: normal; } .row-no-gutter .col-xs-9 { - padding-left: 0px; - padding-right: 0px; - z-index: 50; + padding-left: 0px; + padding-right: 0px; + z-index: 50; } .row-no-gutter .col-xs-3 { - padding-left: 0px; - padding-right: 0px; - z-index: 100; + padding-left: 0px; + padding-right: 0px; + z-index: 100; } .editor-item-picker { @@ -35,20 +35,20 @@ } .editor-toolbar { - padding-left: 5px; + padding-left: 5px; } .editor-toolbar > .btn-group { - margin: 12px 15px 0px 0px; + margin: 12px 15px 0px 0px; } -.editor-toolbar > .btn-group.pull-right { - margin: 0; +.editor-toolbar > .btn-group.pull-right { + margin: 0; } .editor-toolbar .btn.btn-inverse { - font-size: 24px; - color: #FFFFFF; + font-size: 24px; + color: #FFFFFF; border-color: rgba(0, 0, 0, 0); padding: 3px 6px 0px 6px; box-shadow: none; @@ -59,88 +59,91 @@ height: 36px; min-width: 36px; } + .editor-toolbar .btn.btn-inverse.pressed { - background-color: #287d92; - color: #174753; + background-color: #287d92; + color: #174753; } .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 { - background-color: #668b94; - border-color: #668b94; + background-color: #668b94; + border-color: #668b94; } .editor-toolbar .btn.btn-inverse.separator { - background: transparent; - padding: 4px 5px 0px 5px; - width: 1px; - min-width: 1px; + background: transparent; + padding: 4px 5px 0px 5px; + width: 1px; + min-width: 1px; } .editor-toolbar .toolbar-separator { - background: #a4acb9; - width: 1px; - height: 30px; + background: #a4acb9; + width: 1px; + height: 30px; } .stencils { - border-right: 1pt solid #c7cacd; - overflow: auto; - z-index: 5000; + border-right: 1pt solid #c7cacd; + overflow: auto; + z-index: 5000; } .stencils ul { - padding-left: 0; + padding-left: 0; } .stencils > div { - margin-top: 10px; + margin-top: 10px; } .stencil-group { - list-style: none; - list-style-position: outside; - margin: 0px 15px 0px 0px; + list-style: none; + list-style-position: outside; + margin: 0px 15px 0px 0px; } .stencil-group > li { - list-style: none; - list-style-position: outside; - margin: 0px 0px 5px 15px; - background-color: #ffffff; - font-family: Arial, Regular; - font-size: 17px; - color: #323437; + list-style: none; + list-style-position: outside; + margin: 0px 0px 5px 15px; + background-color: #ffffff; + font-family: Arial, Regular; + font-size: 17px; + color: #323437; } .stencil-group > li > span { - margin-left: 5px; - padding-top:5px; - padding-bottom: 5px; - display: block; - cursor: pointer; + margin-left: 5px; + padding-top: 5px; + padding-bottom: 5px; + display: block; + cursor: pointer; } .stencil-group > li > span > i { - font-size: 12px; - line-height: 17px; + font-size: 12px; + line-height: 17px; } + .stencil-group > li > ul { - list-style: none; - list-style-position: inside; - background-color: transparent; - margin: 0px; - overflow: hidden; - padding-left: 20px; + list-style: none; + list-style-position: inside; + background-color: transparent; + margin: 0px; + overflow: hidden; + padding-left: 20px; } .stencil-group.collapsed > li { - color: #000000; + color: #000000; } + .stencil-group.collapsed > li > ul { - max-height: 0px; - padding-top: 0; - padding-bottom: 0; + max-height: 0px; + padding-top: 0; + padding-bottom: 0; } .stencil-group-non-root > li { @@ -168,63 +171,63 @@ /* Modeling Canvas -------------------------------- */ div.canvas-wrapper { - overflow: auto; - background-color: #F8F8F8; + overflow: auto; + background-color: #F8F8F8; } .canvas_resize_indicator i { - font-size: 15px; - color: #ffffff; - cursor: pointer; + font-size: 15px; + color: #ffffff; + cursor: pointer; } .canvas_resize_indicator.N, .canvas_resize_indicator.S, .canvas_resize_indicator.E, .canvas_resize_indicator.W { - background: #5fbcd3; - height: 17px; - width: 17px; - text-align: center; - -webkit-border-radius:3px; - -moz-border-radius:3px; - border-radius:3px; + background: #5fbcd3; + height: 17px; + width: 17px; + text-align: center; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; } #canvas-grow-N.canvas_resize_indicator, #canvas-shrink-S.canvas_resize_indicator { - margin: 0; - top: auto; + margin: 0; + top: auto; } #canvas-grow-S.canvas_resize_indicator, #canvas-shrink-N.canvas_resize_indicator { - margin: 0; - bottom: auto; + margin: 0; + bottom: auto; } #canvas-grow-E.canvas_resize_indicator, #canvas-shrink-W.canvas_resize_indicator { - margin: 0; - right: auto; + margin: 0; + right: auto; } #canvas-grow-W.canvas_resize_indicator, #canvas-shrink-E.canvas_resize_indicator { - margin: 0; - left: auto; + margin: 0; + left: auto; } .x-panel-body.x-panel-body-noheader.x-panel-body-noborder, .ORYX_Editor x-panel { - background-color: #F8F8F8; + background-color: #F8F8F8; } .canvas-message { - position: absolute; - top: 60px; - right: 10px; - background: transparent; - font-size: 10pt; + position: absolute; + top: 60px; + right: 10px; + background: transparent; + font-size: 10pt; } div.propertySection { - height: 250px; + height: 250px; background-color: #e8edf1; - margin-bottom: 0px; + margin-bottom: 0px; } .selected-item-title { @@ -236,118 +239,118 @@ div.propertySection { } .selected-item-title a { - display: block; - color: #1a1a1a; + display: block; + color: #1a1a1a; } .selected-item-title .glyphicon { - line-height: 25px; - font-size: 14px; + line-height: 25px; + font-size: 14px; } .selected-item-title a:hover, .selected-item-title a:focus { - color: #1a1a1a; - text-decoration: none; + color: #1a1a1a; + text-decoration: none; } .selected-item-section > div > .pull-right { - line-height: 50px; - margin: 0px 10px; - font-size: 14px; + line-height: 50px; + margin: 0px 10px; + font-size: 14px; } .selected-item-body .property-row { - float: left; - width: 50%; - border: 0; - margin: 0; - padding: 0; - font-size: 13px; - overflow: hidden; + float: left; + width: 50%; + border: 0; + margin: 0; + padding: 0; + font-size: 13px; + overflow: hidden; } .selected-item-body .property-row:hover { - background-color: #d7dfe6; + background-color: #d7dfe6; } .selected-item-body { - padding: 0; - overflow: auto; - height: 199px; + padding: 0; + overflow: auto; + height: 199px; } .selected-item-body > div { - overflow: hidden; - margin: 5px 20px; + overflow: hidden; + margin: 5px 20px; } .property-row > span { - display: block; - float: left; - margin: 2px 2%; - padding: 0; - min-height: 25px; + display: block; + float: left; + margin: 2px 2%; + padding: 0; + min-height: 25px; } .property-row span.value { - cursor: pointer; - width: 46%; - padding: 0; - margin: 0; + cursor: pointer; + width: 46%; + padding: 0; + margin: 0; } .property-row span.value:hover { - cursor: pointer; + cursor: pointer; } .property-row span.title { - font-size: 13px; - font-weight: bold; - width: 46%; + font-size: 13px; + font-weight: bold; + width: 46%; } .property-row span.title-removed { - font-size: 13px; - font-weight: normal; - width: 46%; + font-size: 13px; + font-weight: normal; + width: 46%; } .propertySection.collapsed { - max-height: 50px; - height: 50px; - overflow: hidden; + max-height: 50px; + height: 50px; + overflow: hidden; } .propertySection.collapsed .selected-item-title { - border: none; + border: none; } .property-row input[type="text"] { - height: 25px; - margin: 2px 0; - padding: 0px 5px; - width: 100%; + height: 25px; + margin: 2px 0; + padding: 0px 5px; + width: 100%; outline: none; - border:none !important; - box-shadow:none !important; + border: none !important; + box-shadow: none !important; } .default-grid { - border: 1px solid rgb(212,212,212); + border: 1px solid rgb(212, 212, 212); width: 100%; height: 300px; margin-bottom: 10px; } .kis-listener-grid { - border: 1px solid rgb(212,212,212); + border: 1px solid rgb(212, 212, 212); width: 100%; height: 200px; margin-bottom: 10px; } .kis-field-grid { - border: 1px solid rgb(212,212,212); + border: 1px solid rgb(212, 212, 212); width: 100%; height: 150px; margin-bottom: 10px; @@ -361,43 +364,43 @@ div.propertySection { .form-property-checkbox { - margin:0; + margin: 0; } /* Oryx overrides -------------------------------- */ ul.x-menu-list { - list-style: none; - list-style-position: inside; - width: 200px; - background-color: #FFFFFF; - border: 1px solid #E1E2E5; - -webkit-border-radius:3px; - -moz-border-radius:3px; - border-radius:3px; - padding: 3px; + list-style: none; + list-style-position: inside; + width: 200px; + background-color: #FFFFFF; + border: 1px solid #E1E2E5; + -webkit-border-radius: 3px; + -moz-border-radius: 3px; + border-radius: 3px; + padding: 3px; } -img.x-menu-item-icon { - width: auto; - height: auto; - margin-right: 5px; +img.x-menu-item-icon { + width: auto; + height: auto; + margin-right: 5px; } li.x-menu-list-item { - margin: 3px 0px; + margin: 3px 0px; } li.x-menu-list-item.x-menu-item-active { - background-color: #EFEFEF; + background-color: #EFEFEF; } li.x-menu-list-item a { - color: #000000; + color: #000000; } li.x-menu-list-item.x-menu-item-active a { - text-decoration: none; + text-decoration: none; } .sequence-flow-order-element { @@ -406,72 +409,85 @@ li.x-menu-list-item.x-menu-item-active a { /* Editor icon font */ .editor-icon { - position: relative; - top: 1px; - display: inline-block; - font-family: 'ActivitiModeler'; - font-style: normal; - font-weight: 400; - line-height: 1; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; + position: relative; + top: 1px; + display: inline-block; + font-family: 'ActivitiModeler'; + font-style: normal; + font-weight: 400; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; } .editor-icon-save:before { - content: 'a'; + content: 'a'; } .editor-icon-edit:before { - content: 'b'; + content: 'b'; } .editor-icon-cut:before { - content: 'c'; + content: 'c'; } .editor-icon-copy:before { - content: 'd'; + content: 'd'; } .editor-icon-paste:before { - content: 'e'; + content: 'e'; } + .editor-icon-delete:before { - content: 'f'; + content: 'f'; } + .editor-icon-redo:before { - content: 'h'; + content: 'h'; } + .editor-icon-undo:before { - content: 'g'; + content: 'g'; } + .editor-icon-same-size:before { - content: 'i'; + content: 'i'; } + .editor-icon-zoom-in:before { - content: 'k'; + content: 'k'; } + .editor-icon-zoom-out:before { - content: 'l'; + content: 'l'; } + .editor-icon-zoom-actual:before { - content: 'm'; + content: 'm'; } + .editor-icon-zoom-fit:before { - content: 'j'; + content: 'j'; } + .editor-icon-bendpoint-add:before { - content: 'n'; + content: 'n'; } + .editor-icon-bendpoint-remove:before { - content: 'o'; + content: 'o'; } + .editor-icon-align-horizontal:before { - content: 'p'; + content: 'p'; } + .editor-icon-align-vertical:before { - content: 'q'; + content: 'q'; } + .editor-icon-close:before { content: "X"; } diff --git a/pear-modules/pear-process/src/main/resources/static/editor-app/editor.html b/pear-modules/pear-process/src/main/resources/static/editor-app/editor.html index 4680f138217fbac6bce650cefe02c469151adc11..9c5bb6bab1745f81b1ea8674528f81e40bd4e253 100644 --- a/pear-modules/pear-process/src/main/resources/static/editor-app/editor.html +++ b/pear-modules/pear-process/src/main/resources/static/editor-app/editor.html @@ -1,133 +1,143 @@
-
-
-
- -
+
+
+
+ +
-
- -
+
+ +
-
-
-
-
-
-
-
-
    -
  • -
-
+
+
+
+
+
+
+
+
    +
  • +
+
+
-
-
-
    -
  • +
    +
      +
    • - - {{item.name}} -
    • -
    -
    -
-
-
-
-
- - - -
-
-
-
-
-
-
- {{'ELEMENT.DATE_CREATED' | translate}}: {{selectedItem.auditData.createDate}} -
-
- {{'ELEMENT.AUTHOR' | translate}}: {{selectedItem.auditData.author}} -
- -
-
-
-
- {{ property.title }} : - {{ property.title }} ({{'PROPERTY.REMOVED' | translate}}) : - + + {{item.name}} + + +
+
+
+
+
+
+ + + +
+
+
+
+
+
+
+ {{'ELEMENT.DATE_CREATED' | translate}}: + {{selectedItem.auditData.createDate}} +
+
+ {{'ELEMENT.AUTHOR' | translate}}: {{selectedItem.auditData.author}} +
+ +
+
+
+
+ {{ property.title }} : + {{ property.title }} ({{'PROPERTY.REMOVED' | translate}}) : + - - + ng-if="!property.hasReadWriteMode" + src="getPropertyTemplateUrl($index)"> + + -
-
-
-
-
+
+
+
+
+
-
+
diff --git a/pear-modules/pear-process/src/main/resources/static/editor-app/editor/css/editor.css b/pear-modules/pear-process/src/main/resources/static/editor-app/editor/css/editor.css index 0936639717dfbc3fb31e4da37fa87cbe79416bf3..ad695b90775ec0390b7394ecbe4c534ef690fdbd 100644 --- a/pear-modules/pear-process/src/main/resources/static/editor-app/editor/css/editor.css +++ b/pear-modules/pear-process/src/main/resources/static/editor-app/editor/css/editor.css @@ -1,5 +1,5 @@ body, html { - font-family: tahoma,arial,helvetica,sans-serif; + font-family: tahoma, arial, helvetica, sans-serif; font-size: 12px; } @@ -9,7 +9,7 @@ body, html { text, text * { - cursor:default; + cursor: default; -webkit-user-select: none; } @@ -25,49 +25,50 @@ text * { .ORYX_Editor { background: white; border: none; - margin:-5px; - margin-top:0px; - width:1200px; - height:600px; + margin: -5px; + margin-top: 0px; + width: 1200px; + height: 600px; } .icon-large { - width:18px !important; + width: 18px !important; } #oryxcanvas { - width:1200px; - height:600px; + width: 1200px; + height: 600px; } /** Resizer for the Canvas **/ .canvas_resize_indicator_area { - margin :auto; - display :block; - height :30px; - left :20%; - position :absolute; - text-align :center; - top :0; - width :60%; + margin: auto; + display: block; + height: 30px; + left: 20%; + position: absolute; + text-align: center; + top: 0; + width: 60%; } .canvas_resize_indicator { - width : 15px; - height : 15px; - position : absolute; - display : block; - margin : auto; - opacity : 0.6; + width: 15px; + height: 15px; + position: absolute; + display: block; + margin: auto; + opacity: 0.6; } .canvas_resize_indicator:hover { - opacity : 1.0; + opacity: 1.0; } + /** End Resizer **/ .Oryx_down { @@ -75,88 +76,88 @@ text * { } .Oryx_button img { - width:16px; - height:16px; - top:0px; - left:0px; - line-height: 16px; + width: 16px; + height: 16px; + top: 0px; + left: 0px; + line-height: 16px; } .Oryx_Right .Oryx_button, .Oryx_Left .Oryx_button, .Oryx_Top .Oryx_button, .Oryx_Bottom .Oryx_button { - opacity: 0.5; + opacity: 0.5; } .Oryx_button.x-opacity-0 { - opacity: 0; - display:none; + opacity: 0; + display: none; } .Oryx_button.x-opacity-10 { - opacity: 0.1; + opacity: 0.1; } .Oryx_button.x-opacity-20 { - opacity: 0.2; + opacity: 0.2; } .Oryx_button.x-opacity-50 { - opacity: 0.5; + opacity: 0.5; } .Oryx_Right:hover .Oryx_button, .Oryx_Left:hover .Oryx_button, .Oryx_Top:hover .Oryx_button, .Oryx_Bottom:hover .Oryx_button { - opacity: 0.7; - display:block; + opacity: 0.7; + display: block; } .Oryx_button img { - top:0px; + top: 0px; } .Oryx_Left img { - top:0px; + top: 0px; } .Oryx_button { - width:24px; - height:24px; - padding:2px; - position:absolute; - background-color: #ffffff; - background-color: rgba(255,255,255,0.7); - cursor: pointer; + width: 24px; + height: 24px; + padding: 2px; + position: absolute; + background-color: #ffffff; + background-color: rgba(255, 255, 255, 0.7); + cursor: pointer; } .Oryx_button_with_caption { - width:inherit; - height:16px; - padding:4px; - position:absolute; + width: inherit; + height: 16px; + padding: 4px; + position: absolute; } /*** Resizer ***/ .resizer_southeast, .resizer_northwest { - width:12px; - height:12px; - position:relative; - background-color: transparent; - background-repeat:no-repeat; + width: 12px; + height: 12px; + position: relative; + background-color: transparent; + background-repeat: no-repeat; } /*** Selection Frame ***/ -.Oryx_SelectionFrame{ - position:absolute; - border:1px dotted gray; - background:none; +.Oryx_SelectionFrame { + position: absolute; + border: 1px dotted gray; + background: none; } .LoadingIndicator { @@ -173,10 +174,10 @@ text * { } .ValidateButton { - width:24px; - height:24px; - padding:2px; - position:absolute; + width: 24px; + height: 24px; + padding: 2px; + position: absolute; cursor: pointer; } @@ -190,13 +191,13 @@ text * { } .resizer_southeast { - background-image:url(../../images/se-handle-dark.gif); + background-image: url(../../images/se-handle-dark.gif); cursor: se-resize; background-position: 4px 4px; } .resizer_northwest { - background-image:url(../../images/nw-handle-dark.gif); + background-image: url(../../images/nw-handle-dark.gif); cursor: nw-resize; background-position: -2px -2px; } diff --git a/pear-modules/pear-process/src/main/resources/static/editor-app/editor/i18n/translation_de.js b/pear-modules/pear-process/src/main/resources/static/editor-app/editor/i18n/translation_de.js index 0d588f0bb4a0884ba267fdaccbde499bf5d893c8..63de630fedb8b06abd9745c6af30ad023c8c9581 100644 --- a/pear-modules/pear-process/src/main/resources/static/editor-app/editor/i18n/translation_de.js +++ b/pear-modules/pear-process/src/main/resources/static/editor-app/editor/i18n/translation_de.js @@ -1,22 +1,22 @@ /** * @author nicolas.peters - * + * * Contains all strings for German language. * Version 1 - 08/29/08 */ -if(!ORYX) var ORYX = {}; +if (!ORYX) var ORYX = {}; -if(!ORYX.I18N) ORYX.I18N = {}; +if (!ORYX.I18N) ORYX.I18N = {}; ORYX.I18N.Language = "de_DE"; //Pattern _ in lower case! -if(!ORYX.I18N.Oryx) ORYX.I18N.Oryx = {}; +if (!ORYX.I18N.Oryx) ORYX.I18N.Oryx = {}; ORYX.I18N.Oryx.pleaseWait = "Editor wird geladen. Bitte warten..."; ORYX.I18N.Oryx.notLoggedOn = "Nicht angemeldet"; -ORYX.I18N.Oryx.noBackendDefined = "Achtung! \n Es wurde kein Repository definiert.\n Ihr Model kann nicht geladen werden. Bitte nutzen sie eine Editor Konfiguration mit einem Speicher Plugin."; +ORYX.I18N.Oryx.noBackendDefined = "Achtung! \n Es wurde kein Repository definiert.\n Ihr Model kann nicht geladen werden. Bitte nutzen sie eine Editor Konfiguration mit einem Speicher Plugin."; -if(!ORYX.I18N.AddDocker) ORYX.I18N.AddDocker = {}; +if (!ORYX.I18N.AddDocker) ORYX.I18N.AddDocker = {}; ORYX.I18N.AddDocker.group = "Docker"; ORYX.I18N.AddDocker.add = "Docker Hinzufügen"; @@ -24,7 +24,7 @@ ORYX.I18N.AddDocker.addDesc = "Fügen Sie einer Kante einen Docker hinzu, indem ORYX.I18N.AddDocker.del = "Docker Löschen"; ORYX.I18N.AddDocker.delDesc = "Löscht einen Docker durch Klicken auf den zu löschenden Docker"; -if(!ORYX.I18N.Arrangement) ORYX.I18N.Arrangement = {}; +if (!ORYX.I18N.Arrangement) ORYX.I18N.Arrangement = {}; ORYX.I18N.Arrangement.groupZ = "Z-Order"; ORYX.I18N.Arrangement.btf = "In den Vordergrund"; @@ -51,7 +51,7 @@ ORYX.I18N.Arrangement.arDesc = "Rechts ausrichten"; ORYX.I18N.Arrangement.as = "Größenangleichung"; ORYX.I18N.Arrangement.asDesc = "Größenangleichung"; -if(!ORYX.I18N.Edit) ORYX.I18N.Edit = {}; +if (!ORYX.I18N.Edit) ORYX.I18N.Edit = {}; ORYX.I18N.Edit.group = "Edit"; ORYX.I18N.Edit.cut = "Ausschneiden"; @@ -63,7 +63,7 @@ ORYX.I18N.Edit.pasteDesc = "Einfügen von kopierten/ausgeschnittenen Elementen"; ORYX.I18N.Edit.del = "Löschen"; ORYX.I18N.Edit.delDesc = "Löschen der selektierten Elemente"; -if(!ORYX.I18N.EPCSupport) ORYX.I18N.EPCSupport = {}; +if (!ORYX.I18N.EPCSupport) ORYX.I18N.EPCSupport = {}; ORYX.I18N.EPCSupport.group = "EPC"; ORYX.I18N.EPCSupport.exp = "EPML Export"; @@ -79,7 +79,7 @@ ORYX.I18N.EPCSupport.close = "Schließen"; ORYX.I18N.EPCSupport.error = "Fehler"; ORYX.I18N.EPCSupport.progressImp = "Importiere..."; -if(!ORYX.I18N.ERDFSupport) ORYX.I18N.ERDFSupport = {}; +if (!ORYX.I18N.ERDFSupport) ORYX.I18N.ERDFSupport = {}; ORYX.I18N.ERDFSupport.exp = "ERDF Export"; ORYX.I18N.ERDFSupport.expDesc = "Exportieren nach ERDF"; @@ -100,7 +100,7 @@ ORYX.I18N.ERDFSupport.close = "Schließen"; ORYX.I18N.ERDFSupport.deprTitle = "Wirklich nach eRDF exportieren?"; ORYX.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?"; -if(!ORYX.I18N.jPDLSupport) ORYX.I18N.jPDLSupport = {}; +if (!ORYX.I18N.jPDLSupport) ORYX.I18N.jPDLSupport = {}; ORYX.I18N.jPDLSupport.group = "ExecBPMN"; ORYX.I18N.jPDLSupport.exp = "jPDL Export"; @@ -110,7 +110,7 @@ ORYX.I18N.jPDLSupport.impDesc = "jPDL Datei importieren"; ORYX.I18N.jPDLSupport.impFailedReq = "Anfrage für den Import der jPDL Datei ist fehlgeschlagen."; ORYX.I18N.jPDLSupport.impFailedJson = "Transformation der jPDL Datei ist fehlgeschlagen."; ORYX.I18N.jPDLSupport.impFailedJsonAbort = "Import abgebrochen."; -ORYX.I18N.jPDLSupport.loadSseQuestionTitle = "Stencil Set Erweiterung für jBPM muss geladen werden"; +ORYX.I18N.jPDLSupport.loadSseQuestionTitle = "Stencil Set Erweiterung für jBPM muss geladen werden"; ORYX.I18N.jPDLSupport.loadSseQuestionBody = "Um jPDL importieren zu können, muss die Stencil Set Erweiterung für jBPM geladen werden. Möchten Sie fortfahren?"; ORYX.I18N.jPDLSupport.expFailedReq = "Anfrage für den Export des Models ist fehlgeschlagen."; ORYX.I18N.jPDLSupport.expFailedXml = "Export nach jPDL ist fehlgeschlagen. Exporter meldet: "; @@ -122,7 +122,7 @@ ORYX.I18N.jPDLSupport.impBtn = "Importieren"; ORYX.I18N.jPDLSupport.impProgress = "Importiere..."; ORYX.I18N.jPDLSupport.close = "Schließen"; -if(!ORYX.I18N.Save) ORYX.I18N.Save = {}; +if (!ORYX.I18N.Save) ORYX.I18N.Save = {}; ORYX.I18N.Save.group = "File"; ORYX.I18N.Save.save = "Speichern"; @@ -141,7 +141,7 @@ ORYX.I18N.Save.noRights = "Sie haben nicht die erforderlichen Rechte, um Änderu ORYX.I18N.Save.saving = "Speichern"; ORYX.I18N.Save.saveAsHint = "Das Diagramm wurde unter folgendem Link gespeichert:"; -if(!ORYX.I18N.File) ORYX.I18N.File = {}; +if (!ORYX.I18N.File) ORYX.I18N.File = {}; ORYX.I18N.File.group = "File"; ORYX.I18N.File.print = "Drucken"; @@ -155,7 +155,7 @@ ORYX.I18N.File.genPDFFailed = "Die Generierung der PDF Datei ist fehlgeschlagen. ORYX.I18N.File.printTitle = "Drucken"; ORYX.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?"; -if(!ORYX.I18N.Grouping) ORYX.I18N.Grouping = {}; +if (!ORYX.I18N.Grouping) ORYX.I18N.Grouping = {}; ORYX.I18N.Grouping.grouping = "Grouping"; ORYX.I18N.Grouping.group = "Gruppieren"; @@ -163,11 +163,11 @@ ORYX.I18N.Grouping.groupDesc = "Gruppierung der selektierten Elemente"; ORYX.I18N.Grouping.ungroup = "Gruppierung aufheben"; ORYX.I18N.Grouping.ungroupDesc = "Aufheben aller Gruppierungen der selektierten Elemente"; -if(!ORYX.I18N.Loading) ORYX.I18N.Loading = {}; +if (!ORYX.I18N.Loading) ORYX.I18N.Loading = {}; -ORYX.I18N.Loading.waiting ="Bitte warten..."; +ORYX.I18N.Loading.waiting = "Bitte warten..."; -if(!ORYX.I18N.PropertyWindow) ORYX.I18N.PropertyWindow = {}; +if (!ORYX.I18N.PropertyWindow) ORYX.I18N.PropertyWindow = {}; ORYX.I18N.PropertyWindow.name = "Name"; ORYX.I18N.PropertyWindow.value = "Wert"; @@ -181,13 +181,13 @@ ORYX.I18N.PropertyWindow.ok = "Ok"; ORYX.I18N.PropertyWindow.cancel = "Abbrechen"; ORYX.I18N.PropertyWindow.dateFormat = "d/m/y"; -if(!ORYX.I18N.ShapeMenuPlugin) ORYX.I18N.ShapeMenuPlugin = {}; +if (!ORYX.I18N.ShapeMenuPlugin) ORYX.I18N.ShapeMenuPlugin = {}; ORYX.I18N.ShapeMenuPlugin.drag = "Ziehen"; ORYX.I18N.ShapeMenuPlugin.clickDrag = "Klicken oder ziehen"; ORYX.I18N.ShapeMenuPlugin.morphMsg = "Shape morphen"; -if(!ORYX.I18N.SyntaxChecker) ORYX.I18N.SyntaxChecker = {}; +if (!ORYX.I18N.SyntaxChecker) ORYX.I18N.SyntaxChecker = {}; ORYX.I18N.SyntaxChecker.group = "Verification"; ORYX.I18N.SyntaxChecker.name = "Syntax-Checker"; @@ -196,7 +196,7 @@ ORYX.I18N.SyntaxChecker.noErrors = "Es wurden keine Syntaxfehler gefunden."; ORYX.I18N.SyntaxChecker.invalid = "Ungültige Antwort vom Server."; ORYX.I18N.SyntaxChecker.checkingMessage = "Überprüfung wird durchgeführt ..."; -if(!ORYX.I18N.Undo) ORYX.I18N.Undo = {}; +if (!ORYX.I18N.Undo) ORYX.I18N.Undo = {}; ORYX.I18N.Undo.group = "Undo"; ORYX.I18N.Undo.undo = "Rückgängig"; @@ -204,7 +204,7 @@ ORYX.I18N.Undo.undoDesc = "Rückgängig"; ORYX.I18N.Undo.redo = "Wiederherstellen"; ORYX.I18N.Undo.redoDesc = "Wiederherstellen"; -if(!ORYX.I18N.View) ORYX.I18N.View = {}; +if (!ORYX.I18N.View) ORYX.I18N.View = {}; ORYX.I18N.View.group = "Zoom"; ORYX.I18N.View.zoomIn = "Vergrößern"; @@ -220,7 +220,7 @@ ORYX.I18N.View.zoomFitToModelDesc = "Modelgröße"; ORYX.I18N.PropertyWindow.title = "Eigenschaften"; -if(!ORYX.I18N.ShapeRepository) ORYX.I18N.ShapeRepository = {}; +if (!ORYX.I18N.ShapeRepository) ORYX.I18N.ShapeRepository = {}; ORYX.I18N.ShapeRepository.title = "Shape Verzeichnis"; ORYX.I18N.Save.dialogDesciption = "Bitte geben Sie einen Namen, eine Beschreibung und einen Kommentar ein."; @@ -229,7 +229,7 @@ ORYX.I18N.Save.dialogLabelDesc = "Beschreibung"; ORYX.I18N.Save.dialogLabelType = "Typ"; ORYX.I18N.Save.dialogLabelComment = "Revisionskommentar"; -if(!ORYX.I18N.Perspective) ORYX.I18N.Perspective = {}; +if (!ORYX.I18N.Perspective) ORYX.I18N.Perspective = {}; ORYX.I18N.Perspective.no = "Keine Perspektive" ORYX.I18N.Perspective.noTip = "Zurücksetzen der aktuellen Perspektive" @@ -254,19 +254,19 @@ ORYX.I18N.JSONSupport = { }; /** New Language Properties: 09.05.2009 */ -if(!ORYX.I18N.JSONImport) ORYX.I18N.JSONImport = {}; +if (!ORYX.I18N.JSONImport) ORYX.I18N.JSONImport = {}; ORYX.I18N.JSONImport.title = "JSON Import"; ORYX.I18N.JSONImport.wrongSS = "Das Stencil Set der importierten Datei ({0}) entspricht nicht dem geladenen Stencil Set ({1})." /** New Language Properties: 14.05.2009 */ -if(!ORYX.I18N.RDFExport) ORYX.I18N.RDFExport = {}; +if (!ORYX.I18N.RDFExport) ORYX.I18N.RDFExport = {}; ORYX.I18N.RDFExport.group = "Export"; ORYX.I18N.RDFExport.rdfExport = "Nach RDF exportieren"; ORYX.I18N.RDFExport.rdfExportDescription = "Exportiert das aktuelle Model in die XML-Serialisierung des Resource Description Frameworks (RDF)"; /** New Language Properties: 15.05.2009*/ -if(!ORYX.I18N.SyntaxChecker.BPMN) ORYX.I18N.SyntaxChecker.BPMN={}; +if (!ORYX.I18N.SyntaxChecker.BPMN) ORYX.I18N.SyntaxChecker.BPMN = {}; ORYX.I18N.SyntaxChecker.BPMN_NO_SOURCE = "Eine Kante muss einen Ursprung haben."; ORYX.I18N.SyntaxChecker.BPMN_NO_TARGET = "Eine Kante muss ein Ziel haben."; ORYX.I18N.SyntaxChecker.BPMN_DIFFERENT_PROCESS = "Ursprungs- und Zielknoten müssen im gleichen Prozess sein."; @@ -281,18 +281,18 @@ ORYX.I18N.SyntaxChecker.BPMN_ENDEVENT_WITH_OUTGOING_CONTROL_FLOW = "End-Ereignis ORYX.I18N.SyntaxChecker.BPMN_EVENTBASEDGATEWAY_BADCONTINUATION = "Auf Ereignis-basierte Gateways dürfen weder Gateways noch Subprozesse folgen."; ORYX.I18N.SyntaxChecker.BPMN_NODE_NOT_ALLOWED = "Knotentyp ist nicht erlaubt."; -if(!ORYX.I18N.SyntaxChecker.IBPMN) ORYX.I18N.SyntaxChecker.IBPMN={}; +if (!ORYX.I18N.SyntaxChecker.IBPMN) ORYX.I18N.SyntaxChecker.IBPMN = {}; ORYX.I18N.SyntaxChecker.IBPMN_NO_ROLE_SET = "Für Interaktionen muss ein Sender und ein Empfänger definiert sein."; ORYX.I18N.SyntaxChecker.IBPMN_NO_INCOMING_SEQFLOW = "Dieser Knoten muss eingehenden Sequenzfluss besitzen."; ORYX.I18N.SyntaxChecker.IBPMN_NO_OUTGOING_SEQFLOW = "Dieser Knoten muss ausgehenden Sequenzfluss besitzen."; -if(!ORYX.I18N.SyntaxChecker.InteractionNet) ORYX.I18N.SyntaxChecker.InteractionNet={}; +if (!ORYX.I18N.SyntaxChecker.InteractionNet) ORYX.I18N.SyntaxChecker.InteractionNet = {}; ORYX.I18N.SyntaxChecker.InteractionNet_SENDER_NOT_SET = "Sender ist nicht definiert"; ORYX.I18N.SyntaxChecker.InteractionNet_RECEIVER_NOT_SET = "Empfänger ist nicht definiert"; ORYX.I18N.SyntaxChecker.InteractionNet_MESSAGETYPE_NOT_SET = "Nachrichtentyp ist nicht definiert."; ORYX.I18N.SyntaxChecker.InteractionNet_ROLE_NOT_SET = "Rolle ist nicht definiert."; -if(!ORYX.I18N.SyntaxChecker.EPC) ORYX.I18N.SyntaxChecker.EPC={}; +if (!ORYX.I18N.SyntaxChecker.EPC) ORYX.I18N.SyntaxChecker.EPC = {}; ORYX.I18N.SyntaxChecker.EPC_NO_SOURCE = "Eine Kante muss einen Ursprung haben."; ORYX.I18N.SyntaxChecker.EPC_NO_TARGET = "Eine Kante muss ein Ziel haben."; ORYX.I18N.SyntaxChecker.EPC_NOT_CONNECTED = "Dieser Knoten muss eingehende oder ausgehende Kanten besitzen."; @@ -302,13 +302,13 @@ ORYX.I18N.SyntaxChecker.EPC_NO_CORRECT_CONNECTOR = "Knoten ist kein korrekter Ko ORYX.I18N.SyntaxChecker.EPC_MANY_STARTS = "Es darf nur ein Start-Ereignis geben."; ORYX.I18N.SyntaxChecker.EPC_FUNCTION_AFTER_OR = "Funktionen hinter einem OR-/XOR-Split sind nicht erlaubt."; ORYX.I18N.SyntaxChecker.EPC_PI_AFTER_OR = "Prozessschnittstellen hinter einem OR-/XOR-Split ist nicht erlaubt."; -ORYX.I18N.SyntaxChecker.EPC_FUNCTION_AFTER_FUNCTION = "Auf eine Funktion darf keine Funktion folgen."; -ORYX.I18N.SyntaxChecker.EPC_EVENT_AFTER_EVENT = "Auf ein Ereignis darf kein Ereignis folgen."; -ORYX.I18N.SyntaxChecker.EPC_PI_AFTER_FUNCTION = "Auf eine Funktion darf keine Prozessschnittstelle folgen."; -ORYX.I18N.SyntaxChecker.EPC_FUNCTION_AFTER_PI = "Auf eine Prozessschnittstelle darf keine Funktion folgen."; +ORYX.I18N.SyntaxChecker.EPC_FUNCTION_AFTER_FUNCTION = "Auf eine Funktion darf keine Funktion folgen."; +ORYX.I18N.SyntaxChecker.EPC_EVENT_AFTER_EVENT = "Auf ein Ereignis darf kein Ereignis folgen."; +ORYX.I18N.SyntaxChecker.EPC_PI_AFTER_FUNCTION = "Auf eine Funktion darf keine Prozessschnittstelle folgen."; +ORYX.I18N.SyntaxChecker.EPC_FUNCTION_AFTER_PI = "Auf eine Prozessschnittstelle darf keine Funktion folgen."; ORYX.I18N.SyntaxChecker.EPC_SOURCE_EQUALS_TARGET = "Eine Kante muss zwei verschiedene Knoten verbinden." -if(!ORYX.I18N.SyntaxChecker.PetriNet) ORYX.I18N.SyntaxChecker.PetriNet={}; +if (!ORYX.I18N.SyntaxChecker.PetriNet) ORYX.I18N.SyntaxChecker.PetriNet = {}; ORYX.I18N.SyntaxChecker.PetriNet_NOT_BIPARTITE = "Der Graph ist nicht bepartit."; ORYX.I18N.SyntaxChecker.PetriNet_NO_LABEL = "Bezeichnung für einen bezeichnete Transition ist nicht gesetzt."; ORYX.I18N.SyntaxChecker.PetriNet_NO_ID = "Ein Knoten besitzt keine ID."; @@ -323,19 +323,19 @@ ORYX.I18N.Node = "Knoten"; ORYX.I18N.SyntaxChecker.notice = "Bitte bewegen Sie den Mauszeiger über ein rotes Kreuz, um die Details zu erfahren."; /** New Language Properties: 15.07.2009*/ -if(!ORYX.I18N.Layouting) ORYX.I18N.Layouting ={}; +if (!ORYX.I18N.Layouting) ORYX.I18N.Layouting = {}; ORYX.I18N.Layouting.doing = "Layouten..."; /** New Language Properties: 18.08.2009*/ ORYX.I18N.SyntaxChecker.MULT_ERRORS = "Mehrere Fehler"; /** New Language Properties: 08.09.2009*/ -if(!ORYX.I18N.PropertyWindow) ORYX.I18N.PropertyWindow = {}; +if (!ORYX.I18N.PropertyWindow) ORYX.I18N.PropertyWindow = {}; ORYX.I18N.PropertyWindow.oftenUsed = "Hauptattribute"; ORYX.I18N.PropertyWindow.moreProps = "Mehr Attribute"; /** New Language Properties 01.10.2009 */ -if(!ORYX.I18N.SyntaxChecker.BPMN2) ORYX.I18N.SyntaxChecker.BPMN2 = {}; +if (!ORYX.I18N.SyntaxChecker.BPMN2) ORYX.I18N.SyntaxChecker.BPMN2 = {}; ORYX.I18N.SyntaxChecker.BPMN2_DATA_INPUT_WITH_INCOMING_DATA_ASSOCIATION = "Ein Dateninput darf keine ausgehenden Datenassoziationen haben."; ORYX.I18N.SyntaxChecker.BPMN2_DATA_OUTPUT_WITH_OUTGOING_DATA_ASSOCIATION = "Ein Datenoutput darf keine eingehenden Datenassoziationen haben."; @@ -360,13 +360,13 @@ ORYX.I18N.SyntaxChecker.BPMN2_EVENT_SUBPROCESS_BAD_CONNECTION = "Ein Ereignis-Un ORYX.I18N.SyntaxChecker.BPMN_MESSAGE_FLOW_NOT_CONNECTED = "Mindestens ein Ende des Nachrichtenflusses muss mit einem anderen Objekt verbunden sein."; /** New Language Properties 05.11.2009 */ -if(!ORYX.I18N.RESIZE) ORYX.I18N.RESIZE = {}; +if (!ORYX.I18N.RESIZE) ORYX.I18N.RESIZE = {}; ORYX.I18N.RESIZE.tipGrow = "Zeichenfläche vergrößern:"; ORYX.I18N.RESIZE.tipShrink = "Zeichenfläche verkleinern:"; ORYX.I18N.RESIZE.N = "Nach oben"; ORYX.I18N.RESIZE.W = "Nach links"; -ORYX.I18N.RESIZE.S ="Nach unten"; -ORYX.I18N.RESIZE.E ="Nach rechts"; +ORYX.I18N.RESIZE.S = "Nach unten"; +ORYX.I18N.RESIZE.E = "Nach rechts"; /** New Language Properties 24.11.2009 */ ORYX.I18N.SyntaxChecker.BPMN2_TOO_MANY_INITIATING_MESSAGES = "Eine Choreographie-Aktivität darf nur eine initiierende Nachricht besitzen."; diff --git a/pear-modules/pear-process/src/main/resources/static/editor-app/editor/i18n/translation_en_us.js b/pear-modules/pear-process/src/main/resources/static/editor-app/editor/i18n/translation_en_us.js index 6c3ebc06a40d5cdd89e9ef60b7c765348eb7e98c..5a60b6de894350be3b4759a173645fc80288de1f 100644 --- a/pear-modules/pear-process/src/main/resources/static/editor-app/editor/i18n/translation_en_us.js +++ b/pear-modules/pear-process/src/main/resources/static/editor-app/editor/i18n/translation_en_us.js @@ -1,24 +1,24 @@ /** * @author nicolas.peters - * + * * Contains all strings for the default language (en-us). * Version 1 - 08/29/08 */ -if(!ORYX) var ORYX = {}; +if (!ORYX) var ORYX = {}; -if(!ORYX.I18N) ORYX.I18N = {}; +if (!ORYX.I18N) ORYX.I18N = {}; ORYX.I18N.Language = "en_us"; //Pattern _ in lower case! -if(!ORYX.I18N.Oryx) ORYX.I18N.Oryx = {}; +if (!ORYX.I18N.Oryx) ORYX.I18N.Oryx = {}; -ORYX.I18N.Oryx.title = "Oryx"; -ORYX.I18N.Oryx.noBackendDefined = "Caution! \nNo Backend defined.\n The requested model cannot be loaded. Try to load a configuration with a save plugin."; -ORYX.I18N.Oryx.pleaseWait = "Please wait while loading..."; +ORYX.I18N.Oryx.title = "Oryx"; +ORYX.I18N.Oryx.noBackendDefined = "Caution! \nNo Backend defined.\n The requested model cannot be loaded. Try to load a configuration with a save plugin."; +ORYX.I18N.Oryx.pleaseWait = "Please wait while loading..."; ORYX.I18N.Oryx.notLoggedOn = "Not logged on"; ORYX.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."; -if(!ORYX.I18N.AddDocker) ORYX.I18N.AddDocker = {}; +if (!ORYX.I18N.AddDocker) ORYX.I18N.AddDocker = {}; ORYX.I18N.AddDocker.group = "Docker"; ORYX.I18N.AddDocker.add = "Add Docker"; @@ -26,7 +26,7 @@ ORYX.I18N.AddDocker.addDesc = "Add a Docker to an edge, by clicking on it"; ORYX.I18N.AddDocker.del = "Delete Docker"; ORYX.I18N.AddDocker.delDesc = "Delete a Docker"; -if(!ORYX.I18N.Arrangement) ORYX.I18N.Arrangement = {}; +if (!ORYX.I18N.Arrangement) ORYX.I18N.Arrangement = {}; ORYX.I18N.Arrangement.groupZ = "Z-Order"; ORYX.I18N.Arrangement.btf = "Bring To Front"; @@ -53,7 +53,7 @@ ORYX.I18N.Arrangement.arDesc = "Right"; ORYX.I18N.Arrangement.as = "Alignment Same Size"; ORYX.I18N.Arrangement.asDesc = "Same Size"; -if(!ORYX.I18N.Edit) ORYX.I18N.Edit = {}; +if (!ORYX.I18N.Edit) ORYX.I18N.Edit = {}; ORYX.I18N.Edit.group = "Edit"; ORYX.I18N.Edit.cut = "Cut"; @@ -65,7 +65,7 @@ ORYX.I18N.Edit.pasteDesc = "Pastes the Oryx clipboard to the canvas"; ORYX.I18N.Edit.del = "Delete"; ORYX.I18N.Edit.delDesc = "Deletes all selected shapes"; -if(!ORYX.I18N.EPCSupport) ORYX.I18N.EPCSupport = {}; +if (!ORYX.I18N.EPCSupport) ORYX.I18N.EPCSupport = {}; ORYX.I18N.EPCSupport.group = "EPC"; ORYX.I18N.EPCSupport.exp = "Export EPC"; @@ -81,7 +81,7 @@ ORYX.I18N.EPCSupport.close = "Close"; ORYX.I18N.EPCSupport.error = "Error"; ORYX.I18N.EPCSupport.progressImp = "Import..."; -if(!ORYX.I18N.ERDFSupport) ORYX.I18N.ERDFSupport = {}; +if (!ORYX.I18N.ERDFSupport) ORYX.I18N.ERDFSupport = {}; ORYX.I18N.ERDFSupport.exp = "Export to ERDF"; ORYX.I18N.ERDFSupport.expDesc = "Export to ERDF"; @@ -102,7 +102,7 @@ ORYX.I18N.ERDFSupport.close = "Close"; ORYX.I18N.ERDFSupport.deprTitle = "Really export to eRDF?"; ORYX.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?"; -if(!ORYX.I18N.jPDLSupport) ORYX.I18N.jPDLSupport = {}; +if (!ORYX.I18N.jPDLSupport) ORYX.I18N.jPDLSupport = {}; ORYX.I18N.jPDLSupport.group = "ExecBPMN"; ORYX.I18N.jPDLSupport.exp = "Export to jPDL"; @@ -112,7 +112,7 @@ ORYX.I18N.jPDLSupport.impDesc = "Import jPDL File"; ORYX.I18N.jPDLSupport.impFailedReq = "Request for import of jPDL failed."; ORYX.I18N.jPDLSupport.impFailedJson = "Transformation of jPDL failed."; ORYX.I18N.jPDLSupport.impFailedJsonAbort = "Import aborted."; -ORYX.I18N.jPDLSupport.loadSseQuestionTitle = "jBPM stencil set extension needs to be loaded"; +ORYX.I18N.jPDLSupport.loadSseQuestionTitle = "jBPM stencil set extension needs to be loaded"; ORYX.I18N.jPDLSupport.loadSseQuestionBody = "In order to import jPDL, the stencil set extension has to be loaded. Do you want to proceed?"; ORYX.I18N.jPDLSupport.expFailedReq = "Request for export of model failed."; ORYX.I18N.jPDLSupport.expFailedXml = "Export to jPDL failed. Exporter reported: "; @@ -124,7 +124,7 @@ ORYX.I18N.jPDLSupport.impBtn = "Import"; ORYX.I18N.jPDLSupport.impProgress = "Importing..."; ORYX.I18N.jPDLSupport.close = "Close"; -if(!ORYX.I18N.Save) ORYX.I18N.Save = {}; +if (!ORYX.I18N.Save) ORYX.I18N.Save = {}; ORYX.I18N.Save.group = "File"; ORYX.I18N.Save.save = "Save"; @@ -143,7 +143,7 @@ ORYX.I18N.Save.noRights = "You have no rights to save changes."; ORYX.I18N.Save.saving = "Saving"; ORYX.I18N.Save.saveAsHint = "The process diagram is stored under:"; -if(!ORYX.I18N.File) ORYX.I18N.File = {}; +if (!ORYX.I18N.File) ORYX.I18N.File = {}; ORYX.I18N.File.group = "File"; ORYX.I18N.File.print = "Print"; @@ -157,7 +157,7 @@ ORYX.I18N.File.genPDFFailed = "Generating PDF failed."; ORYX.I18N.File.printTitle = "Print"; ORYX.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?"; -if(!ORYX.I18N.Grouping) ORYX.I18N.Grouping = {}; +if (!ORYX.I18N.Grouping) ORYX.I18N.Grouping = {}; ORYX.I18N.Grouping.grouping = "Grouping"; ORYX.I18N.Grouping.group = "Group"; @@ -165,11 +165,11 @@ ORYX.I18N.Grouping.groupDesc = "Groups all selected shapes"; ORYX.I18N.Grouping.ungroup = "Ungroup"; ORYX.I18N.Grouping.ungroupDesc = "Deletes the group of all selected Shapes"; -if(!ORYX.I18N.Loading) ORYX.I18N.Loading = {}; +if (!ORYX.I18N.Loading) ORYX.I18N.Loading = {}; -ORYX.I18N.Loading.waiting ="Please wait..."; +ORYX.I18N.Loading.waiting = "Please wait..."; -if(!ORYX.I18N.PropertyWindow) ORYX.I18N.PropertyWindow = {}; +if (!ORYX.I18N.PropertyWindow) ORYX.I18N.PropertyWindow = {}; ORYX.I18N.PropertyWindow.name = "Name"; ORYX.I18N.PropertyWindow.value = "Value"; @@ -183,13 +183,13 @@ ORYX.I18N.PropertyWindow.ok = "Ok"; ORYX.I18N.PropertyWindow.cancel = "Cancel"; ORYX.I18N.PropertyWindow.dateFormat = "m/d/y"; -if(!ORYX.I18N.ShapeMenuPlugin) ORYX.I18N.ShapeMenuPlugin = {}; +if (!ORYX.I18N.ShapeMenuPlugin) ORYX.I18N.ShapeMenuPlugin = {}; ORYX.I18N.ShapeMenuPlugin.drag = "Drag"; ORYX.I18N.ShapeMenuPlugin.clickDrag = "Click or drag"; ORYX.I18N.ShapeMenuPlugin.morphMsg = "Morph shape"; -if(!ORYX.I18N.SyntaxChecker) ORYX.I18N.SyntaxChecker = {}; +if (!ORYX.I18N.SyntaxChecker) ORYX.I18N.SyntaxChecker = {}; ORYX.I18N.SyntaxChecker.group = "Verification"; ORYX.I18N.SyntaxChecker.name = "Syntax Checker"; @@ -198,25 +198,25 @@ ORYX.I18N.SyntaxChecker.noErrors = "There are no syntax errors."; ORYX.I18N.SyntaxChecker.invalid = "Invalid answer from server."; ORYX.I18N.SyntaxChecker.checkingMessage = "Checking ..."; -if(!ORYX.I18N.FormHandler) ORYX.I18N.FormHandler = {}; +if (!ORYX.I18N.FormHandler) ORYX.I18N.FormHandler = {}; ORYX.I18N.FormHandler.group = "FormHandling"; ORYX.I18N.FormHandler.name = "FormHandler"; ORYX.I18N.FormHandler.desc = "Testing from handling"; -if(!ORYX.I18N.Deployer) ORYX.I18N.Deployer = {}; +if (!ORYX.I18N.Deployer) ORYX.I18N.Deployer = {}; ORYX.I18N.Deployer.group = "Deployment"; ORYX.I18N.Deployer.name = "Deployer"; ORYX.I18N.Deployer.desc = "Deploy to engine"; -if(!ORYX.I18N.Tester) ORYX.I18N.Tester = {}; +if (!ORYX.I18N.Tester) ORYX.I18N.Tester = {}; ORYX.I18N.Tester.group = "Testing"; ORYX.I18N.Tester.name = "Test process"; ORYX.I18N.Tester.desc = "Open the test component to test this process definition"; -if(!ORYX.I18N.Undo) ORYX.I18N.Undo = {}; +if (!ORYX.I18N.Undo) ORYX.I18N.Undo = {}; ORYX.I18N.Undo.group = "Undo"; ORYX.I18N.Undo.undo = "Undo"; @@ -224,7 +224,7 @@ ORYX.I18N.Undo.undoDesc = "Undo the last action"; ORYX.I18N.Undo.redo = "Redo"; ORYX.I18N.Undo.redoDesc = "Redo the last undone action"; -if(!ORYX.I18N.View) ORYX.I18N.View = {}; +if (!ORYX.I18N.View) ORYX.I18N.View = {}; ORYX.I18N.View.group = "Zoom"; ORYX.I18N.View.zoomIn = "Zoom In"; @@ -236,7 +236,7 @@ ORYX.I18N.View.zoomStandardDesc = "Zoom to the standard level"; ORYX.I18N.View.zoomFitToModel = "Zoom fit to model"; ORYX.I18N.View.zoomFitToModelDesc = "Zoom to fit the model size"; -if(!ORYX.I18N.XFormsSerialization) ORYX.I18N.XFormsSerialization = {}; +if (!ORYX.I18N.XFormsSerialization) ORYX.I18N.XFormsSerialization = {}; ORYX.I18N.XFormsSerialization.group = "XForms Serialization"; ORYX.I18N.XFormsSerialization.exportXForms = "XForms Export"; @@ -260,7 +260,7 @@ ORYX.I18N.XFormsSerialization.close = "Close"; ORYX.I18N.PropertyWindow.title = "Properties"; -if(!ORYX.I18N.ShapeRepository) ORYX.I18N.ShapeRepository = {}; +if (!ORYX.I18N.ShapeRepository) ORYX.I18N.ShapeRepository = {}; ORYX.I18N.ShapeRepository.title = "Shape Repository"; ORYX.I18N.Save.dialogDesciption = "Please enter a name, a description and a comment."; @@ -269,7 +269,7 @@ ORYX.I18N.Save.dialogLabelDesc = "Description"; ORYX.I18N.Save.dialogLabelType = "Type"; ORYX.I18N.Save.dialogLabelComment = "Revision comment"; -if(!ORYX.I18N.Perspective) ORYX.I18N.Perspective = {}; +if (!ORYX.I18N.Perspective) ORYX.I18N.Perspective = {}; ORYX.I18N.Perspective.no = "No Perspective" ORYX.I18N.Perspective.noTip = "Unload the current perspective" @@ -294,19 +294,19 @@ ORYX.I18N.JSONSupport = { }; /** New Language Properties: 09.05.2009 */ -if(!ORYX.I18N.JSONImport) ORYX.I18N.JSONImport = {}; +if (!ORYX.I18N.JSONImport) ORYX.I18N.JSONImport = {}; ORYX.I18N.JSONImport.title = "JSON Import"; ORYX.I18N.JSONImport.wrongSS = "The stencil set of the imported file ({0}) does not match to the loaded stencil set ({1})." /** New Language Properties: 14.05.2009 */ -if(!ORYX.I18N.RDFExport) ORYX.I18N.RDFExport = {}; +if (!ORYX.I18N.RDFExport) ORYX.I18N.RDFExport = {}; ORYX.I18N.RDFExport.group = "Export"; ORYX.I18N.RDFExport.rdfExport = "Export to RDF"; ORYX.I18N.RDFExport.rdfExportDescription = "Exports current model to the XML serialization defined for the Resource Description Framework (RDF)"; /** New Language Properties: 15.05.2009*/ -if(!ORYX.I18N.SyntaxChecker.BPMN) ORYX.I18N.SyntaxChecker.BPMN={}; +if (!ORYX.I18N.SyntaxChecker.BPMN) ORYX.I18N.SyntaxChecker.BPMN = {}; ORYX.I18N.SyntaxChecker.BPMN_NO_SOURCE = "An edge must have a source."; ORYX.I18N.SyntaxChecker.BPMN_NO_TARGET = "An edge must have a target."; ORYX.I18N.SyntaxChecker.BPMN_DIFFERENT_PROCESS = "Source and target node must be contained in the same process."; @@ -321,18 +321,18 @@ ORYX.I18N.SyntaxChecker.BPMN_ENDEVENT_WITH_OUTGOING_CONTROL_FLOW = "End events m ORYX.I18N.SyntaxChecker.BPMN_EVENTBASEDGATEWAY_BADCONTINUATION = "Event-based gateways must not be followed by gateways or subprocesses."; ORYX.I18N.SyntaxChecker.BPMN_NODE_NOT_ALLOWED = "Node type is not allowed."; -if(!ORYX.I18N.SyntaxChecker.IBPMN) ORYX.I18N.SyntaxChecker.IBPMN={}; +if (!ORYX.I18N.SyntaxChecker.IBPMN) ORYX.I18N.SyntaxChecker.IBPMN = {}; ORYX.I18N.SyntaxChecker.IBPMN_NO_ROLE_SET = "Interactions must have a sender and a receiver role set"; ORYX.I18N.SyntaxChecker.IBPMN_NO_INCOMING_SEQFLOW = "This node must have incoming sequence flow."; ORYX.I18N.SyntaxChecker.IBPMN_NO_OUTGOING_SEQFLOW = "This node must have outgoing sequence flow."; -if(!ORYX.I18N.SyntaxChecker.InteractionNet) ORYX.I18N.SyntaxChecker.InteractionNet={}; +if (!ORYX.I18N.SyntaxChecker.InteractionNet) ORYX.I18N.SyntaxChecker.InteractionNet = {}; ORYX.I18N.SyntaxChecker.InteractionNet_SENDER_NOT_SET = "Sender not set"; ORYX.I18N.SyntaxChecker.InteractionNet_RECEIVER_NOT_SET = "Receiver not set"; ORYX.I18N.SyntaxChecker.InteractionNet_MESSAGETYPE_NOT_SET = "Message type not set"; ORYX.I18N.SyntaxChecker.InteractionNet_ROLE_NOT_SET = "Role not set"; -if(!ORYX.I18N.SyntaxChecker.EPC) ORYX.I18N.SyntaxChecker.EPC={}; +if (!ORYX.I18N.SyntaxChecker.EPC) ORYX.I18N.SyntaxChecker.EPC = {}; ORYX.I18N.SyntaxChecker.EPC_NO_SOURCE = "Each edge must have a source."; ORYX.I18N.SyntaxChecker.EPC_NO_TARGET = "Each edge must have a target."; ORYX.I18N.SyntaxChecker.EPC_NOT_CONNECTED = "Node must be connected with edges."; @@ -342,13 +342,13 @@ ORYX.I18N.SyntaxChecker.EPC_NO_CORRECT_CONNECTOR = "Node is no correct connector ORYX.I18N.SyntaxChecker.EPC_MANY_STARTS = "There must be only one start event."; ORYX.I18N.SyntaxChecker.EPC_FUNCTION_AFTER_OR = "There must be no functions after a splitting OR/XOR."; ORYX.I18N.SyntaxChecker.EPC_PI_AFTER_OR = "There must be no process interface after a splitting OR/XOR."; -ORYX.I18N.SyntaxChecker.EPC_FUNCTION_AFTER_FUNCTION = "There must be no function after a function."; -ORYX.I18N.SyntaxChecker.EPC_EVENT_AFTER_EVENT = "There must be no event after an event."; -ORYX.I18N.SyntaxChecker.EPC_PI_AFTER_FUNCTION = "There must be no process interface after a function."; -ORYX.I18N.SyntaxChecker.EPC_FUNCTION_AFTER_PI = "There must be no function after a process interface."; +ORYX.I18N.SyntaxChecker.EPC_FUNCTION_AFTER_FUNCTION = "There must be no function after a function."; +ORYX.I18N.SyntaxChecker.EPC_EVENT_AFTER_EVENT = "There must be no event after an event."; +ORYX.I18N.SyntaxChecker.EPC_PI_AFTER_FUNCTION = "There must be no process interface after a function."; +ORYX.I18N.SyntaxChecker.EPC_FUNCTION_AFTER_PI = "There must be no function after a process interface."; ORYX.I18N.SyntaxChecker.EPC_SOURCE_EQUALS_TARGET = "Edge must connect two distinct nodes." -if(!ORYX.I18N.SyntaxChecker.PetriNet) ORYX.I18N.SyntaxChecker.PetriNet={}; +if (!ORYX.I18N.SyntaxChecker.PetriNet) ORYX.I18N.SyntaxChecker.PetriNet = {}; ORYX.I18N.SyntaxChecker.PetriNet_NOT_BIPARTITE = "The graph is not bipartite"; ORYX.I18N.SyntaxChecker.PetriNet_NO_LABEL = "Label not set for a labeled transition"; ORYX.I18N.SyntaxChecker.PetriNet_NO_ID = "There is a node without id"; @@ -363,28 +363,28 @@ ORYX.I18N.Node = "Node"; ORYX.I18N.SyntaxChecker.notice = "Move the mouse over a red cross icon to see the error message."; /** New Language Properties: 05.06.2009*/ -if(!ORYX.I18N.RESIZE) ORYX.I18N.RESIZE = {}; +if (!ORYX.I18N.RESIZE) ORYX.I18N.RESIZE = {}; ORYX.I18N.RESIZE.tipGrow = "Increase canvas size:"; ORYX.I18N.RESIZE.tipShrink = "Decrease canvas size:"; ORYX.I18N.RESIZE.N = "Top"; ORYX.I18N.RESIZE.W = "Left"; -ORYX.I18N.RESIZE.S ="Down"; -ORYX.I18N.RESIZE.E ="Right"; +ORYX.I18N.RESIZE.S = "Down"; +ORYX.I18N.RESIZE.E = "Right"; /** New Language Properties: 15.07.2009*/ -if(!ORYX.I18N.Layouting) ORYX.I18N.Layouting ={}; +if (!ORYX.I18N.Layouting) ORYX.I18N.Layouting = {}; ORYX.I18N.Layouting.doing = "Layouting..."; /** New Language Properties: 18.08.2009*/ ORYX.I18N.SyntaxChecker.MULT_ERRORS = "Multiple Errors"; /** New Language Properties: 08.09.2009*/ -if(!ORYX.I18N.PropertyWindow) ORYX.I18N.PropertyWindow = {}; +if (!ORYX.I18N.PropertyWindow) ORYX.I18N.PropertyWindow = {}; ORYX.I18N.PropertyWindow.oftenUsed = "Often used"; ORYX.I18N.PropertyWindow.moreProps = "More Properties"; /** New Language Properties 01.10.2009 */ -if(!ORYX.I18N.SyntaxChecker.BPMN2) ORYX.I18N.SyntaxChecker.BPMN2 = {}; +if (!ORYX.I18N.SyntaxChecker.BPMN2) ORYX.I18N.SyntaxChecker.BPMN2 = {}; ORYX.I18N.SyntaxChecker.BPMN2_DATA_INPUT_WITH_INCOMING_DATA_ASSOCIATION = "A Data Input must not have any incoming Data Associations."; ORYX.I18N.SyntaxChecker.BPMN2_DATA_OUTPUT_WITH_OUTGOING_DATA_ASSOCIATION = "A Data Output must not have any outgoing Data Associations."; diff --git a/pear-modules/pear-process/src/main/resources/static/editor-app/editor/i18n/translation_signavio_de.js b/pear-modules/pear-process/src/main/resources/static/editor-app/editor/i18n/translation_signavio_de.js index b03e6e7aadecf962aa93064aa1ddae58cbea7c2c..c0c6e7d690df726153cfa1c2579b37be11eee3dd 100644 --- a/pear-modules/pear-process/src/main/resources/static/editor-app/editor/i18n/translation_signavio_de.js +++ b/pear-modules/pear-process/src/main/resources/static/editor-app/editor/i18n/translation_signavio_de.js @@ -1,8 +1,8 @@ Ext.PagingToolbar.prototype.firstText = "Erste Seite"; Ext.PagingToolbar.prototype.prevText = "Vorherige Seite"; Ext.PagingToolbar.prototype.nextText = "Nächste Seite"; -Ext.PagingToolbar.prototype.lastText = "Letzte Seite"; - +Ext.PagingToolbar.prototype.lastText = "Letzte Seite"; + ORYX.I18N.PropertyWindow.dateFormat = "d.m.y"; @@ -41,16 +41,24 @@ ORYX.I18N.Save.exception = "Beim Speichern Ihres Diagramms sind einige Probleme ORYX.I18N.Save.retrieveData = "Bitte warten, Daten werden geladen"; /** New Language Properties: 10.6.09*/ -if(!ORYX.I18N.ShapeMenuPlugin) ORYX.I18N.ShapeMenuPlugin = {}; +if (!ORYX.I18N.ShapeMenuPlugin) ORYX.I18N.ShapeMenuPlugin = {}; ORYX.I18N.ShapeMenuPlugin.morphMsg = "Umwandeln"; ORYX.I18N.ShapeMenuPlugin.morphWarningTitleMsg = "Umwandeln"; ORYX.I18N.ShapeMenuPlugin.morphWarningMsg = "Einige Kindelemente können nicht im neuen Element enthalten sein.
Möchten Sie dennoch das Element umwandeln?"; -if (!Signavio) { var Signavio = {}; } -if (!Signavio.I18N) { Signavio.I18N = {} } -if (!Signavio.I18N.Editor) { Signavio.I18N.Editor = {} } +if (!Signavio) { + var Signavio = {}; +} +if (!Signavio.I18N) { + Signavio.I18N = {} +} +if (!Signavio.I18N.Editor) { + Signavio.I18N.Editor = {} +} -if (!Signavio.I18N.Editor.Linking) { Signavio.I18N.Editor.Linking = {} } +if (!Signavio.I18N.Editor.Linking) { + Signavio.I18N.Editor.Linking = {} +} Signavio.I18N.Editor.Linking.CreateDiagram = "Neues Diagramm erstellen:"; Signavio.I18N.Editor.Linking.UseDiagram = "Vorhandenes Diagramm verwenden"; Signavio.I18N.Editor.Linking.UseLink = "Web-Link verwenden"; @@ -69,19 +77,21 @@ Signavio.I18N.Editor.Linking.OpenLink = "Öffnen"; Signavio.I18N.Editor.Linking.BrokenLink = "Der Link ist nicht verfügbar!"; Signavio.I18N.Editor.Linking.PreviewTitle = "Vorschau"; -if(!ORYX.I18N.PropertyWindow) ORYX.I18N.PropertyWindow = {}; +if (!ORYX.I18N.PropertyWindow) ORYX.I18N.PropertyWindow = {}; ORYX.I18N.PropertyWindow.oftenUsed = "Hauptattribute"; ORYX.I18N.PropertyWindow.moreProps = "Weitere Attribute"; ORYX.I18N.PropertyWindow.characteristicNr = "Kennzahlen"; ORYX.I18N.PropertyWindow.meta = "Eigene Attribute"; -if(!ORYX.I18N.PropertyWindow.Category){ORYX.I18N.PropertyWindow.Category = {}} +if (!ORYX.I18N.PropertyWindow.Category) { + ORYX.I18N.PropertyWindow.Category = {} +} ORYX.I18N.PropertyWindow.Category.popular = "Hauptattribute"; ORYX.I18N.PropertyWindow.Category.characteristicnr = "Kennzahlen"; ORYX.I18N.PropertyWindow.Category.others = "Weitere Attribute"; ORYX.I18N.PropertyWindow.Category.meta = "Eigene Attribute"; -if(!ORYX.I18N.PropertyWindow.ListView) ORYX.I18N.PropertyWindow.ListView = {}; +if (!ORYX.I18N.PropertyWindow.ListView) ORYX.I18N.PropertyWindow.ListView = {}; ORYX.I18N.PropertyWindow.ListView.title = "Attribut: "; ORYX.I18N.PropertyWindow.ListView.dataViewLabel = "Bereits vorhandene Einträge"; ORYX.I18N.PropertyWindow.ListView.dataViewEmptyText = "Es sind noch keine Einträge vorhanden."; @@ -90,17 +100,21 @@ ORYX.I18N.PropertyWindow.ListView.buttonAdd = "Hinzufügen"; ORYX.I18N.PropertyWindow.ListView.save = "Speichern"; ORYX.I18N.PropertyWindow.ListView.cancel = "Abbrachen"; -if(!Signavio.I18N.Buttons) Signavio.I18N.Buttons = {}; -Signavio.I18N.Buttons.save = "Speichern"; -Signavio.I18N.Buttons.cancel = "Abbrechen"; -Signavio.I18N.Buttons.remove = "Entfernen"; +if (!Signavio.I18N.Buttons) Signavio.I18N.Buttons = {}; +Signavio.I18N.Buttons.save = "Speichern"; +Signavio.I18N.Buttons.cancel = "Abbrechen"; +Signavio.I18N.Buttons.remove = "Entfernen"; -if(!Signavio.I18N.btn) {Signavio.I18N.btn = {};} +if (!Signavio.I18N.btn) { + Signavio.I18N.btn = {}; +} Signavio.I18N.btn.btnEdit = "Editieren"; Signavio.I18N.btn.btnRemove = "Löschen"; Signavio.I18N.btn.moveUp = "Nach oben"; Signavio.I18N.btn.moveDown = "Nach unten"; -if(!Signavio.I18N.field) {Signavio.I18N.field = {};} +if (!Signavio.I18N.field) { + Signavio.I18N.field = {}; +} Signavio.I18N.field.Url = "URL"; -Signavio.I18N.field.UrlLabel = "Label"; \ No newline at end of file +Signavio.I18N.field.UrlLabel = "Label"; diff --git a/pear-modules/pear-process/src/main/resources/static/editor-app/editor/i18n/translation_signavio_en_us.js b/pear-modules/pear-process/src/main/resources/static/editor-app/editor/i18n/translation_signavio_en_us.js index e103b214a2824cb651345407ebd9fe2c40a21d84..47b727dfad31760b46043199d63951a821904d06 100644 --- a/pear-modules/pear-process/src/main/resources/static/editor-app/editor/i18n/translation_signavio_en_us.js +++ b/pear-modules/pear-process/src/main/resources/static/editor-app/editor/i18n/translation_signavio_en_us.js @@ -3,7 +3,7 @@ ORYX.I18N.PropertyWindow.dateFormat = "d/m/y"; ORYX.I18N.View.East = "Attributes"; ORYX.I18N.View.West = "Modeling Elements"; -ORYX.I18N.Oryx.title = "Signavio"; +ORYX.I18N.Oryx.title = "Signavio"; ORYX.I18N.Oryx.pleaseWait = "Please wait while the Signavio Process Editor is loading..."; ORYX.I18N.Edit.cutDesc = "Cuts the selection into the clipboard"; ORYX.I18N.Edit.copyDesc = "Copies the selection into the clipboard"; @@ -27,16 +27,24 @@ ORYX.I18N.Save.exception = "Some exceptions are raised while trying to save your ORYX.I18N.Save.retrieveData = "Please wait, data is retrieving."; /** New Language Properties: 10.6.09*/ -if(!ORYX.I18N.ShapeMenuPlugin) ORYX.I18N.ShapeMenuPlugin = {}; +if (!ORYX.I18N.ShapeMenuPlugin) ORYX.I18N.ShapeMenuPlugin = {}; ORYX.I18N.ShapeMenuPlugin.morphMsg = "Transform shape"; ORYX.I18N.ShapeMenuPlugin.morphWarningTitleMsg = "Transform shape"; ORYX.I18N.ShapeMenuPlugin.morphWarningMsg = "There are child shape which can not be contained in the transformed element.
Do you want to transform anyway?"; -if (!Signavio) { var Signavio = {}; } -if (!Signavio.I18N) { Signavio.I18N = {} } -if (!Signavio.I18N.Editor) { Signavio.I18N.Editor = {} } +if (!Signavio) { + var Signavio = {}; +} +if (!Signavio.I18N) { + Signavio.I18N = {} +} +if (!Signavio.I18N.Editor) { + Signavio.I18N.Editor = {} +} -if (!Signavio.I18N.Editor.Linking) { Signavio.I18N.Editor.Linking = {} } +if (!Signavio.I18N.Editor.Linking) { + Signavio.I18N.Editor.Linking = {} +} Signavio.I18N.Editor.Linking.CreateDiagram = "Create a new diagram"; Signavio.I18N.Editor.Linking.UseDiagram = "Use existing diagram"; Signavio.I18N.Editor.Linking.UseLink = "Use web link"; @@ -55,12 +63,14 @@ Signavio.I18N.Editor.Linking.OpenLink = "Open"; Signavio.I18N.Editor.Linking.BrokenLink = "The link is broken!"; Signavio.I18N.Editor.Linking.PreviewTitle = "Preview"; -if(!Signavio.I18N.Glossary_Support) { Signavio.I18N.Glossary_Support = {}; } +if (!Signavio.I18N.Glossary_Support) { + Signavio.I18N.Glossary_Support = {}; +} Signavio.I18N.Glossary_Support.renameEmpty = "No dictionary entry"; Signavio.I18N.Glossary_Support.renameLoading = "Searching..."; /** New Language Properties: 08.09.2009*/ -if(!ORYX.I18N.PropertyWindow) ORYX.I18N.PropertyWindow = {}; +if (!ORYX.I18N.PropertyWindow) ORYX.I18N.PropertyWindow = {}; ORYX.I18N.PropertyWindow.oftenUsed = "Main properties"; ORYX.I18N.PropertyWindow.moreProps = "More properties"; @@ -71,19 +81,21 @@ ORYX.I18N.PropertyWindow.btnUp = "Move up"; ORYX.I18N.PropertyWindow.btnDown = "Move down"; ORYX.I18N.PropertyWindow.createNew = "Create new"; -if(!ORYX.I18N.PropertyWindow) ORYX.I18N.PropertyWindow = {}; +if (!ORYX.I18N.PropertyWindow) ORYX.I18N.PropertyWindow = {}; ORYX.I18N.PropertyWindow.oftenUsed = "Main attributes"; ORYX.I18N.PropertyWindow.moreProps = "More attributes"; ORYX.I18N.PropertyWindow.characteristicNr = "Cost & Resource Analysis"; ORYX.I18N.PropertyWindow.meta = "Custom attributes"; -if(!ORYX.I18N.PropertyWindow.Category){ORYX.I18N.PropertyWindow.Category = {}} +if (!ORYX.I18N.PropertyWindow.Category) { + ORYX.I18N.PropertyWindow.Category = {} +} ORYX.I18N.PropertyWindow.Category.popular = "Main Attributes"; ORYX.I18N.PropertyWindow.Category.characteristicnr = "Cost & Resource Analysis"; ORYX.I18N.PropertyWindow.Category.others = "More Attributes"; ORYX.I18N.PropertyWindow.Category.meta = "Custom Attributes"; -if(!ORYX.I18N.PropertyWindow.ListView) ORYX.I18N.PropertyWindow.ListView = {}; +if (!ORYX.I18N.PropertyWindow.ListView) ORYX.I18N.PropertyWindow.ListView = {}; ORYX.I18N.PropertyWindow.ListView.title = "Edit: "; ORYX.I18N.PropertyWindow.ListView.dataViewLabel = "Already existing entries."; ORYX.I18N.PropertyWindow.ListView.dataViewEmptyText = "No list entries."; @@ -92,17 +104,21 @@ ORYX.I18N.PropertyWindow.ListView.buttonAdd = "Add"; ORYX.I18N.PropertyWindow.ListView.save = "Save"; ORYX.I18N.PropertyWindow.ListView.cancel = "Cancel"; -if(!Signavio.I18N.Buttons) Signavio.I18N.Buttons = {}; -Signavio.I18N.Buttons.save = "Save"; -Signavio.I18N.Buttons.cancel = "Cancel"; -Signavio.I18N.Buttons.remove = "Remove"; +if (!Signavio.I18N.Buttons) Signavio.I18N.Buttons = {}; +Signavio.I18N.Buttons.save = "Save"; +Signavio.I18N.Buttons.cancel = "Cancel"; +Signavio.I18N.Buttons.remove = "Remove"; -if(!Signavio.I18N.btn) {Signavio.I18N.btn = {};} +if (!Signavio.I18N.btn) { + Signavio.I18N.btn = {}; +} Signavio.I18N.btn.btnEdit = "Edit"; Signavio.I18N.btn.btnRemove = "Remove"; Signavio.I18N.btn.moveUp = "Move up"; Signavio.I18N.btn.moveDown = "Move down"; -if(!Signavio.I18N.field) {Signavio.I18N.field = {};} +if (!Signavio.I18N.field) { + Signavio.I18N.field = {}; +} Signavio.I18N.field.Url = "URL"; Signavio.I18N.field.UrlLabel = "Label"; diff --git a/pear-modules/pear-process/src/main/resources/static/editor-app/editor/oryx.debug.js b/pear-modules/pear-process/src/main/resources/static/editor-app/editor/oryx.debug.js index 45aaac1e585072633979bd103d2d7970aedd5b85..fb08975c8795cee1786a58871d7613447a565866 100644 --- a/pear-modules/pear-process/src/main/resources/static/editor-app/editor/oryx.debug.js +++ b/pear-modules/pear-process/src/main/resources/static/editor-app/editor/oryx.debug.js @@ -1,47 +1,48 @@ /** * @namespace Oryx name space for different utility methods * @name ORYX.Utils -*/ + */ -if(!ORYX) var ORYX = {}; +if (!ORYX) var ORYX = {}; ORYX.Utils = { /** * General helper method for parsing a param out of current location url * @example * // Current url in Browser => "http://oryx.org?param=value" - * ORYX.Utils.getParamFromUrl("param") // => "value" + * ORYX.Utils.getParamFromUrl("param") // => "value" * @param {Object} name */ - getParamFromUrl: function(name){ + getParamFromUrl: function (name) { name = name.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]"); var regexS = "[\\?&]" + name + "=([^&#]*)"; var regex = new RegExp(regexS); var results = regex.exec(window.location.href); if (results == null) { return null; - } - else { + } else { return results[1]; } }, - - adjustLightness: function(){ - return arguments[0]; - }, - - adjustGradient: function(gradient, reference){ - - if (ORYX.CONFIG.DISABLE_GRADIENT && gradient){ - - var col = reference.getAttributeNS(null, "stop-color") || "#ffffff"; - - $A(gradient.getElementsByTagName("stop")).each(function(stop){ - if (stop == reference){ return; } - stop.setAttributeNS(null, "stop-color", col); - }); - } - } + + adjustLightness: function () { + return arguments[0]; + }, + + adjustGradient: function (gradient, reference) { + + if (ORYX.CONFIG.DISABLE_GRADIENT && gradient) { + + var col = reference.getAttributeNS(null, "stop-color") || "#ffffff"; + + $A(gradient.getElementsByTagName("stop")).each(function (stop) { + if (stop == reference) { + return; + } + stop.setAttributeNS(null, "stop-color", col); + }); + } + } } /* * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. @@ -54,77 +55,79 @@ ORYX.Utils = { */ 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: "" + 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: "" }; //TODO kann kickstart sich vielleicht auch um die erzeugung von paketen/ // namespaces k???mmern? z.b. requireNamespace("ORYX.Core.SVG"); var Kickstart = { - started: false, - callbacks: [], - alreadyLoaded: [], - PATH: '', - - load: function() { Kickstart.kick(); }, - - kick: function() { - //console.profile("loading"); - if(!Kickstart.started) { - Kickstart.started = true; - Kickstart.callbacks.each(function(callback){ - // call the registered callback asynchronously. - window.setTimeout(callback, 1); - }); - } - }, + started: false, + callbacks: [], + alreadyLoaded: [], + PATH: '', - register: function(callback) { - //TODO Add some mutual exclusion between kick and register calls. - with(Kickstart) { - if(started) window.setTimeout(callback, 1); - else Kickstart.callbacks.push(callback) - } - }, + load: function () { + Kickstart.kick(); + }, - /** - * Loads a js, assuring that it has only been downloaded once. - * @param {String} url the script to load. - */ - require: function(url) { - // if not already loaded, include it. - if(Kickstart.alreadyLoaded.member(url)) - return false; - return Kickstart.include(url); - }, + kick: function () { + //console.profile("loading"); + if (!Kickstart.started) { + Kickstart.started = true; + Kickstart.callbacks.each(function (callback) { + // call the registered callback asynchronously. + window.setTimeout(callback, 1); + }); + } + }, - /** - * Loads a js, regardless of whether it has only been already downloaded. - * @param {String} url the script to load. - */ - include: function(url) { + register: function (callback) { + //TODO Add some mutual exclusion between kick and register calls. + with (Kickstart) { + if (started) window.setTimeout(callback, 1); + else Kickstart.callbacks.push(callback) + } + }, - // prepare a script tag and place it in html head. - var head = document.getElementsByTagNameNS(XMLNS.XHTML, 'head')[0]; - var s = document.createElementNS(XMLNS.XHTML, "script"); - s.setAttributeNS(XMLNS.XHTML, 'type', 'text/javascript'); - s.src = Kickstart.PATH + url; + /** + * Loads a js, assuring that it has only been downloaded once. + * @param {String} url the script to load. + */ + require: function (url) { + // if not already loaded, include it. + if (Kickstart.alreadyLoaded.member(url)) + return false; + return Kickstart.include(url); + }, + + /** + * Loads a js, regardless of whether it has only been already downloaded. + * @param {String} url the script to load. + */ + include: function (url) { - //TODO macht es sinn, dass neue skript als letztes kind in den head - // einzubinden (stichwort reihenfolge der skript tags)? - head.appendChild(s); + // prepare a script tag and place it in html head. + var head = document.getElementsByTagNameNS(XMLNS.XHTML, 'head')[0]; + var s = document.createElementNS(XMLNS.XHTML, "script"); + s.setAttributeNS(XMLNS.XHTML, 'type', 'text/javascript'); + s.src = Kickstart.PATH + url; - // remember this url. - Kickstart.alreadyLoaded.push(url); + //TODO macht es sinn, dass neue skript als letztes kind in den head + // einzubinden (stichwort reihenfolge der skript tags)? + head.appendChild(s); - return true; - } + // remember this url. + Kickstart.alreadyLoaded.push(url); + + return true; + } } // register kickstart as the new onload event listener on current window. @@ -141,387 +144,395 @@ Event.observe(window, 'load', Kickstart.load);/* var ERDF = { - LITERAL: 0x01, - RESOURCE: 0x02, - DELIMITERS: ['.', '-'], - HASH: '#', - HYPHEN: "-", - - schemas: [], - callback: undefined, - log: undefined, - - init: function(callback) { - - // init logging. - //ERDF.log = Log4js.getLogger("oryx"); - //ERDF.log.setLevel(Log4js.Level.ALL); - //ERDF.log.addAppender(new ConsoleAppender(ERDF.log, false)); - - //if(ERDF.log.isTraceEnabled()) - // ERDF.log.trace("ERDF Parser is initialized."); - - // register callbacks and default schemas. - ERDF.callback = callback; - ERDF.registerSchema('schema', XMLNS.SCHEMA); - ERDF.registerSchema('rdfs', XMLNS.RDFS); - }, + LITERAL: 0x01, + RESOURCE: 0x02, + DELIMITERS: ['.', '-'], + HASH: '#', + HYPHEN: "-", - run: function() { + schemas: [], + callback: undefined, + log: undefined, - //if(ERDF.log.isTraceEnabled()) - // ERDF.log.trace("ERDF Parser is running."); + init: function (callback) { - // do the work. - return ERDF._checkProfile() && ERDF.parse(); - }, - - parse: function() { - - //(ERDF.log.isDebugEnabled()) - // ERDF.log.debug("Begin parsing document metadata."); - - // time measuring - ERDF.__startTime = new Date(); - - var bodies = document.getElementsByTagNameNS(XMLNS.XHTML, 'body'); - var subject = {type: ERDF.RESOURCE, value: ''}; - - var result = ERDF._parseDocumentMetadata() && - ERDF._parseFromTag(bodies[0], subject); - - // time measuring - ERDF.__stopTime = new Date(); - - var duration = (ERDF.__stopTime - ERDF.__startTime)/1000.; - //alert('ERDF parsing took ' + duration + ' s.'); - - return result; - }, - - _parseDocumentMetadata: function() { - - // get links from head element. - var heads = document.getElementsByTagNameNS(XMLNS.XHTML, 'head'); - var links = heads[0].getElementsByTagNameNS(XMLNS.XHTML, 'link'); - var metas = heads[0].getElementsByTagNameNS(XMLNS.XHTML, 'meta'); - - // process links first, since they could contain schema definitions. - $A(links).each(function(link) { - var properties = link.getAttribute('rel'); - var reversedProperties = link.getAttribute('rev'); - var value = link.getAttribute('href'); - - ERDF._parseTriplesFrom( - ERDF.RESOURCE, '', - properties, - ERDF.RESOURCE, value); - - ERDF._parseTriplesFrom( - ERDF.RESOURCE, value, - reversedProperties, - ERDF.RESOURCE, ''); - }); + // init logging. + //ERDF.log = Log4js.getLogger("oryx"); + //ERDF.log.setLevel(Log4js.Level.ALL); + //ERDF.log.addAppender(new ConsoleAppender(ERDF.log, false)); - // continue with metas. - $A(metas).each(function(meta) { - var property = meta.getAttribute('name'); - var value = meta.getAttribute('content'); - - ERDF._parseTriplesFrom( - ERDF.RESOURCE, '', - property, - ERDF.LITERAL, value); - }); + //if(ERDF.log.isTraceEnabled()) + // ERDF.log.trace("ERDF Parser is initialized."); - return true; - }, - - _parseFromTag: function(node, subject, depth) { - - // avoid parsing non-xhtml content. - if(!node || !node.namespaceURI || node.namespaceURI != XMLNS.XHTML) { return; } - - // housekeeping. - if(!depth) depth=0; - var id = node.getAttribute('id'); - - // some logging. - //if(ERDF.log.isTraceEnabled()) - // ERDF.log.trace(">".times(depth) + " Parsing " + node.nodeName + " ("+node.nodeType+") for data on " + - // ((subject.type == ERDF.RESOURCE) ? ('<' + subject.value + '>') : '') + - // ((subject.type == ERDF.LITERAL) ? '"' + subject.value + '"' : '')); - - /* triple finding! */ - - // in a-tags... - if(node.nodeName.endsWith(':a') || node.nodeName == 'a') { - var properties = node.getAttribute('rel'); - var reversedProperties = node.getAttribute('rev'); - var value = node.getAttribute('href'); - var title = node.getAttribute('title'); - var content = node.textContent; - - // rel triples - ERDF._parseTriplesFrom( - subject.type, subject.value, - properties, - ERDF.RESOURCE, value, - function(triple) { - var label = title? title : content; - - // label triples - ERDF._parseTriplesFrom( - triple.object.type, triple.object.value, - 'rdfs.label', - ERDF.LITERAL, label); - }); + // register callbacks and default schemas. + ERDF.callback = callback; + ERDF.registerSchema('schema', XMLNS.SCHEMA); + ERDF.registerSchema('rdfs', XMLNS.RDFS); + }, - // rev triples - ERDF._parseTriplesFrom( - subject.type, subject.value, - reversedProperties, - ERDF.RESOURCE, ''); - - // type triples - ERDF._parseTypeTriplesFrom( - subject.type, subject.value, - properties); - - // in img-tags... - } else if(node.nodeName.endsWith(':img') || node.nodeName == 'img') { - var properties = node.getAttribute('class'); - var value = node.getAttribute('src'); - var alt = node.getAttribute('alt'); - - ERDF._parseTriplesFrom( - subject.type, subject.value, - properties, - ERDF.RESOURCE, value, - function(triple) { - var label = alt; - - // label triples - ERDF._parseTriplesFrom( - triple.object.type, triple.object.value, - 'rdfs.label', - ERDF.LITERAL, label); - }); + run: function () { - } - - // in every tag - var properties = node.getAttribute('class'); - var title = node.getAttribute('title'); - var content = node.textContent; - var label = title ? title : content; - - // regular triples - ERDF._parseTriplesFrom( - subject.type, subject.value, - properties, - ERDF.LITERAL, label); - - if(id) subject = {type: ERDF.RESOURCE, value: ERDF.HASH+id}; - - // type triples - ERDF._parseTypeTriplesFrom( - subject.type, subject.value, - properties); - - // parse all children that are element nodes. - var children = node.childNodes; - if(children) $A(children).each(function(_node) { - if(_node.nodeType == _node.ELEMENT_NODE) - ERDF._parseFromTag(_node, subject, depth+1); }); - }, - - _parseTriplesFrom: function(subjectType, subject, properties, - objectType, object, callback) { - - if(!properties) return; - properties.toLowerCase().split(' ').each( function(property) { - - //if(ERDF.log.isTraceEnabled()) - // ERDF.log.trace("Going for property " + property); - - var schema = ERDF.schemas.find( function(schema) { - return false || ERDF.DELIMITERS.find( function(delimiter) { - return property.startsWith(schema.prefix + delimiter); - }); - }); - - if(schema && object) { - property = property.substring( - schema.prefix.length+1, property.length); - var triple = ERDF.registerTriple( - new ERDF.Resource(subject), - {prefix: schema.prefix, name: property}, - (objectType == ERDF.RESOURCE) ? - new ERDF.Resource(object) : - new ERDF.Literal(object)); - - if(callback) callback(triple); - } - }); - }, - - _parseTypeTriplesFrom: function(subjectType, subject, properties, callback) { - - if(!properties) return; - properties.toLowerCase().split(' ').each( function(property) { - - //if(ERDF.log.isTraceEnabled()) - // ERDF.log.trace("Going for property " + property); - - var schema = ERDF.schemas.find( function(schema) { - return false || ERDF.DELIMITERS.find( function(delimiter) { - return property.startsWith(ERDF.HYPHEN + schema.prefix + delimiter); - }); - }); - - if(schema && subject) { - property = property.substring(schema.prefix.length+2, property.length); - var triple = ERDF.registerTriple( - (subjectType == ERDF.RESOURCE) ? - new ERDF.Resource(subject) : - new ERDF.Literal(subject), - {prefix: 'rdf', name: 'type'}, - new ERDF.Resource(schema.namespace+property)); - if(callback) callback(triple); - } - }); - }, - - /** - * Checks for ERDF profile declaration in head of document. - */ - _checkProfile: function() { + //if(ERDF.log.isTraceEnabled()) + // ERDF.log.trace("ERDF Parser is running."); - // get profiles from head element. - var heads = document.getElementsByTagNameNS(XMLNS.XHTML, 'head'); - var profiles = heads[0].getAttribute("profile"); - var found = false; + // do the work. + return ERDF._checkProfile() && ERDF.parse(); + }, - // if erdf profile is contained. - if(profiles && profiles.split(" ").member(XMLNS.ERDF)) { + parse: function () { - // pass check. - //if(ERDF.log.isTraceEnabled()) - // ERDF.log.trace("Found ERDF profile " + XMLNS.ERDF); - return true; - - } else { - - // otherwise fail check. - //if(ERDF.log.isFatalEnabled()) - // ERDF.log.fatal("No ERDF profile found."); - return false; - } - }, - - __stripHashes: function(s) { - return (s && (typeof s.substring == 'function') && s.substring(0, 1)=='#') ? s.substring(1, s.length) : s; - }, - - registerSchema: function(prefix, namespace) { - - // TODO check whether already registered, if so, complain. - ERDF.schemas.push({ - prefix: prefix, - namespace: namespace - }); - - //if(ERDF.log.isDebugEnabled()) - // ERDF.log.debug("Prefix '"+prefix+"' for '"+namespace+"' registered."); - }, - - registerTriple: function(subject, predicate, object) { - - // if prefix is schema, this is a schema definition. - if(predicate.prefix.toLowerCase() == 'schema') - this.registerSchema(predicate.name, object.value); - - var triple = new ERDF.Triple(subject, predicate, object); - ERDF.callback(triple); - - //if(ERDF.log.isInfoEnabled()) - // ERDF.log.info(triple) - - // return the registered triple. - return triple; - }, - - __enhanceObject: function() { - - /* Resource state querying methods */ - 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 == '') }; - - /* Resource getter methods.*/ - this.getId = function() { - return this.isLocal() ? ERDF.__stripHashes(this.value) : false; }; - - /* Liiteral state querying methods */ - this.isLiteral = function() { - return this.type == ERDF.LIITERAL }; - }, - - serialize: function(literal) { - - if(!literal){ - return ""; - }else if(literal.constructor == String) { - return literal; - } else if(literal.constructor == Boolean) { - return literal? 'true':'false'; - } else { - return literal.toString(); - } - } + //(ERDF.log.isDebugEnabled()) + // ERDF.log.debug("Begin parsing document metadata."); + + // time measuring + ERDF.__startTime = new Date(); + + var bodies = document.getElementsByTagNameNS(XMLNS.XHTML, 'body'); + var subject = {type: ERDF.RESOURCE, value: ''}; + + var result = ERDF._parseDocumentMetadata() && + ERDF._parseFromTag(bodies[0], subject); + + // time measuring + ERDF.__stopTime = new Date(); + + var duration = (ERDF.__stopTime - ERDF.__startTime) / 1000.; + //alert('ERDF parsing took ' + duration + ' s.'); + + return result; + }, + + _parseDocumentMetadata: function () { + + // get links from head element. + var heads = document.getElementsByTagNameNS(XMLNS.XHTML, 'head'); + var links = heads[0].getElementsByTagNameNS(XMLNS.XHTML, 'link'); + var metas = heads[0].getElementsByTagNameNS(XMLNS.XHTML, 'meta'); + + // process links first, since they could contain schema definitions. + $A(links).each(function (link) { + var properties = link.getAttribute('rel'); + var reversedProperties = link.getAttribute('rev'); + var value = link.getAttribute('href'); + + ERDF._parseTriplesFrom( + ERDF.RESOURCE, '', + properties, + ERDF.RESOURCE, value); + + ERDF._parseTriplesFrom( + ERDF.RESOURCE, value, + reversedProperties, + ERDF.RESOURCE, ''); + }); + + // continue with metas. + $A(metas).each(function (meta) { + var property = meta.getAttribute('name'); + var value = meta.getAttribute('content'); + + ERDF._parseTriplesFrom( + ERDF.RESOURCE, '', + property, + ERDF.LITERAL, value); + }); + + return true; + }, + + _parseFromTag: function (node, subject, depth) { + + // avoid parsing non-xhtml content. + if (!node || !node.namespaceURI || node.namespaceURI != XMLNS.XHTML) { + return; + } + + // housekeeping. + if (!depth) depth = 0; + var id = node.getAttribute('id'); + + // some logging. + //if(ERDF.log.isTraceEnabled()) + // ERDF.log.trace(">".times(depth) + " Parsing " + node.nodeName + " ("+node.nodeType+") for data on " + + // ((subject.type == ERDF.RESOURCE) ? ('<' + subject.value + '>') : '') + + // ((subject.type == ERDF.LITERAL) ? '"' + subject.value + '"' : '')); + + /* triple finding! */ + + // in a-tags... + if (node.nodeName.endsWith(':a') || node.nodeName == 'a') { + var properties = node.getAttribute('rel'); + var reversedProperties = node.getAttribute('rev'); + var value = node.getAttribute('href'); + var title = node.getAttribute('title'); + var content = node.textContent; + + // rel triples + ERDF._parseTriplesFrom( + subject.type, subject.value, + properties, + ERDF.RESOURCE, value, + function (triple) { + var label = title ? title : content; + + // label triples + ERDF._parseTriplesFrom( + triple.object.type, triple.object.value, + 'rdfs.label', + ERDF.LITERAL, label); + }); + + // rev triples + ERDF._parseTriplesFrom( + subject.type, subject.value, + reversedProperties, + ERDF.RESOURCE, ''); + + // type triples + ERDF._parseTypeTriplesFrom( + subject.type, subject.value, + properties); + + // in img-tags... + } else if (node.nodeName.endsWith(':img') || node.nodeName == 'img') { + var properties = node.getAttribute('class'); + var value = node.getAttribute('src'); + var alt = node.getAttribute('alt'); + + ERDF._parseTriplesFrom( + subject.type, subject.value, + properties, + ERDF.RESOURCE, value, + function (triple) { + var label = alt; + + // label triples + ERDF._parseTriplesFrom( + triple.object.type, triple.object.value, + 'rdfs.label', + ERDF.LITERAL, label); + }); + + } + + // in every tag + var properties = node.getAttribute('class'); + var title = node.getAttribute('title'); + var content = node.textContent; + var label = title ? title : content; + + // regular triples + ERDF._parseTriplesFrom( + subject.type, subject.value, + properties, + ERDF.LITERAL, label); + + if (id) subject = {type: ERDF.RESOURCE, value: ERDF.HASH + id}; + + // type triples + ERDF._parseTypeTriplesFrom( + subject.type, subject.value, + properties); + + // parse all children that are element nodes. + var children = node.childNodes; + if (children) $A(children).each(function (_node) { + if (_node.nodeType == _node.ELEMENT_NODE) + ERDF._parseFromTag(_node, subject, depth + 1); + }); + }, + + _parseTriplesFrom: function (subjectType, subject, properties, + objectType, object, callback) { + + if (!properties) return; + properties.toLowerCase().split(' ').each(function (property) { + + //if(ERDF.log.isTraceEnabled()) + // ERDF.log.trace("Going for property " + property); + + var schema = ERDF.schemas.find(function (schema) { + return false || ERDF.DELIMITERS.find(function (delimiter) { + return property.startsWith(schema.prefix + delimiter); + }); + }); + + if (schema && object) { + property = property.substring( + schema.prefix.length + 1, property.length); + var triple = ERDF.registerTriple( + new ERDF.Resource(subject), + {prefix: schema.prefix, name: property}, + (objectType == ERDF.RESOURCE) ? + new ERDF.Resource(object) : + new ERDF.Literal(object)); + + if (callback) callback(triple); + } + }); + }, + + _parseTypeTriplesFrom: function (subjectType, subject, properties, callback) { + + if (!properties) return; + properties.toLowerCase().split(' ').each(function (property) { + + //if(ERDF.log.isTraceEnabled()) + // ERDF.log.trace("Going for property " + property); + + var schema = ERDF.schemas.find(function (schema) { + return false || ERDF.DELIMITERS.find(function (delimiter) { + return property.startsWith(ERDF.HYPHEN + schema.prefix + delimiter); + }); + }); + + if (schema && subject) { + property = property.substring(schema.prefix.length + 2, property.length); + var triple = ERDF.registerTriple( + (subjectType == ERDF.RESOURCE) ? + new ERDF.Resource(subject) : + new ERDF.Literal(subject), + {prefix: 'rdf', name: 'type'}, + new ERDF.Resource(schema.namespace + property)); + if (callback) callback(triple); + } + }); + }, + + /** + * Checks for ERDF profile declaration in head of document. + */ + _checkProfile: function () { + + // get profiles from head element. + var heads = document.getElementsByTagNameNS(XMLNS.XHTML, 'head'); + var profiles = heads[0].getAttribute("profile"); + var found = false; + + // if erdf profile is contained. + if (profiles && profiles.split(" ").member(XMLNS.ERDF)) { + + // pass check. + //if(ERDF.log.isTraceEnabled()) + // ERDF.log.trace("Found ERDF profile " + XMLNS.ERDF); + return true; + + } else { + + // otherwise fail check. + //if(ERDF.log.isFatalEnabled()) + // ERDF.log.fatal("No ERDF profile found."); + return false; + } + }, + + __stripHashes: function (s) { + return (s && (typeof s.substring == 'function') && s.substring(0, 1) == '#') ? s.substring(1, s.length) : s; + }, + + registerSchema: function (prefix, namespace) { + + // TODO check whether already registered, if so, complain. + ERDF.schemas.push({ + prefix: prefix, + namespace: namespace + }); + + //if(ERDF.log.isDebugEnabled()) + // ERDF.log.debug("Prefix '"+prefix+"' for '"+namespace+"' registered."); + }, + + registerTriple: function (subject, predicate, object) { + + // if prefix is schema, this is a schema definition. + if (predicate.prefix.toLowerCase() == 'schema') + this.registerSchema(predicate.name, object.value); + + var triple = new ERDF.Triple(subject, predicate, object); + ERDF.callback(triple); + + //if(ERDF.log.isInfoEnabled()) + // ERDF.log.info(triple) + + // return the registered triple. + return triple; + }, + + __enhanceObject: function () { + + /* Resource state querying methods */ + 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 == '') + }; + + /* Resource getter methods.*/ + this.getId = function () { + return this.isLocal() ? ERDF.__stripHashes(this.value) : false; + }; + + /* Liiteral state querying methods */ + this.isLiteral = function () { + return this.type == ERDF.LIITERAL + }; + }, + + serialize: function (literal) { + + if (!literal) { + return ""; + } else if (literal.constructor == String) { + return literal; + } else if (literal.constructor == Boolean) { + return literal ? 'true' : 'false'; + } else { + return literal.toString(); + } + } }; -ERDF.Triple = function(subject, predicate, object) { - - this.subject = subject; - this.predicate = predicate; - this.object = object; - - this.toString = function() { - - return "[ERDF.Triple] " + - this.subject.toString() + ' ' + - this.predicate.prefix + ':' + this.predicate.name + ' ' + - this.object.toString(); - }; +ERDF.Triple = function (subject, predicate, object) { + + this.subject = subject; + this.predicate = predicate; + this.object = object; + + this.toString = function () { + + return "[ERDF.Triple] " + + this.subject.toString() + ' ' + + this.predicate.prefix + ':' + this.predicate.name + ' ' + + this.object.toString(); + }; }; -ERDF.Resource = function(uri) { - - this.type = ERDF.RESOURCE; - this.value = uri; - ERDF.__enhanceObject.apply(this); - - this.toString = function() { - return '<' + this.value + '>'; - } - +ERDF.Resource = function (uri) { + + this.type = ERDF.RESOURCE; + this.value = uri; + ERDF.__enhanceObject.apply(this); + + this.toString = function () { + return '<' + this.value + '>'; + } + }; -ERDF.Literal = function(literal) { - - this.type = ERDF.LITERAL; - this.value = ERDF.serialize(literal); - ERDF.__enhanceObject.apply(this); +ERDF.Literal = function (literal) { + + this.type = ERDF.LITERAL; + this.value = ERDF.serialize(literal); + ERDF.__enhanceObject.apply(this); - this.toString = function() { - return '"' + this.value + '"'; - } + this.toString = function () { + return '"' + this.value + '"'; + } };/* * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. * License rights for this program may be obtained from Alfresco Software, Ltd. @@ -536,20 +547,20 @@ ERDF.Literal = function(literal) { * Save and triple generation behaviour. Use this area to configure * data management to your needs. */ -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 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 SHOW_DEBUG_ALERTS_WHEN_SAVING = false; +var SHOW_EXTENDED_DEBUG_INFORMATION = false; /* * Back end specific workarounds. */ -var USE_ARESS_WORKAROUNDS = true; +var USE_ARESS_WORKAROUNDS = true; /* * Data management constants. Do not change these, as they are used @@ -558,17 +569,17 @@ var USE_ARESS_WORKAROUNDS = true; */ // Resource constants -var RESOURCE_CREATED = 0x01; -var RESOURCE_REMOVED = 0x02; -var RESOURCE_SAVED = 0x04; -var RESOURCE_RELOADED = 0x08; -var RESOURCE_SYNCHRONIZED = 0x10; +var RESOURCE_CREATED = 0x01; +var RESOURCE_REMOVED = 0x02; +var RESOURCE_SAVED = 0x04; +var RESOURCE_RELOADED = 0x08; +var RESOURCE_SYNCHRONIZED = 0x10; // Triple constants -var TRIPLE_REMOVE = 0x01; -var TRIPLE_ADD = 0x02; -var TRIPLE_RELOAD = 0x04; -var TRIPLE_SAVE = 0x08; +var TRIPLE_REMOVE = 0x01; +var TRIPLE_ADD = 0x02; +var TRIPLE_RELOAD = 0x04; +var TRIPLE_SAVE = 0x08; var PROCESSDATA_REF = 'processdata'; @@ -604,2940 +615,1145 @@ var PROCESSDATA_REF = 'processdata'; * @class DataManager */ var DataManager = { - - /** - * The init method should be called once in the DataManagers lifetime. - * It causes the DataManager to initialize itself, the erdf parser, do all - * neccessary registrations and configurations, to run the parser and - * from then on deliver all resulting triples. - * No parameters needed are needed in a call to this method. - */ - init: function() { - ERDF.init(DataManager._registerTriple); - DataManager.__synclocal(); - }, - - /** - * This triple array is meant to be the whole knowledge of the DataManager. - */ - _triples: [], - - /** - * This method is meant for callback from erdf parsing. It is not to be - * used in another way than to add triples to the triple store. - * @param {Object} triple the triple to add to the triple store. - */ - _registerTriple: function(triple) { - DataManager._triples.push(triple) - }, - - /** - * The __synclocal method is for internal usage only. - * It performs synchronization with the local document, that is, the triple - * store is adjustet to the content of the document, which could have been - * changed by any other applications running on the same page. - */ - __synclocal: function() { - DataManager._triples = []; - ERDF.run(); - }, - - /** - * Makes the shape passed into this method synchronize itself with the DOM. - * This method returns the shapes resource object for further manipulation. - * @param {Object} shape - */ - __synchronizeShape: function(shape) { - - var r = ResourceManager.getResource(shape.resourceId); - var serialize = shape.serialize(); - - // store all serialize values - serialize.each( function(ser) { - - var resource = (ser.type == 'resource'); - var _triple = new ERDF.Triple( - new ERDF.Resource(shape.resourceId), - {prefix: ser.prefix, name: ser.name}, - resource ? - new ERDF.Resource(ser.value) : - new ERDF.Literal(ser.value) - ); - DataManager.setObject(_triple); - }); - - return r; - }, - __storeShape: function(shape) { - - // first synchronize the shape, - var resource = DataManager.__synchronizeShape(shape); - - // then save the synchronized dom. - resource.save(); - }, - - __forceExistance: function(shape) { - - if(!$(shape.resourceId)) { - - if(!$$('.' + PROCESSDATA_REF)[0]) - DataManager.graft(XMLNS.XHTML, - document.getElementsByTagNameNS(XMLNS.XHTML, 'body').item(0), ['div', {'class': PROCESSDATA_REF, 'style':'display:none;'}]); - - // object is literal - DataManager.graft(XMLNS.XHTML, - $$('.' + PROCESSDATA_REF)[0], [ - - 'div', { - 'id': shape.resourceId, - //This should be done in a more dynamic way!!!!! - 'class': (shape instanceof ORYX.Core.Canvas) ? "-oryx-canvas" : undefined - } - ]); - - } else { - var resource = $(shape.resourceId) - var children = $A(resource.childNodes) - children.each( function(child) { - resource.removeChild(child); - }); - }; - }, - - __persistShape: function(shape) { - - // a shape serialization. - var shapeData = shape.serialize(); - - // initialize a triple array and construct a shape resource - // to be used in triple generation. - var triplesArray = []; - var shapeResource = new ERDF.Resource(shape.resourceId); - - // remove all triples for this particular shape's resource - DataManager.removeTriples( DataManager.query( - shapeResource, undefined, undefined)); - - // for each data set in the shape's serialization - shapeData.each( function(data) { - - // construct a triple's value - var value = (data.type == 'resource') ? - new ERDF.Resource(data.value) : - new ERDF.Literal(data.value); - - // construct triple and add it to the DOM. - DataManager.addTriple( new ERDF.Triple( - shapeResource, - {prefix: data.prefix, name: data.name}, - value - )); - }); - }, - - __persistDOM: function(facade) { - - // getChildShapes gets all shapes (nodes AND edges), deep flag - // makes it return a flattened child hierarchy. - - var canvas = facade.getCanvas(); - var shapes = canvas.getChildShapes(true); - var result = ''; - - // persist all shapes. - shapes.each( function(shape) { - DataManager.__forceExistance(shape); - }); - //DataManager.__synclocal(); - - DataManager.__renderCanvas(facade); - result += DataManager.serialize( - $(ERDF.__stripHashes(facade.getCanvas().resourceId)), true); - - shapes.each( function(shape) { - - DataManager.__persistShape(shape); - result += DataManager.serialize( - $(ERDF.__stripHashes(shape.resourceId)), true); - }); - - //result += DataManager.__renderCanvas(facade); - - return result; - }, + /** + * The init method should be called once in the DataManagers lifetime. + * It causes the DataManager to initialize itself, the erdf parser, do all + * neccessary registrations and configurations, to run the parser and + * from then on deliver all resulting triples. + * No parameters needed are needed in a call to this method. + */ + init: function () { + ERDF.init(DataManager._registerTriple); + DataManager.__synclocal(); + }, - __renderCanvas: function(facade) { - - var canvas = facade.getCanvas(); - var stencilSets = facade.getStencilSets(); - var shapes = canvas.getChildShapes(true); - - DataManager.__forceExistance(canvas); - - DataManager.__persistShape(canvas); - - var shapeResource = new ERDF.Resource(canvas.resourceId); - - // remove all triples for this particular shape's resource - DataManager.removeTriples( DataManager.query( - shapeResource, undefined, undefined)); - - DataManager.addTriple( new ERDF.Triple( - shapeResource, - {prefix: "oryx", name: "mode"}, - new ERDF.Literal("writable") - )); - - DataManager.addTriple( new ERDF.Triple( - shapeResource, - {prefix: "oryx", name: "mode"}, - new ERDF.Literal("fullscreen") - )); - - stencilSets.values().each(function(stencilset) { - DataManager.addTriple( new ERDF.Triple( - shapeResource, - {prefix: "oryx", name: "stencilset"}, - new ERDF.Resource(stencilset.source().replace(/&/g, "%26")) - )); - - DataManager.addTriple( new ERDF.Triple( - shapeResource, - {prefix: "oryx", name: "ssnamespace"}, - new ERDF.Resource(stencilset.namespace()) - )); - - stencilset.extensions().keys().each(function(extension) { - DataManager.addTriple( new ERDF.Triple( - shapeResource, - {prefix: "oryx", name: "ssextension"}, - new ERDF.Literal(extension) - )); - }); - }); - - shapes.each(function(shape) { - DataManager.addTriple( new ERDF.Triple( - shapeResource, - {prefix: "oryx", name: "render"}, - new ERDF.Resource("#" + shape.resourceId) - )); - }); - }, + /** + * This triple array is meant to be the whole knowledge of the DataManager. + */ + _triples: [], - __counter: 0, - __provideId: function() { - - while($(RESOURCE_ID_PREFIX+DataManager.__counter)) - DataManager.__counter++; - - return RESOURCE_ID_PREFIX+DataManager.__counter; - }, - - serializeDOM: function(facade) { - - return DataManager.__persistDOM(facade); - }, - - syncGlobal: function(facade) { - - return DataManager.__syncglobal(facade); - }, - - /** - * This method is used to synchronize local DOM with remote resources. - * Local changes are commited to the server, and remote changes are - * performed to the local document. - * @param {Object} facade The facade of the editor that holds certain - * resource representations as shapes. - */ - __syncglobal: function(facade) { + /** + * This method is meant for callback from erdf parsing. It is not to be + * used in another way than to add triples to the triple store. + * @param {Object} triple the triple to add to the triple store. + */ + _registerTriple: function (triple) { + DataManager._triples.push(triple) + }, - // getChildShapes gets all shapes (nodes AND edges), deep flag - // makes it return a flattened child hierarchy. - - var canvas = facade.getCanvas(); - var shapes = canvas.getChildShapes(true); + /** + * The __synclocal method is for internal usage only. + * It performs synchronization with the local document, that is, the triple + * store is adjustet to the content of the document, which could have been + * changed by any other applications running on the same page. + */ + __synclocal: function () { + DataManager._triples = []; + ERDF.run(); + }, - // create dummy resource representations in the dom - // for all shapes that were newly created. + /** + * Makes the shape passed into this method synchronize itself with the DOM. + * This method returns the shapes resource object for further manipulation. + * @param {Object} shape + */ + __synchronizeShape: function (shape) { + + var r = ResourceManager.getResource(shape.resourceId); + var serialize = shape.serialize(); + + // store all serialize values + serialize.each(function (ser) { + + var resource = (ser.type == 'resource'); + var _triple = new ERDF.Triple( + new ERDF.Resource(shape.resourceId), + {prefix: ser.prefix, name: ser.name}, + resource ? + new ERDF.Resource(ser.value) : + new ERDF.Literal(ser.value) + ); + DataManager.setObject(_triple); + }); - shapes.select( function(shape) { + return r; + }, - // select shapes without resource id. + __storeShape: function (shape) { - return !($(shape.resourceId)); + // first synchronize the shape, + var resource = DataManager.__synchronizeShape(shape); - }).each( function(shape) { + // then save the synchronized dom. + resource.save(); + }, - // create new resources for them. - if(USE_ARESS_WORKAROUNDS) { - - /* - * This is a workaround due to a bug in aress. Resources are - * ignoring changes to raziel:type property once they are - * created. As long as this is not fixed, the resource is now - * being created using a randomly guessed id, this temporary id - * is then used in references and the appropriate div is being - * populated with properties. - * - * AFTER THIS PHASE THE DATA IS INCONSISTENT AS REFERENCES POINT - * TO IDS THAT ARE UNKNOWN TO THE BACK END. - * - * After the resource is actually created in aress, it gets an id - * that is persistent. All shapes are then being populated with the - * correct id references and stored on the server. - * - * AFTER THE SAVE PROCESS HAS RETURNED, THE DATA IS CONSISTENT - * REGARDING THE ID REFERENCES AGAIN. - */ - - var razielType = shape.properties['raziel-type']; - - var div = '
' + - ''+razielType+'
'; - - var r = ResourceManager.__createResource(div); - shape.resourceId = r.id(); - - } else { - - var r = ResourceManager.__createResource(); - shape.resourceId = r.id(); - } + __forceExistance: function (shape) { - }); + if (!$(shape.resourceId)) { - shapes.each( function(shape) { - - // store all shapes. - DataManager.__storeShape(shape); - }); - }, - - /** - * This method serializes a single div into a string that satisfies the - * client/server communication protocol. It ingnores all elements that have - * an attribute named class that includes 'transient'. - * @param {Object} node the element to serialize. - * @param {Object} preserveNamespace whether to preserve the parent's - * namespace. If you are not sure about namespaces, provide - * just the element to be serialized. - */ - serialize: function(node, preserveNamespace) { - - if (node.nodeType == node.ELEMENT_NODE) { - // serialize an element node. - - var children = $A(node.childNodes); - var attributes = $A(node.attributes); - var clazz = new String(node.getAttribute('class')); - var ignore = clazz.split(' ').member('transient'); - - // ignore transients. - - if(ignore) - return ''; - - // start serialization. - - var result = '<' + node.nodeName; - - // preserve namespace? - if(!preserveNamespace) - result += ' xmlns="' + (node.namespaceURI ? node.namespaceURI : XMLNS.XHTML) + '" xmlns:oryx="http://oryx-editor.org"'; - - // add all attributes. - - attributes.each(function(attribute) { - result += ' ' + attribute.nodeName + '="' + - attribute.nodeValue + '"';}); - - // close if no children. - - if(children.length == 0) - result += '/>'; - - else { - - // serialize all children. - - result += '>'; - children.each(function(_node) { - result += DataManager.serialize(_node, true)}); - result += '' - } + if (!$$('.' + PROCESSDATA_REF)[0]) + DataManager.graft(XMLNS.XHTML, + document.getElementsByTagNameNS(XMLNS.XHTML, 'body').item(0), ['div', { + 'class': PROCESSDATA_REF, + 'style': 'display:none;' + }]); - return result; - - } else if (node.nodeType == node.TEXT_NODE) { - - // serialize a text node. - return node.nodeValue; - } - - //TODO serialize cdata areas also. - //TODO work on namespace awareness. - }, + // object is literal + DataManager.graft(XMLNS.XHTML, + $$('.' + PROCESSDATA_REF)[0], [ - addTriple: function(triple) { - - // assert the subject is a resource - - if(!triple.subject.type == ERDF.LITERAL) - throw 'Cannot add the triple ' + triple.toString() + - ' because the subject is not a resource.' - - // get the element which represents this triple's subject. - var elementId = ERDF.__stripHashes(triple.subject.value); - var element = $(elementId); - - // assert the subject is inside this document. - if(!element) - throw 'Cannot add the triple ' + triple.toString() + - ' because the subject "'+elementId+'" is not in the document.'; - - if(triple.object.type == ERDF.LITERAL) - - // object is literal - DataManager.graft(XMLNS.XHTML, element, [ - 'span', {'class': (triple.predicate.prefix + "-" + - triple.predicate.name)}, triple.object.value.escapeHTML() - ]); - - else { - - // object is resource - DataManager.graft(XMLNS.XHTML, element, [ - 'a', {'rel': (triple.predicate.prefix + "-" + - triple.predicate.name), 'href': triple.object.value} - ]); - - } + 'div', { + 'id': shape.resourceId, + //This should be done in a more dynamic way!!!!! + 'class': (shape instanceof ORYX.Core.Canvas) ? "-oryx-canvas" : undefined + } + ]); - return true; - }, - - removeTriples: function(triples) { + } else { + var resource = $(shape.resourceId) + var children = $A(resource.childNodes) + children.each(function (child) { + resource.removeChild(child); + }); + } + ; + }, - // alert('Removing ' +triples.length+' triples.'); + __persistShape: function (shape) { - // from all the triples select those ... - var removed = triples.select( + // a shape serialization. + var shapeData = shape.serialize(); - function(triple) { - - // TODO remove also from triple store. - // ... that were actually removed. - return DataManager.__removeTriple(triple); - }); - - // sync and return removed triples. - // DataManager.__synclocal(); - return removed; - }, - - removeTriple: function(triple) { - - // remember whether the triple was actually removed. - var result = DataManager.__removeTriple(triple); - - // sync and return removed triples. - // DataManager.__synclocal(); - return result; - }, + // initialize a triple array and construct a shape resource + // to be used in triple generation. + var triplesArray = []; + var shapeResource = new ERDF.Resource(shape.resourceId); - __removeTriple: function(triple) { - - // assert the subject is a resource - if(!triple.subject.type == ERDF.LITERAL) - - throw 'Cannot remove the triple ' + triple.toString() + - ' because the subject is not a resource.'; - - // get the element which represents this triple's subject. - var elementId = ERDF.__stripHashes(triple.subject.value); - var element = $(elementId); - - // assert the subject is inside this document. - if(!element) - - throw 'Cannot remove the triple ' + triple.toString() + - ' because the subject is not in the document.'; - - if(triple.object.type == ERDF.LITERAL) { - - // continue searching actively for the triple. - var result = DataManager.__removeTripleRecursively(triple, element); - return result; - } - }, + // remove all triples for this particular shape's resource + DataManager.removeTriples(DataManager.query( + shapeResource, undefined, undefined)); - __removeTripleRecursively: function(triple, continueFrom) { - - // return when this node is not an element node. - if(continueFrom.nodeType != continueFrom.ELEMENT_NODE) - return false; - - var classes = new String(continueFrom.getAttribute('class')); - var children = $A(continueFrom.childNodes); - - if(classes.include(triple.predicate.prefix + '-' + triple.predicate.name)) { - - var content = continueFrom.textContent; - if( (triple.object.type == ERDF.LITERAL) && - (triple.object.value == content)) - - continueFrom.parentNode.removeChild(continueFrom); - - return true; - - } else { - - children.each(function(_node) { - DataManager.__removeTripleRecursively(triple, _node)}); - return false; - } + // for each data set in the shape's serialization + shapeData.each(function (data) { - }, + // construct a triple's value + var value = (data.type == 'resource') ? + new ERDF.Resource(data.value) : + new ERDF.Literal(data.value); - /** - * graft() function - * Originally by Sean M. Burke from interglacial.com, altered for usage with - * SVG and namespace (xmlns) support. Be sure you understand xmlns before - * using this funtion, as it creates all grafted elements in the xmlns - * provided by you and all element's attribures in default xmlns. If you - * need to graft elements in a certain xmlns and wish to assign attributes - * in both that and another xmlns, you will need to do stepwise grafting, - * adding non-default attributes yourself or you'll have to enhance this - * function. Latter, I would appreciate: martin???apfelfabrik.de - * @param {Object} namespace The namespace in which - * elements should be grafted. - * @param {Object} parent The element that should contain the grafted - * structure after the function returned. - * @param {Object} t the crafting structure. - * @param {Object} doc the document in which grafting is performed. - */ - graft: function(namespace, parent, t, doc) { - - doc = (doc || (parent && parent.ownerDocument) || document); - var e; - if(t === undefined) { - echo( "Can't graft an undefined value"); - } else if(t.constructor == String) { - e = doc.createTextNode( t ); - } else { - for(var i = 0; i < t.length; i++) { - if( i === 0 && t[i].constructor == String ) { - var snared = t[i].match( /^([a-z][a-z0-9]*)\.([^\s\.]+)$/i ); - if( snared ) { - e = doc.createElementNS(namespace, snared[1]); - e.setAttributeNS(null, 'class', snared[2] ); - continue; - } - snared = t[i].match( /^([a-z][a-z0-9]*)$/i ); - if( snared ) { - e = doc.createElementNS(namespace, snared[1]); // but no class - continue; - } - - // Otherwise: - e = doc.createElementNS(namespace, "span"); - e.setAttribute(null, "class", "namelessFromLOL" ); - } - - if( t[i] === undefined ) { - echo("Can't graft an undefined value in a list!"); - } else if( t[i].constructor == String || t[i].constructor == Array) { - this.graft(namespace, e, t[i], doc ); - } else if( t[i].constructor == Number ) { - this.graft(namespace, e, t[i].toString(), doc ); - } else if( t[i].constructor == Object ) { - // hash's properties => element's attributes - for(var k in t[i]) { e.setAttributeNS(null, k, t[i][k] ); } - } else if( t[i].constructor == Boolean ) { - this.graft(namespace, e, t[i] ? 'true' : 'false', doc ); - } else - throw "Object " + t[i] + " is inscrutable as an graft arglet."; - } - } - - if(parent) parent.appendChild(e); - - return Element.extend(e); // return the topmost created node - }, + // construct triple and add it to the DOM. + DataManager.addTriple(new ERDF.Triple( + shapeResource, + {prefix: data.prefix, name: data.name}, + value + )); + }); + }, - setObject: function(triple) { + __persistDOM: function (facade) { - /** - * Erwartungen von Arvid an diese Funktion: - * - Es existiert genau ein triple mit dem Subjekt und Praedikat, - * das uebergeben wurde, und dieses haelt uebergebenes Objekt. - */ + // getChildShapes gets all shapes (nodes AND edges), deep flag + // makes it return a flattened child hierarchy. - var triples = DataManager.query( - triple.subject, - triple.predicate, - undefined - ); - - DataManager.removeTriples(triples); + var canvas = facade.getCanvas(); + var shapes = canvas.getChildShapes(true); + var result = ''; - DataManager.addTriple(triple); + // persist all shapes. + shapes.each(function (shape) { + DataManager.__forceExistance(shape); + }); + //DataManager.__synclocal(); - return true; - }, - - query: function(subject, predicate, object) { + DataManager.__renderCanvas(facade); + result += DataManager.serialize( + $(ERDF.__stripHashes(facade.getCanvas().resourceId)), true); - /* - * Typical triple. - * {value: subject, type: subjectType}, - * {prefix: schema.prefix, name: property}, - * {value: object, type: objectType}); - */ - - return DataManager._triples.select(function(triple) { - - var select = ((subject) ? - (triple.subject.type == subject.type) && - (triple.subject.value == subject.value) : true); - if(predicate) { - select = select && ((predicate.prefix) ? - (triple.predicate.prefix == predicate.prefix) : true); - select = select && ((predicate.name) ? - (triple.predicate.name == predicate.name) : true); - } - select = select && ((object) ? - (triple.object.type == object.type) && - (triple.object.value == object.value) : true); - return select; - }); - } -} + shapes.each(function (shape) { -Kickstart.register(DataManager.init); + DataManager.__persistShape(shape); + result += DataManager.serialize( + $(ERDF.__stripHashes(shape.resourceId)), true); + }); -function assert(expr, m) { if(!expr) throw m; }; + //result += DataManager.__renderCanvas(facade); -function DMCommand(action, triple) { - - // store action and triple. - this.action = action; - this.triple = triple; - - this.toString = function() { - return 'Command('+action+', '+triple+')'; - }; -} + return result; + }, -function DMCommandHandler(nextHandler) { - - /** - * Private method to set the next handler in the Chain of Responsibility - * (see http://en.wikipedia.org/wiki/Chain-of-responsibility_pattern for - * details). - * @param {DMCommandHandler} handler The handler that is next in the chain. - */ - this.__setNext = function(handler) { - var _next = this.__next; - this.__next = nextHandler; - return _next ? _next : true; - }; - this.__setNext(nextHandler); - - /** - * Invokes the next handler. If there is no next handler, this method - * returns false, otherwise it forwards the result of the handling. - * @param {Object} command The command object to be processed. - */ - this.__invokeNext = function(command) { - return this.__next ? this.__next.handle(command) : false; - }; - - /** - * Handles a command. The abstract method process() is called with the - * command object that has been passed. If the process method catches the - * command (returns true on completion), the handle() method returns true. - * If the process() method doesn't catch the command, the next handler will - * be invoked. - * @param {Object} command The command object to be processed. - */ - this.handle = function(command) { - return this.process(command) ? true : this.__invokeNext(command); - } - - /** - * Empty process() method returning false. If javascript knew abstract - * class members, this would be one. - * @param {Object} command The command object to process. - */ - this.process = function(command) { return false; }; -}; + __renderCanvas: function (facade) { + + var canvas = facade.getCanvas(); + var stencilSets = facade.getStencilSets(); + var shapes = canvas.getChildShapes(true); + + DataManager.__forceExistance(canvas); + + DataManager.__persistShape(canvas); + + var shapeResource = new ERDF.Resource(canvas.resourceId); + + // remove all triples for this particular shape's resource + DataManager.removeTriples(DataManager.query( + shapeResource, undefined, undefined)); + + DataManager.addTriple(new ERDF.Triple( + shapeResource, + {prefix: "oryx", name: "mode"}, + new ERDF.Literal("writable") + )); + + DataManager.addTriple(new ERDF.Triple( + shapeResource, + {prefix: "oryx", name: "mode"}, + new ERDF.Literal("fullscreen") + )); + + stencilSets.values().each(function (stencilset) { + DataManager.addTriple(new ERDF.Triple( + shapeResource, + {prefix: "oryx", name: "stencilset"}, + new ERDF.Resource(stencilset.source().replace(/&/g, "%26")) + )); + + DataManager.addTriple(new ERDF.Triple( + shapeResource, + {prefix: "oryx", name: "ssnamespace"}, + new ERDF.Resource(stencilset.namespace()) + )); + + stencilset.extensions().keys().each(function (extension) { + DataManager.addTriple(new ERDF.Triple( + shapeResource, + {prefix: "oryx", name: "ssextension"}, + new ERDF.Literal(extension) + )); + }); + }); -/** - * This Handler manages the addition and the removal of meta elements in the - * head of the document. - * @param {DMCommandHandler} next The handler that is next in the chain. - */ -function MetaTagHandler(next) { - - DMCommandHandler.apply(this, [next]); - this.process = function(command) { - - with(command.triple) { - - /* assert prerequisites */ - if( !( - (subject instanceof ERDF.Resource) && - (subject.isCurrentDocument()) && - (object instanceof ERDF.Literal) - )) return false; - } - - }; -}; + shapes.each(function (shape) { + DataManager.addTriple(new ERDF.Triple( + shapeResource, + {prefix: "oryx", name: "render"}, + new ERDF.Resource("#" + shape.resourceId) + )); + }); + }, -var chain = new MetaTagHandler(); -var command = new DMCommand(TRIPLE_ADD, new ERDF.Triple( - new ERDF.Resource(''), - 'rdf:tool', - new ERDF.Literal('') -)); + __counter: 0, + __provideId: function () { -/* -if(chain.handle(command)) - alert('Handled!'); -*/ + while ($(RESOURCE_ID_PREFIX + DataManager.__counter)) + DataManager.__counter++; -ResourceManager = { - - __corrupt: false, - __latelyCreatedResource: undefined, - __listeners: $H(), - __token: 1, - - addListener: function(listener, mask) { - - if(!(listener instanceof Function)) - throw 'Resource event listener is not a function!'; - if(!(mask)) - throw 'Invalid mask for resource event listener registration.'; - - // construct controller and token. - var controller = {listener: listener, mask: mask}; - var token = ResourceManager.__token++; - - // add new listener. - ResourceManager.__listeners[token] = controller; - - // return the token generated. - return token; - }, - - removeListener: function(token) { - - // remove the listener with the token and return it. - return ResourceManager.__listners.remove(token); - }, - - __Event: function(action, resourceId) { - this.action = action; - this.resourceId = resourceId; - }, - - __dispatchEvent: function(event) { - - // get all listeners. for each listener, ... - ResourceManager.__listeners.values().each(function(controller) { - - // .. if listener subscribed to this type of event ... - if(event.action & controller.mask) - return controller.listener(event); - }); - }, + return RESOURCE_ID_PREFIX + DataManager.__counter; + }, - getResource: function(id) { + serializeDOM: function (facade) { - // get all possible resources for this. - id = ERDF.__stripHashes(id); - var resources = DataManager.query( - new ERDF.Resource('#'+id), - {prefix: 'raziel', name: 'entry'}, - undefined - ); + return DataManager.__persistDOM(facade); + }, - // check for consistency. - if((resources.length == 1) && (resources[0].object.isResource())) { - var entryUrl = resources[0].object.value; - return new ResourceManager.__Resource(id, entryUrl); - } + syncGlobal: function (facade) { - // else throw an error message. - throw ('Resource with id ' +id+ ' not recognized as such. ' + - ((resources.length > 1) ? - ' There is more than one raziel:entry URL.' : - ' There is no raziel:entry URL.')); + return DataManager.__syncglobal(facade); + }, - return false; - }, + /** + * This method is used to synchronize local DOM with remote resources. + * Local changes are commited to the server, and remote changes are + * performed to the local document. + * @param {Object} facade The facade of the editor that holds certain + * resource representations as shapes. + */ + __syncglobal: function (facade) { - __createResource: function(alternativeDiv) { - - var collectionUrls = DataManager.query( - new ERDF.Resource(''), - // TODO This will become raziel:collection in near future. - {prefix: 'raziel', name: 'collection'}, - undefined - ); - - // check for consistency. - - if( (collectionUrls.length == 1) && - (collectionUrls[0].object.isResource())) { - - // get the collection url. - - var collectionUrl = collectionUrls[0].object.value; - var resource = undefined; - - // if there is an old id, serialize the dummy div from there, - // otherwise create a dummy div on the fly. - - var serialization = alternativeDiv? alternativeDiv : - '
'; - - ResourceManager.__request( - 'POST', collectionUrl, serialization, - - // on success - function() { - - // get div and id that have been generated by the server. - - var response = (this.responseXML); - var div = response.childNodes[0]; - var id = div.getAttribute('id'); - - // store div in DOM - 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(div.cloneNode(true)); - - // parse local erdf data once more. - - DataManager.__synclocal(); - - // get new resource object. - - resource = new ResourceManager.getResource(id); - - // set up an action informing of the creation. - - ResourceManager.__resourceActionSucceeded( - this, RESOURCE_CREATED, undefined); - }, - - function() { ResourceManager.__resourceActionFailed( - this, RESOURCE_CREATED, undefined);}, - false - ); - - return resource; - } - - // else - throw 'Could not create resource! raziel:collection URL is missing!'; - return false; + // getChildShapes gets all shapes (nodes AND edges), deep flag + // makes it return a flattened child hierarchy. - }, - - __Resource: function(id, url) { - - this.__id = id; - this.__url = url; - - /* - * Process URL is no longer needed to refer to the shape element on the - * canvas. AReSS uses the id's to gather information on fireing - * behaviour now. - */ - -// // find the process url. -// var processUrl = undefined; -// -// var urls = DataManager.query( -// new ERDF.Resource('#'+this.__id), -// {prefix: 'raziel', name: 'process'}, -// undefined -// ); -// -// if(urls.length == 0) { throw 'The resource with the id ' +id+ ' has no process url.'}; -// -// urls.each( function(triple) { -// -// // if there are more urls, use the last one. -// processUrl = triple.object.value; -// }); -// -// this.__processUrl = processUrl; -// -// // convenience function for getting the process url. -// this.processUrl = function() { -// return this.__processUrl; -// } + var canvas = facade.getCanvas(); + var shapes = canvas.getChildShapes(true); + // create dummy resource representations in the dom + // for all shapes that were newly created. - // convenience finction for getting the id. - this.id = function() { - return this.__id; - } + shapes.select(function (shape) { - // convenience finction for getting the entry url. - this.url = function() { - return this.__url; - } - - this.reload = function() { - var _url = this.__url; - var _id = this.__id; - ResourceManager.__request( - 'GET', _url, null, - function() { ResourceManager.__resourceActionSucceeded( - this, RESOURCE_RELOADED, _id); }, - function() { ResourceManager.__resourceActionFailed( - this, RESURCE_RELOADED, _id); }, - USE_ASYNCHRONOUS_REQUESTS - ); - }; - - this.save = function(synchronize) { - var _url = this.__url; - var _id = this.__id; - data = DataManager.serialize($(_id)); - ResourceManager.__request( - 'PUT', _url, data, - function() { ResourceManager.__resourceActionSucceeded( - this, synchronize ? RESOURCE_SAVED | RESOURCE_SYNCHRONIZED : RESOURCE_SAVED, _id); }, - function() { ResourceManager.__resourceActionFailed( - this, synchronize ? RESOURCE_SAVED | RESOURCE_SYNCHRONIZED : RESOURCE.SAVED, _id); }, - USE_ASYNCHRONOUS_REQUESTS - ); - }; - - this.remove = function() { - var _url = this.__url; - var _id = this.__id; - ResourceManager.__request( - 'DELETE', _url, null, - function() { ResourceManager.__resourceActionSucceeded( - this, RESOURCE_REMOVED, _id); }, - function() { ResourceManager.__resourceActionFailed( - this, RESOURCE_REMOVED, _id);}, - USE_ASYNCHRONOUS_REQUESTS - ); - }; - }, + // select shapes without resource id. - request: function(url, requestOptions) { - - var options = { - method: 'get', - asynchronous: true, - parameters: {} - }; - - Object.extend(options, requestOptions || {}); - - var params = Hash.toQueryString(options.parameters); - if (params) - url += (url.include('?') ? '&' : '?') + params; - - return ResourceManager.__request( - options.method, - url, - options.data, - (options.onSuccess instanceof Function ? function() { options.onSuccess(this); } : undefined ), - (options.onFailure instanceof Function ? function() { options.onFailure(this); } : undefined ), - options.asynchronous && USE_ASYNCHRONOUS_REQUESTS, - options.headers); - }, - - __request: function(method, url, data, success, error, async, headers) { - - // get a request object - var httpRequest = Try.these( - - /* do the Mozilla/Safari/Opera stuff */ - function() { return new XMLHttpRequest(); }, - - /* do the IE stuff */ - function() { return new ActiveXObject("Msxml2.XMLHTTP"); }, - function() { return new ActiveXObject("Microsoft.XMLHTTP") } - ); - - // if there is no request object ... - if (!httpRequest) { - 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(success instanceof Function) - httpRequest.onload = success; - if(error instanceof Function) { - httpRequest.onerror = error; - } - - var h = $H(headers) - h.keys().each(function(key) { - - httpRequest.setRequestHeader(key, h[key]); - }); - - try { - - if(SHOW_DEBUG_ALERTS_WHEN_SAVING) - - alert(method + ' ' + url + '\n' + - SHOW_EXTENDED_DEBUG_INFORMATION ? data : ''); - - // TODO Remove synchronous calls to the server as soon as xenodot - // handles asynchronous requests without failure. - httpRequest.open(method, url, !async?false:true); - httpRequest.send(data); - - } catch(e) { - return false; - } - return true; - }, - - __resourceActionSucceeded: function(transport, action, id) { - - var status = transport.status; - var response = transport.responseText; - - if(SHOW_DEBUG_ALERTS_WHEN_SAVING) - - alert(status + ' ' + url + '\n' + - SHOW_EXTENDED_DEBUG_INFORMATION ? data : ''); - - // if the status code is not in 2xx, throw an error. - if(status >= 300) - throw '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.'); - - switch(action) { - - case RESOURCE_REMOVED: - - // get div and id - var response = (transport.responseXML); - var div = response.childNodes[0]; - var id = div.getAttribute('id'); - - // remove the resource from DOM - var localDiv = document.getElementById(id); - localDiv.parentNode.removeChild(localDiv); - break; - - case RESOURCE_CREATED: - - // nothing remains to be done. - break; - - case RESOURCE_SAVED | RESOURCE_SYNCHRONIZED: - - DataManager.__synclocal(); - - case RESOURCE_SAVED: - - // nothing remains to be done. - break; - - case RESOURCE_RELOADED: - - // get div and id - var response = (transport.responseXML); - var div = response.childNodes[0]; - var id = div.getAttribute('id'); - - // remove the local resource representation from DOM - var localDiv = document.getElementById(id) - localDiv.parentNode.removeChild(localDiv); - - // store div in DOM - 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(div.cloneNode(true)); - DataManager.__synclocal(); - break; - - default: - DataManager.__synclocal(); + return !($(shape.resourceId)); - } - - // dispatch to all listeners ... - ResourceManager.__dispatchEvent( + }).each(function (shape) { - // ... an event describing the change that happened here. - new ResourceManager.__Event(action, id) - ); - }, + // create new resources for them. + if (USE_ARESS_WORKAROUNDS) { - __resourceActionFailed: function(transport, action, id) { - 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?"; - } -}/* - * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. - * License rights for this program may be obtained from Alfresco Software, Ltd. - * pursuant to a written agreement and any use of this program without such an - * agreement is prohibited. - */ -/* - * All code Copyright 2013 KIS Consultancy all rights reserved - */ + /* + * This is a workaround due to a bug in aress. Resources are + * ignoring changes to raziel:type property once they are + * created. As long as this is not fixed, the resource is now + * being created using a randomly guessed id, this temporary id + * is then used in references and the appropriate div is being + * populated with properties. + * + * AFTER THIS PHASE THE DATA IS INCONSISTENT AS REFERENCES POINT + * TO IDS THAT ARE UNKNOWN TO THE BACK END. + * + * After the resource is actually created in aress, it gets an id + * that is persistent. All shapes are then being populated with the + * correct id references and stored on the server. + * + * AFTER THE SAVE PROCESS HAS RETURNED, THE DATA IS CONSISTENT + * REGARDING THE ID REFERENCES AGAIN. + */ -/** - * The super class for all classes in ORYX. Adds some OOP feeling to javascript. - * See article "Object Oriented Super Class Method Calling with JavaScript" on - * http://truecode.blogspot.com/2006/08/object-oriented-super-class-method.html - * for a documentation on this. Fairly good article that points out errors in - * Douglas Crockford's inheritance and super method calling approach. - * Worth reading. - * @class Clazz - */ -var Clazz = function() {}; + var razielType = shape.properties['raziel-type']; -/** - * Empty constructor. - * @methodOf Clazz.prototype - */ -Clazz.prototype.construct = function() {}; + var div = '
' + + '' + razielType + '
'; -/** - * Can be used to build up inheritances of classes. - * @example - * var MyClass = Clazz.extend({ - * construct: function(myParam){ - * // Do sth. - * } - * }); - * var MySubClass = MyClass.extend({ - * construct: function(myParam){ - * // Use this to call constructor of super class - * arguments.callee.$.construct.apply(this, arguments); - * // Do sth. - * } - * }); - * @param {Object} def The definition of the new class. - */ -Clazz.extend = function(def) { - var classDef = function() { - if (arguments[0] !== Clazz) { this.construct.apply(this, arguments); } - }; - - var proto = new this(Clazz); - var superClass = this.prototype; - - for (var n in def) { - var item = def[n]; - if (item instanceof Function) item.$ = superClass; - proto[n] = item; - } + var r = ResourceManager.__createResource(div); + shape.resourceId = r.id(); - classDef.prototype = proto; - - //Give this new class the same static extend method - classDef.extend = this.extend; - return classDef; -};/* - * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. - * License rights for this program may be obtained from Alfresco Software, Ltd. - * pursuant to a written agreement and any use of this program without such an - * agreement is prohibited. - */ -/* - * All code Copyright 2013 KIS Consultancy all rights reserved - */ + } else { -if(!ORYX) var ORYX = {}; + var r = ResourceManager.__createResource(); + shape.resourceId = r.id(); + } -if(!ORYX.CONFIG) ORYX.CONFIG = {}; + }); -/** - * This file contains URI constants that may be used for XMLHTTPRequests. - */ + shapes.each(function (shape) { -ORYX.CONFIG.ROOT_PATH = "../../editor/"; //TODO: Remove last slash!! -ORYX.CONFIG.EXPLORER_PATH = "explorer"; -ORYX.CONFIG.LIBS_PATH = "libs"; + // store all shapes. + DataManager.__storeShape(shape); + }); + }, -/** - * Regular Config - */ -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";/* - * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. - * License rights for this program may be obtained from Alfresco Software, Ltd. - * pursuant to a written agreement and any use of this program without such an - * agreement is prohibited. - */ -/* - * All code Copyright 2013 KIS Consultancy all rights reserved - */ + /** + * This method serializes a single div into a string that satisfies the + * client/server communication protocol. It ingnores all elements that have + * an attribute named class that includes 'transient'. + * @param {Object} node the element to serialize. + * @param {Object} preserveNamespace whether to preserve the parent's + * namespace. If you are not sure about namespaces, provide + * just the element to be serialized. + */ + serialize: function (node, preserveNamespace) { -if(!ORYX) var ORYX = {}; + if (node.nodeType == node.ELEMENT_NODE) { + // serialize an element node. -if(!ORYX.CONFIG) ORYX.CONFIG = {}; + var children = $A(node.childNodes); + var attributes = $A(node.attributes); + var clazz = new String(node.getAttribute('class')); + var ignore = clazz.split(' ').member('transient'); -/** - * Signavio specific variables - */ -ORYX.CONFIG.BACKEND_SWITCH = true; -ORYX.CONFIG.PANEL_LEFT_WIDTH = 250; -ORYX.CONFIG.PANEL_RIGHT_COLLAPSED = true; -ORYX.CONFIG.PANEL_RIGHT_WIDTH = 300; -ORYX.CONFIG.APPNAME = 'KISBPM'; -ORYX.CONFIG.WEB_URL = "."; + // ignore transients. -ORYX.CONFIG.BLANK_IMAGE = ORYX.CONFIG.LIBS_PATH + '/ext-2.0.2/resources/images/default/s.gif'; + if (ignore) + return ''; -/* Specify offset of header */ -ORYX.CONFIG.OFFSET_HEADER = 61; + // start serialization. -/* Show grid line while dragging */ -ORYX.CONFIG.SHOW_GRIDLINE = true; + var result = '<' + node.nodeName; - /* Editor-Mode */ -ORYX.CONFIG.MODE_READONLY = "readonly"; -ORYX.CONFIG.MODE_FULLSCREEN = "fullscreen"; -ORYX.CONFIG.WINDOW_HEIGHT = 800; -ORYX.CONFIG.PREVENT_LOADINGMASK_AT_READY = false; + // preserve namespace? + if (!preserveNamespace) + result += ' xmlns="' + (node.namespaceURI ? node.namespaceURI : XMLNS.XHTML) + '" xmlns:oryx="http://oryx-editor.org"'; - /* Plugins */ -ORYX.CONFIG.PLUGINS_ENABLED = true; -ORYX.CONFIG.PLUGINS_FOLDER = "Plugins/"; + // add all attributes. -ORYX.CONFIG.BPMN20_SCHEMA_VALIDATION_ON = true; + attributes.each(function (attribute) { + result += ' ' + attribute.nodeName + '="' + + attribute.nodeValue + '"'; + }); - /* Namespaces */ -ORYX.CONFIG.NAMESPACE_ORYX = "http://www.b3mn.org/oryx"; -ORYX.CONFIG.NAMESPACE_SVG = "http://www.w3.org/2000/svg"; - - /* UI */ -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; // Updated so the form editor shows all elements at once + // close if no children. -ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET_CORNER = 30; -ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET = 45; + if (children.length == 0) + result += '/>'; - /* Shape-Menu Align */ -ORYX.CONFIG.SHAPEMENU_RIGHT = "Oryx_Right"; -ORYX.CONFIG.SHAPEMENU_BOTTOM = "Oryx_Bottom"; -ORYX.CONFIG.SHAPEMENU_LEFT = "Oryx_Left"; -ORYX.CONFIG.SHAPEMENU_TOP = "Oryx_Top"; - - - /* Morph-Menu Item */ -ORYX.CONFIG.MORPHITEM_DISABLED = "Oryx_MorphItem_disabled"; - - /* Property type names */ -ORYX.CONFIG.TYPE_STRING = "string"; -ORYX.CONFIG.TYPE_BOOLEAN = "boolean"; -ORYX.CONFIG.TYPE_INTEGER = "integer"; -ORYX.CONFIG.TYPE_FLOAT = "float"; -ORYX.CONFIG.TYPE_COLOR = "color"; -ORYX.CONFIG.TYPE_DATE = "date"; -ORYX.CONFIG.TYPE_CHOICE = "choice"; -ORYX.CONFIG.TYPE_URL = "url"; -ORYX.CONFIG.TYPE_DIAGRAM_LINK = "diagramlink"; -ORYX.CONFIG.TYPE_COMPLEX = "complex"; -ORYX.CONFIG.TYPE_MULTIPLECOMPLEX = "multiplecomplex"; -ORYX.CONFIG.TYPE_TEXT = "text"; -ORYX.CONFIG.TYPE_KISBPM_MULTIINSTANCE = "kisbpm-multiinstance"; -ORYX.CONFIG.TYPE_MODEL_LINK = "modellink"; -ORYX.CONFIG.TYPE_FORM_FLOW_LINK = "formflowlink"; -ORYX.CONFIG.TYPE_FORM_LINK = "formlink"; -ORYX.CONFIG.TYPE_SUB_PROCESS_LINK = "subprocesslink"; -ORYX.CONFIG.TYPE_SERVICE_LINK = "servicelink"; -ORYX.CONFIG.TYPE_CONDITIONS = "conditions"; -ORYX.CONFIG.TYPE_VARIABLES = "variables"; -ORYX.CONFIG.TYPE_LISTENER = "listener"; -ORYX.CONFIG.TYPE_EPC_FREQ = "epcfrequency"; -ORYX.CONFIG.TYPE_GLOSSARY_LINK = "glossarylink"; -ORYX.CONFIG.TYPE_EXPRESSION = "expression"; -ORYX.CONFIG.TYPE_DATASOURCE = "datasource"; -ORYX.CONFIG.TYPE_DATASOURCE_MINIMAL = "datasource-minimal"; -ORYX.CONFIG.TYPE_VALIDATORS = "validators"; - - - /* Vertical line distance of multiline labels */ -ORYX.CONFIG.LABEL_LINE_DISTANCE = 2; -ORYX.CONFIG.LABEL_DEFAULT_LINE_HEIGHT = 12; - - /* Open Morph Menu with Hover */ -ORYX.CONFIG.ENABLE_MORPHMENU_BY_HOVER = false; + else { + // serialize all children. - /* Editor constants come here */ -ORYX.CONFIG.EDITOR_ALIGN_BOTTOM = 0x01; -ORYX.CONFIG.EDITOR_ALIGN_MIDDLE = 0x02; -ORYX.CONFIG.EDITOR_ALIGN_TOP = 0x04; -ORYX.CONFIG.EDITOR_ALIGN_LEFT = 0x08; -ORYX.CONFIG.EDITOR_ALIGN_CENTER = 0x10; -ORYX.CONFIG.EDITOR_ALIGN_RIGHT = 0x20; -ORYX.CONFIG.EDITOR_ALIGN_SIZE = 0x30; - - /* Event types */ -ORYX.CONFIG.EVENT_MOUSEDOWN = "mousedown"; -ORYX.CONFIG.EVENT_MOUSEUP = "mouseup"; -ORYX.CONFIG.EVENT_MOUSEOVER = "mouseover"; -ORYX.CONFIG.EVENT_MOUSEOUT = "mouseout"; -ORYX.CONFIG.EVENT_MOUSEMOVE = "mousemove"; -ORYX.CONFIG.EVENT_DBLCLICK = "dblclick"; -ORYX.CONFIG.EVENT_KEYDOWN = "keydown"; -ORYX.CONFIG.EVENT_KEYUP = "keyup"; - -ORYX.CONFIG.EVENT_LOADED = "editorloaded"; -ORYX.CONFIG.EVENT_SAVED = "editorSaved"; - -ORYX.CONFIG.EVENT_EXECUTE_COMMANDS = "executeCommands"; -ORYX.CONFIG.EVENT_STENCIL_SET_LOADED = "stencilSetLoaded"; -ORYX.CONFIG.EVENT_SELECTION_CHANGED = "selectionchanged"; -ORYX.CONFIG.EVENT_SHAPEADDED = "shapeadded"; -ORYX.CONFIG.EVENT_SHAPEREMOVED = "shaperemoved"; -ORYX.CONFIG.EVENT_PROPERTY_CHANGED = "propertyChanged"; -ORYX.CONFIG.EVENT_DRAGDROP_START = "dragdrop.start"; -ORYX.CONFIG.EVENT_SHAPE_MENU_CLOSE = "shape.menu.close"; -ORYX.CONFIG.EVENT_DRAGDROP_END = "dragdrop.end"; -ORYX.CONFIG.EVENT_RESIZE_START = "resize.start"; -ORYX.CONFIG.EVENT_RESIZE_END = "resize.end"; -ORYX.CONFIG.EVENT_DRAGDOCKER_DOCKED = "dragDocker.docked"; -ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW = "highlight.showHighlight"; -ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE = "highlight.hideHighlight"; -ORYX.CONFIG.EVENT_LOADING_ENABLE = "loading.enable"; -ORYX.CONFIG.EVENT_LOADING_DISABLE = "loading.disable"; -ORYX.CONFIG.EVENT_LOADING_STATUS = "loading.status"; -ORYX.CONFIG.EVENT_OVERLAY_SHOW = "overlay.show"; -ORYX.CONFIG.EVENT_OVERLAY_HIDE = "overlay.hide"; -ORYX.CONFIG.EVENT_ARRANGEMENT_TOP = "arrangement.setToTop"; -ORYX.CONFIG.EVENT_ARRANGEMENT_BACK = "arrangement.setToBack"; -ORYX.CONFIG.EVENT_ARRANGEMENT_FORWARD = "arrangement.setForward"; -ORYX.CONFIG.EVENT_ARRANGEMENT_BACKWARD = "arrangement.setBackward"; -ORYX.CONFIG.EVENT_PROPWINDOW_PROP_CHANGED = "propertyWindow.propertyChanged"; -ORYX.CONFIG.EVENT_LAYOUT_ROWS = "layout.rows"; -ORYX.CONFIG.EVENT_LAYOUT_BPEL = "layout.BPEL"; -ORYX.CONFIG.EVENT_LAYOUT_BPEL_VERTICAL = "layout.BPEL.vertical"; -ORYX.CONFIG.EVENT_LAYOUT_BPEL_HORIZONTAL = "layout.BPEL.horizontal"; -ORYX.CONFIG.EVENT_LAYOUT_BPEL_SINGLECHILD = "layout.BPEL.singlechild"; -ORYX.CONFIG.EVENT_LAYOUT_BPEL_AUTORESIZE = "layout.BPEL.autoresize"; -ORYX.CONFIG.EVENT_AUTOLAYOUT_LAYOUT = "autolayout.layout"; -ORYX.CONFIG.EVENT_UNDO_EXECUTE = "undo.execute"; -ORYX.CONFIG.EVENT_UNDO_ROLLBACK = "undo.rollback"; -ORYX.CONFIG.EVENT_BUTTON_UPDATE = "toolbar.button.update"; -ORYX.CONFIG.EVENT_LAYOUT = "layout.dolayout"; -ORYX.CONFIG.EVENT_GLOSSARY_LINK_EDIT = "glossary.link.edit"; -ORYX.CONFIG.EVENT_GLOSSARY_SHOW = "glossary.show.info"; -ORYX.CONFIG.EVENT_GLOSSARY_NEW = "glossary.show.new"; -ORYX.CONFIG.EVENT_DOCKERDRAG = "dragTheDocker"; -ORYX.CONFIG.EVENT_CANVAS_SCROLL = "canvas.scroll"; - -ORYX.CONFIG.EVENT_SHOW_PROPERTYWINDOW = "propertywindow.show"; -ORYX.CONFIG.EVENT_ABOUT_TO_SAVE = "file.aboutToSave"; - - /* Selection Shapes Highlights */ -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; - - /* Copy & Paste */ -ORYX.CONFIG.EDIT_OFFSET_PASTE = 10; - - /* Key-Codes */ -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; - - // TODO Determine where the lowercase constants are still used and remove them from here. -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; + result += '>'; + children.each(function (_node) { + result += DataManager.serialize(_node, true) + }); + result += '' + } -/* Supported Meta Keys */ - -ORYX.CONFIG.META_KEY_META_CTRL = "metactrl"; -ORYX.CONFIG.META_KEY_ALT = "alt"; -ORYX.CONFIG.META_KEY_SHIFT = "shift"; + return result; -/* Key Actions */ + } else if (node.nodeType == node.TEXT_NODE) { -ORYX.CONFIG.KEY_ACTION_DOWN = "down"; -ORYX.CONFIG.KEY_ACTION_UP = "up"; + // serialize a text node. + return node.nodeValue; + } + //TODO serialize cdata areas also. + //TODO work on namespace awareness. + }, -/* Form Rowlayouting */ -ORYX.CONFIG.FORM_ROW_WIDTH = 350; -ORYX.CONFIG.FORM_GROUP_MARGIN = 5; -ORYX.CONFIG.FORM_GROUP_EMPTY_HEIGHT = 100; + addTriple: function (triple) { -/* Form element types */ -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'; - - /* - * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. - * License rights for this program may be obtained from Alfresco Software, Ltd. - * pursuant to a written agreement and any use of this program without such an - * agreement is prohibited. - */ -/* - * All code Copyright 2013 KIS Consultancy all rights reserved - */ + // assert the subject is a resource -function printf() { - - var result = arguments[0]; - for (var i=1; i= 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(prefix, messageParts) { - - messageParts[0] = (new Date()).getTime() + " " - + prefix + " " + messageParts[0]; - var message = printf.apply(null, messageParts); - - ORYX.Log.__appenders.each(function(appender) { - appender.append(message); - }); - }, - - addAppender: function(appender) { - ORYX.Log.__appenders.push(appender); - } - }, + // alert('Removing ' +triples.length+' triples.'); - /** - * First bootstrapping layer. The Oryx loading procedure begins. In this - * step, all preliminaries that are not in the responsibility of Oryx to be - * met have to be checked here, such as the existance of the prototpe - * library in the current execution environment. After that, the second - * bootstrapping layer is being invoked. Failing to ensure that any - * preliminary condition is not met has to fail with an error. - */ - load: function() { - - ORYX.Log.debug("Oryx begins loading procedure."); - - // check for prototype - 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."); - - // continue loading. - ORYX._load(); - }, + // from all the triples select those ... + var removed = triples.select( + function (triple) { - /** - * Second bootstrapping layer. The oryx configuration is checked. When not - * yet loaded, config.js is being requested from the server. A repeated - * error in retrieving the configuration will result in an error to be - * thrown after a certain time of retries. Once the configuration is there, - * all urls that are registered with oryx loading are being requested from - * the server. Once everything is loaded, the third layer is being invoked. - */ - _load: function() { - /* - // if configuration not there already, - if(!(ORYX.CONFIG)) { - - // if this is the first attempt... - if(ORYX.configrationRetries == 0) { - - // get the path and filename. - var configuration = ORYX.PATH + ORYX.CONFIGURATION; - - ORYX.Log.debug("Configuration not found, loading from '%0'.", - configuration); - - // require configuration file. - Kickstart.require(configuration); - - // else if attempts exceeded ... - } else if(ORYX.configrationRetries >= ORYX_CONFIGURATION_WAIT_ATTEMPTS) { - - throw "Tried to get configuration" + - ORYX_CONFIGURATION_WAIT_ATTEMPTS + - " times from '" + configuration + "'. Giving up." - - } else if(ORYX.configrationRetries > 0){ - - // point out how many attempts are left... - ORYX.Log.debug("Waiting once more (%0 attempts left)", - (ORYX_CONFIGURATION_WAIT_ATTEMPTS - - ORYX.configrationRetries)); + // TODO remove also from triple store. + // ... that were actually removed. + return DataManager.__removeTriple(triple); + }); - } - - // any case: continue in a moment with increased retry count. - ORYX.configrationRetries++; - window.setTimeout(ORYX._load, ORYX_CONFIGURATION_DELAY); - return; - } - - ORYX.Log.info("Configuration loaded."); - - // load necessary scripts. - ORYX.URLS.each(function(url) { - ORYX.Log.debug("Requireing '%0'", url); - Kickstart.require(ORYX.PATH + url) }); - */ - // configurate logging and load plugins. - ORYX.loadPlugins(); - }, + // sync and return removed triples. + // DataManager.__synclocal(); + return removed; + }, - /** - * Third bootstrapping layer. This is where first the plugin coniguration - * file is loaded into oryx, analyzed, and where all plugins are being - * requested by the server. Afterwards, all editor instances will be - * initialized. - */ - loadPlugins: function() { - - // load plugins if enabled. - if(ORYX.CONFIG.PLUGINS_ENABLED) - ORYX._loadPlugins() - else - ORYX.Log.warn("Ignoring plugins, loading Core only."); - - // init the editor instances. - init(); - }, - - _loadPlugins: function() { + removeTriple: function (triple) { - // load plugin configuration file. - var source = ORYX.CONFIG.PLUGINS_CONFIG; + // remember whether the triple was actually removed. + var result = DataManager.__removeTriple(triple); - ORYX.Log.debug("Loading plugin configuration from '%0'.", source); - - new Ajax.Request(source, { - asynchronous: false, - method: 'get', - onSuccess: function(result) { + // sync and return removed triples. + // DataManager.__synclocal(); + return result; + }, - /* - * This is the method that is being called when the plugin - * configuration was successfully loaded from the server. The - * file has to be processed and the contents need to be - * considered for further plugin requireation. - */ - - ORYX.Log.info("Plugin configuration file loaded."); - - // get plugins.xml content - var resultXml = result.responseXML; - - // TODO: Describe how properties are handled. - // Get the globale Properties - var globalProperties = []; - var preferences = $A(resultXml.getElementsByTagName("properties")); - preferences.each( function(p) { - - var props = $A(p.childNodes); - props.each( function(prop) { - var property = new Hash(); - - // get all attributes from the node and set to global properties - var attributes = $A(prop.attributes) - attributes.each(function(attr){property[attr.nodeName] = attr.nodeValue}); - if(attributes.length > 0) { globalProperties.push(property) }; - }); - }); + __removeTriple: function (triple) { - - // TODO Why are we using XML if we don't respect structure anyway? - // for each plugin element in the configuration.. - var plugin = resultXml.getElementsByTagName("plugin"); - $A(plugin).each( function(node) { - - // get all element's attributes. - // TODO: What about: var pluginData = $H(node.attributes) !? - var pluginData = new Hash(); - $A(node.attributes).each( function(attr){ - pluginData[attr.nodeName] = attr.nodeValue}); - - // ensure there's a name attribute. - if(!pluginData['name']) { - ORYX.Log.error("A plugin is not providing a name. Ingnoring this plugin."); - return; - } + // assert the subject is a resource + if (!triple.subject.type == ERDF.LITERAL) - // ensure there's a source attribute. - if(!pluginData['source']) { - ORYX.Log.error("Plugin with name '%0' doesn't provide a source attribute.", pluginData['name']); - return; - } - - // Get all private Properties - var propertyNodes = node.getElementsByTagName("property"); - var properties = []; - $A(propertyNodes).each(function(prop) { - var property = new Hash(); - - // Get all Attributes from the Node - var attributes = $A(prop.attributes) - attributes.each(function(attr){property[attr.nodeName] = attr.nodeValue}); - if(attributes.length > 0) { properties.push(property) }; - - }); - - // Set all Global-Properties to the Properties - properties = properties.concat(globalProperties); - - // Set Properties to Plugin-Data - pluginData['properties'] = properties; - - // Get the RequieredNodes - var requireNodes = node.getElementsByTagName("requires"); - var requires; - $A(requireNodes).each(function(req) { - var namespace = $A(req.attributes).find(function(attr){ return attr.name == "namespace"}) - if( namespace && namespace.nodeValue ){ - if( !requires ){ - requires = {namespaces:[]} - } - - requires.namespaces.push(namespace.nodeValue) - } - }); - - // Set Requires to the Plugin-Data, if there is one - if( requires ){ - pluginData['requires'] = requires; - } + throw 'Cannot remove the triple ' + triple.toString() + + ' because the subject is not a resource.'; + // get the element which represents this triple's subject. + var elementId = ERDF.__stripHashes(triple.subject.value); + var element = $(elementId); - // Get the RequieredNodes - var notUsesInNodes = node.getElementsByTagName("notUsesIn"); - var notUsesIn; - $A(notUsesInNodes).each(function(not) { - var namespace = $A(not.attributes).find(function(attr){ return attr.name == "namespace"}) - if( namespace && namespace.nodeValue ){ - if( !notUsesIn ){ - notUsesIn = {namespaces:[]} - } - - notUsesIn.namespaces.push(namespace.nodeValue) - } - }); - - // Set Requires to the Plugin-Data, if there is one - if( notUsesIn ){ - pluginData['notUsesIn'] = notUsesIn; - } - - - var url = ORYX.PATH + ORYX.CONFIG.PLUGINS_FOLDER + pluginData['source']; - - ORYX.Log.debug("Requireing '%0'", url); - - // Add the Script-Tag to the Site - //Kickstart.require(url); - - ORYX.Log.info("Plugin '%0' successfully loaded.", pluginData['name']); - - // Add the Plugin-Data to all available Plugins - ORYX.availablePlugins.push(pluginData); - - }); - - }, - onFailure:this._loadPluginsOnFails - }); + // assert the subject is inside this document. + if (!element) - }, + throw 'Cannot remove the triple ' + triple.toString() + + ' because the subject is not in the document.'; - _loadPluginsOnFails: function(result) { + if (triple.object.type == ERDF.LITERAL) { - ORYX.Log.error("Plugin configuration file not available."); - } -}); + // continue searching actively for the triple. + var result = DataManager.__removeTripleRecursively(triple, element); + return result; + } + }, + __removeTripleRecursively: function (triple, continueFrom) { -/* - * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. - * License rights for this program may be obtained from Alfresco Software, Ltd. - * pursuant to a written agreement and any use of this program without such an - * agreement is prohibited. - */ -/* - * All code Copyright 2013 KIS Consultancy all rights reserved - */ + // return when this node is not an element node. + if (continueFrom.nodeType != continueFrom.ELEMENT_NODE) + return false; -/** - * Init namespaces - */ -if(!ORYX) {var ORYX = {};} -if(!ORYX.Core) {ORYX.Core = {};} -if(!ORYX.Core.SVG) {ORYX.Core.SVG = {};} + var classes = new String(continueFrom.getAttribute('class')); + var children = $A(continueFrom.childNodes); + if (classes.include(triple.predicate.prefix + '-' + triple.predicate.name)) { -/** - * EditPathHandler - * - * Edit SVG paths' coordinates according to specified from-to movement and - * horizontal and vertical scaling factors. - * The resulting path's d attribute is stored in instance variable d. - * - * @constructor - */ -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 - * - * @param {float} x Target point's x-coordinate - * @param {float} y Target point's y-coordinate - * @param {float} oldX Reference point's x-coordinate - * @param {float} oldY Reference point's y-coordinate - * @param {float} deltaWidth Horizontal scaling factor - * @param {float} deltaHeight Vertical scaling factor - */ - init: function(x, y, oldX, oldY, deltaWidth, deltaHeight) { - this.x = x; - this.y = y; - this.oldX = oldX; - this.oldY = oldY; - this.deltaWidth = deltaWidth; - this.deltaHeight = deltaHeight; - - this.d = ""; - }, + var content = continueFrom.textContent; + if ((triple.object.type == ERDF.LITERAL) && + (triple.object.value == content)) - /** - * editPointsAbs - * - * @param {Array} points Array of absolutePoints - */ - editPointsAbs: function(points) { - if(points instanceof Array) { - var newPoints = []; - var x, y; - for(var i = 0; i < points.length; i++) { - x = (parseFloat(points[i]) - this.oldX)*this.deltaWidth + this.x; - i++; - y = (parseFloat(points[i]) - this.oldY)*this.deltaHeight + this.y; - newPoints.push(x); - newPoints.push(y); - } - - return newPoints; - } else { - //TODO error - } - }, - - /** - * editPointsRel - * - * @param {Array} points Array of absolutePoints - */ - editPointsRel: function(points) { - if(points instanceof Array) { - var newPoints = []; - var x, y; - for(var i = 0; i < points.length; i++) { - x = parseFloat(points[i])*this.deltaWidth; - i++; - y = parseFloat(points[i])*this.deltaHeight; - newPoints.push(x); - newPoints.push(y); - } - - return newPoints; - } else { - //TODO error - } - }, + continueFrom.parentNode.removeChild(continueFrom); - /** - * arcAbs - A - * - * @param {Number} rx - * @param {Number} ry - * @param {Number} xAxisRotation - * @param {Boolean} largeArcFlag - * @param {Boolean} sweepFlag - * @param {Number} x - * @param {Number} y - */ - arcAbs: function(rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) { - var pointsAbs = this.editPointsAbs([x, y]); - var pointsRel = this.editPointsRel([rx, ry]); - - this.d = this.d.concat(" A" + pointsRel[0] + " " + pointsRel[1] + - " " + xAxisRotation + " " + largeArcFlag + - " " + sweepFlag + " " + pointsAbs[0] + " " + - pointsAbs[1] + " "); - }, + return true; - /** - * arcRel - a - * - * @param {Number} rx - * @param {Number} ry - * @param {Number} xAxisRotation - * @param {Boolean} largeArcFlag - * @param {Boolean} sweepFlag - * @param {Number} x - * @param {Number} y - */ - arcRel: function(rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) { - var pointsRel = this.editPointsRel([rx, ry, x, y]); - - this.d = this.d.concat(" a" + pointsRel[0] + " " + pointsRel[1] + - " " + xAxisRotation + " " + largeArcFlag + - " " + sweepFlag + " " + pointsRel[2] + " " + - pointsRel[3] + " "); - }, + } else { - /** - * curvetoCubicAbs - C - * - * @param {Number} x1 - * @param {Number} y1 - * @param {Number} x2 - * @param {Number} y2 - * @param {Number} x - * @param {Number} y - */ - curvetoCubicAbs: function(x1, y1, x2, y2, x, y) { - var pointsAbs = this.editPointsAbs([x1, y1, x2, y2, x, y]); - - this.d = this.d.concat(" C" + pointsAbs[0] + " " + pointsAbs[1] + - " " + pointsAbs[2] + " " + pointsAbs[3] + - " " + pointsAbs[4] + " " + pointsAbs[5] + " "); - }, + children.each(function (_node) { + DataManager.__removeTripleRecursively(triple, _node) + }); + return false; + } - /** - * curvetoCubicRel - c - * - * @param {Number} x1 - * @param {Number} y1 - * @param {Number} x2 - * @param {Number} y2 - * @param {Number} x - * @param {Number} y - */ - curvetoCubicRel: function(x1, y1, x2, y2, x, y) { - var pointsRel = this.editPointsRel([x1, y1, x2, y2, x, y]); - - this.d = this.d.concat(" c" + pointsRel[0] + " " + pointsRel[1] + - " " + pointsRel[2] + " " + pointsRel[3] + - " " + pointsRel[4] + " " + pointsRel[5] + " "); - }, + }, - /** - * linetoHorizontalAbs - H - * - * @param {Number} x - */ - linetoHorizontalAbs: function(x) { - var pointsAbs = this.editPointsAbs([x, 0]); - - this.d = this.d.concat(" H" + pointsAbs[0] + " "); - }, + /** + * graft() function + * Originally by Sean M. Burke from interglacial.com, altered for usage with + * SVG and namespace (xmlns) support. Be sure you understand xmlns before + * using this funtion, as it creates all grafted elements in the xmlns + * provided by you and all element's attribures in default xmlns. If you + * need to graft elements in a certain xmlns and wish to assign attributes + * in both that and another xmlns, you will need to do stepwise grafting, + * adding non-default attributes yourself or you'll have to enhance this + * function. Latter, I would appreciate: martin???apfelfabrik.de + * @param {Object} namespace The namespace in which + * elements should be grafted. + * @param {Object} parent The element that should contain the grafted + * structure after the function returned. + * @param {Object} t the crafting structure. + * @param {Object} doc the document in which grafting is performed. + */ + graft: function (namespace, parent, t, doc) { + + doc = (doc || (parent && parent.ownerDocument) || document); + var e; + if (t === undefined) { + echo("Can't graft an undefined value"); + } else if (t.constructor == String) { + e = doc.createTextNode(t); + } else { + for (var i = 0; i < t.length; i++) { + if (i === 0 && t[i].constructor == String) { + var snared = t[i].match(/^([a-z][a-z0-9]*)\.([^\s\.]+)$/i); + if (snared) { + e = doc.createElementNS(namespace, snared[1]); + e.setAttributeNS(null, 'class', snared[2]); + continue; + } + snared = t[i].match(/^([a-z][a-z0-9]*)$/i); + if (snared) { + e = doc.createElementNS(namespace, snared[1]); // but no class + continue; + } - /** - * linetoHorizontalRel - h - * - * @param {Number} x - */ - linetoHorizontalRel: function(x) { - var pointsRel = this.editPointsRel([x, 0]); - - this.d = this.d.concat(" h" + pointsRel[0] + " "); - }, + // Otherwise: + e = doc.createElementNS(namespace, "span"); + e.setAttribute(null, "class", "namelessFromLOL"); + } - /** - * linetoAbs - L - * - * @param {Number} x - * @param {Number} y - */ - linetoAbs: function(x, y) { - var pointsAbs = this.editPointsAbs([x, y]); - - this.d = this.d.concat(" L" + pointsAbs[0] + " " + pointsAbs[1] + " "); - }, + if (t[i] === undefined) { + echo("Can't graft an undefined value in a list!"); + } else if (t[i].constructor == String || t[i].constructor == Array) { + this.graft(namespace, e, t[i], doc); + } else if (t[i].constructor == Number) { + this.graft(namespace, e, t[i].toString(), doc); + } else if (t[i].constructor == Object) { + // hash's properties => element's attributes + for (var k in t[i]) { + e.setAttributeNS(null, k, t[i][k]); + } + } else if (t[i].constructor == Boolean) { + this.graft(namespace, e, t[i] ? 'true' : 'false', doc); + } else + throw "Object " + t[i] + " is inscrutable as an graft arglet."; + } + } - /** - * linetoRel - l - * - * @param {Number} x - * @param {Number} y - */ - linetoRel: function(x, y) { - var pointsRel = this.editPointsRel([x, y]); - - this.d = this.d.concat(" l" + pointsRel[0] + " " + pointsRel[1] + " "); - }, + if (parent) parent.appendChild(e); - /** - * movetoAbs - M - * - * @param {Number} x - * @param {Number} y - */ - movetoAbs: function(x, y) { - var pointsAbs = this.editPointsAbs([x, y]); - - this.d = this.d.concat(" M" + pointsAbs[0] + " " + pointsAbs[1] + " "); - }, + return Element.extend(e); // return the topmost created node + }, - /** - * movetoRel - m - * - * @param {Number} x - * @param {Number} y - */ - movetoRel: function(x, y) { - var pointsRel; - if(this.d === "") { - pointsRel = this.editPointsAbs([x, y]); - } else { - pointsRel = this.editPointsRel([x, y]); - } - - this.d = this.d.concat(" m" + pointsRel[0] + " " + pointsRel[1] + " "); - }, + setObject: function (triple) { - /** - * curvetoQuadraticAbs - Q - * - * @param {Number} x1 - * @param {Number} y1 - * @param {Number} x - * @param {Number} y - */ - curvetoQuadraticAbs: function(x1, y1, x, y) { - var pointsAbs = this.editPointsAbs([x1, y1, x, y]); - - this.d = this.d.concat(" Q" + pointsAbs[0] + " " + pointsAbs[1] + " " + - pointsAbs[2] + " " + pointsAbs[3] + " "); - }, + /** + * Erwartungen von Arvid an diese Funktion: + * - Es existiert genau ein triple mit dem Subjekt und Praedikat, + * das uebergeben wurde, und dieses haelt uebergebenes Objekt. + */ - /** - * curvetoQuadraticRel - q - * - * @param {Number} x1 - * @param {Number} y1 - * @param {Number} x - * @param {Number} y - */ - curvetoQuadraticRel: function(x1, y1, x, y) { - var pointsRel = this.editPointsRel([x1, y1, x, y]); - - this.d = this.d.concat(" q" + pointsRel[0] + " " + pointsRel[1] + " " + - pointsRel[2] + " " + pointsRel[3] + " "); - }, + var triples = DataManager.query( + triple.subject, + triple.predicate, + undefined + ); - /** - * curvetoCubicSmoothAbs - S - * - * @param {Number} x2 - * @param {Number} y2 - * @param {Number} x - * @param {Number} y - */ - curvetoCubicSmoothAbs: function(x2, y2, x, y) { - var pointsAbs = this.editPointsAbs([x2, y2, x, y]); - - this.d = this.d.concat(" S" + pointsAbs[0] + " " + pointsAbs[1] + " " + - pointsAbs[2] + " " + pointsAbs[3] + " "); - }, + DataManager.removeTriples(triples); - /** - * curvetoCubicSmoothRel - s - * - * @param {Number} x2 - * @param {Number} y2 - * @param {Number} x - * @param {Number} y - */ - curvetoCubicSmoothRel: function(x2, y2, x, y) { - var pointsRel = this.editPointsRel([x2, y2, x, y]); - - this.d = this.d.concat(" s" + pointsRel[0] + " " + pointsRel[1] + " " + - pointsRel[2] + " " + pointsRel[3] + " "); - }, + DataManager.addTriple(triple); - /** - * curvetoQuadraticSmoothAbs - T - * - * @param {Number} x - * @param {Number} y - */ - curvetoQuadraticSmoothAbs: function(x, y) { - var pointsAbs = this.editPointsAbs([x, y]); - - this.d = this.d.concat(" T" + pointsAbs[0] + " " + pointsAbs[1] + " "); - }, + return true; + }, - /** - * curvetoQuadraticSmoothRel - t - * - * @param {Number} x - * @param {Number} y - */ - curvetoQuadraticSmoothRel: function(x, y) { - var pointsRel = this.editPointsRel([x, y]); - - this.d = this.d.concat(" t" + pointsRel[0] + " " + pointsRel[1] + " "); - }, + query: function (subject, predicate, object) { - /** - * linetoVerticalAbs - V - * - * @param {Number} y - */ - linetoVerticalAbs: function(y) { - var pointsAbs = this.editPointsAbs([0, y]); - - this.d = this.d.concat(" V" + pointsAbs[1] + " "); - }, + /* + * Typical triple. + * {value: subject, type: subjectType}, + * {prefix: schema.prefix, name: property}, + * {value: object, type: objectType}); + */ - /** - * linetoVerticalRel - v - * - * @param {Number} y - */ - linetoVerticalRel: function(y) { - var pointsRel = this.editPointsRel([0, y]); - - this.d = this.d.concat(" v" + pointsRel[1] + " "); - }, + return DataManager._triples.select(function (triple) { - /** - * closePath - z or Z - */ - closePath: function() { - this.d = this.d.concat(" z"); - } + var select = ((subject) ? + (triple.subject.type == subject.type) && + (triple.subject.value == subject.value) : true); + if (predicate) { + select = select && ((predicate.prefix) ? + (triple.predicate.prefix == predicate.prefix) : true); + select = select && ((predicate.name) ? + (triple.predicate.name == predicate.name) : true); + } + select = select && ((object) ? + (triple.object.type == object.type) && + (triple.object.value == object.value) : true); + return select; + }); + } +} -});/* - * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. - * License rights for this program may be obtained from Alfresco Software, Ltd. - * pursuant to a written agreement and any use of this program without such an - * agreement is prohibited. - */ -/* - * All code Copyright 2013 KIS Consultancy all rights reserved - */ +Kickstart.register(DataManager.init); -/** - * Init namespaces - */ -if(!ORYX) {var ORYX = {};} -if(!ORYX.Core) {ORYX.Core = {};} -if(!ORYX.Core.SVG) {ORYX.Core.SVG = {};} +function assert(expr, m) { + if (!expr) throw m; +}; +function DMCommand(action, triple) { -/** - * MinMaxPathHandler - * - * Determine the minimum and maximum of a SVG path's absolute coordinates. - * For relative coordinates the absolute value is computed for consideration. - * The values are stored in attributes minX, minY, maxX, and maxY. - * - * @constructor - */ -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; - }, + // store action and triple. + this.action = action; + this.triple = triple; - /** - * Store minimal and maximal coordinates of passed points to attributes minX, maxX, minY, maxY - * - * @param {Array} points Array of absolutePoints - */ - calculateMinMax: function(points) { - if(points instanceof Array) { - var x, y; - for(var i = 0; i < points.length; i++) { - x = parseFloat(points[i]); - i++; - y = parseFloat(points[i]); - - this.minX = (this.minX !== undefined) ? Math.min(this.minX, x) : x; - this.maxX = (this.maxX !== undefined) ? Math.max(this.maxX, x) : x; - this.minY = (this.minY !== undefined) ? Math.min(this.minY, y) : y; - this.maxY = (this.maxY !== undefined) ? Math.max(this.maxY, y) : y; - - this._lastAbsX = x; - this._lastAbsY = y; - } - } else { - //TODO error - } - }, + this.toString = function () { + return 'Command(' + action + ', ' + triple + ')'; + }; +} - /** - * arcAbs - A - * - * @param {Number} rx - * @param {Number} ry - * @param {Number} xAxisRotation - * @param {Boolean} largeArcFlag - * @param {Boolean} sweepFlag - * @param {Number} x - * @param {Number} y - */ - arcAbs: function(rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) { - this.calculateMinMax([x, y]); - }, +function DMCommandHandler(nextHandler) { - /** - * arcRel - a - * - * @param {Number} rx - * @param {Number} ry - * @param {Number} xAxisRotation - * @param {Boolean} largeArcFlag - * @param {Boolean} sweepFlag - * @param {Number} x - * @param {Number} y - */ - arcRel: function(rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) { - this.calculateMinMax([this._lastAbsX + x, this._lastAbsY + y]); - }, + /** + * Private method to set the next handler in the Chain of Responsibility + * (see http://en.wikipedia.org/wiki/Chain-of-responsibility_pattern for + * details). + * @param {DMCommandHandler} handler The handler that is next in the chain. + */ + this.__setNext = function (handler) { + var _next = this.__next; + this.__next = nextHandler; + return _next ? _next : true; + }; + this.__setNext(nextHandler); - /** - * curvetoCubicAbs - C - * - * @param {Number} x1 - * @param {Number} y1 - * @param {Number} x2 - * @param {Number} y2 - * @param {Number} x - * @param {Number} y - */ - curvetoCubicAbs: function(x1, y1, x2, y2, x, y) { - this.calculateMinMax([x1, y1, x2, y2, x, y]); - }, + /** + * Invokes the next handler. If there is no next handler, this method + * returns false, otherwise it forwards the result of the handling. + * @param {Object} command The command object to be processed. + */ + this.__invokeNext = function (command) { + return this.__next ? this.__next.handle(command) : false; + }; - /** - * curvetoCubicRel - c - * - * @param {Number} x1 - * @param {Number} y1 - * @param {Number} x2 - * @param {Number} y2 - * @param {Number} x - * @param {Number} y - */ - curvetoCubicRel: function(x1, y1, x2, y2, x, y) { - this.calculateMinMax([this._lastAbsX + x1, this._lastAbsY + y1, - this._lastAbsX + x2, this._lastAbsY + y2, - this._lastAbsX + x, this._lastAbsY + y]); - }, + /** + * Handles a command. The abstract method process() is called with the + * command object that has been passed. If the process method catches the + * command (returns true on completion), the handle() method returns true. + * If the process() method doesn't catch the command, the next handler will + * be invoked. + * @param {Object} command The command object to be processed. + */ + this.handle = function (command) { + return this.process(command) ? true : this.__invokeNext(command); + } - /** - * linetoHorizontalAbs - H - * - * @param {Number} x - */ - linetoHorizontalAbs: function(x) { - this.calculateMinMax([x, this._lastAbsY]); - }, + /** + * Empty process() method returning false. If javascript knew abstract + * class members, this would be one. + * @param {Object} command The command object to process. + */ + this.process = function (command) { + return false; + }; +}; - /** - * linetoHorizontalRel - h - * - * @param {Number} x - */ - linetoHorizontalRel: function(x) { - this.calculateMinMax([this._lastAbsX + x, this._lastAbsY]); - }, +/** + * This Handler manages the addition and the removal of meta elements in the + * head of the document. + * @param {DMCommandHandler} next The handler that is next in the chain. + */ +function MetaTagHandler(next) { - /** - * linetoAbs - L - * - * @param {Number} x - * @param {Number} y - */ - linetoAbs: function(x, y) { - this.calculateMinMax([x, y]); - }, + DMCommandHandler.apply(this, [next]); + this.process = function (command) { - /** - * linetoRel - l - * - * @param {Number} x - * @param {Number} y - */ - linetoRel: function(x, y) { - this.calculateMinMax([this._lastAbsX + x, this._lastAbsY + y]); - }, + with (command.triple) { - /** - * movetoAbs - M - * - * @param {Number} x - * @param {Number} y - */ - movetoAbs: function(x, y) { - this.calculateMinMax([x, y]); - }, + /* assert prerequisites */ + if (!( + (subject instanceof ERDF.Resource) && + (subject.isCurrentDocument()) && + (object instanceof ERDF.Literal) + )) return false; + } - /** - * movetoRel - m - * - * @param {Number} x - * @param {Number} y - */ - movetoRel: function(x, y) { - if(this._lastAbsX && this._lastAbsY) { - this.calculateMinMax([this._lastAbsX + x, this._lastAbsY + y]); - } else { - this.calculateMinMax([x, y]); - } - }, + }; +}; - /** - * curvetoQuadraticAbs - Q - * - * @param {Number} x1 - * @param {Number} y1 - * @param {Number} x - * @param {Number} y - */ - curvetoQuadraticAbs: function(x1, y1, x, y) { - this.calculateMinMax([x1, y1, x, y]); - }, +var chain = new MetaTagHandler(); +var command = new DMCommand(TRIPLE_ADD, new ERDF.Triple( + new ERDF.Resource(''), + 'rdf:tool', + new ERDF.Literal('') +)); - /** - * curvetoQuadraticRel - q - * - * @param {Number} x1 - * @param {Number} y1 - * @param {Number} x - * @param {Number} y - */ - curvetoQuadraticRel: function(x1, y1, x, y) { - this.calculateMinMax([this._lastAbsX + x1, this._lastAbsY + y1, this._lastAbsX + x, this._lastAbsY + y]); - }, +/* +if(chain.handle(command)) + alert('Handled!'); +*/ - /** - * curvetoCubicSmoothAbs - S - * - * @param {Number} x2 - * @param {Number} y2 - * @param {Number} x - * @param {Number} y - */ - curvetoCubicSmoothAbs: function(x2, y2, x, y) { - this.calculateMinMax([x2, y2, x, y]); - }, +ResourceManager = { - /** - * curvetoCubicSmoothRel - s - * - * @param {Number} x2 - * @param {Number} y2 - * @param {Number} x - * @param {Number} y - */ - curvetoCubicSmoothRel: function(x2, y2, x, y) { - this.calculateMinMax([this._lastAbsX + x2, this._lastAbsY + y2, this._lastAbsX + x, this._lastAbsY + y]); - }, + __corrupt: false, + __latelyCreatedResource: undefined, + __listeners: $H(), + __token: 1, - /** - * curvetoQuadraticSmoothAbs - T - * - * @param {Number} x - * @param {Number} y - */ - curvetoQuadraticSmoothAbs: function(x, y) { - this.calculateMinMax([x, y]); - }, + addListener: function (listener, mask) { - /** - * curvetoQuadraticSmoothRel - t - * - * @param {Number} x - * @param {Number} y - */ - curvetoQuadraticSmoothRel: function(x, y) { - this.calculateMinMax([this._lastAbsX + x, this._lastAbsY + y]); - }, + if (!(listener instanceof Function)) + throw 'Resource event listener is not a function!'; + if (!(mask)) + throw 'Invalid mask for resource event listener registration.'; - /** - * linetoVerticalAbs - V - * - * @param {Number} y - */ - linetoVerticalAbs: function(y) { - this.calculateMinMax([this._lastAbsX, y]); - }, + // construct controller and token. + var controller = {listener: listener, mask: mask}; + var token = ResourceManager.__token++; - /** - * linetoVerticalRel - v - * - * @param {Number} y - */ - linetoVerticalRel: function(y) { - this.calculateMinMax([this._lastAbsX, this._lastAbsY + y]); - }, + // add new listener. + ResourceManager.__listeners[token] = controller; - /** - * closePath - z or Z - */ - closePath: function() { - return;// do nothing - } + // return the token generated. + return token; + }, -});/* - * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. - * License rights for this program may be obtained from Alfresco Software, Ltd. - * pursuant to a written agreement and any use of this program without such an - * agreement is prohibited. - */ -/* - * All code Copyright 2013 KIS Consultancy all rights reserved - */ + removeListener: function (token) { -/** - * Init namespaces - */ -if(!ORYX) {var ORYX = {};} -if(!ORYX.Core) {ORYX.Core = {};} -if(!ORYX.Core.SVG) {ORYX.Core.SVG = {};} + // remove the listener with the token and return it. + return ResourceManager.__listners.remove(token); + }, + __Event: function (action, resourceId) { + this.action = action; + this.resourceId = resourceId; + }, -/** - * PathHandler - * - * Determine absolute points of a SVG path. The coordinates are stored - * sequentially in the attribute points (x-coordinates at even indices, - * y-coordinates at odd indices). - * - * @constructor - */ -ORYX.Core.SVG.PointsPathHandler = Clazz.extend({ - - construct: function() { - arguments.callee.$.construct.apply(this, arguments); - - this.points = []; - - this._lastAbsX = undefined; - this._lastAbsY = undefined; - }, - - /** - * addPoints - * - * @param {Array} points Array of absolutePoints - */ - addPoints: function(points) { - if(points instanceof Array) { - var x, y; - for(var i = 0; i < points.length; i++) { - x = parseFloat(points[i]); - i++; - y = parseFloat(points[i]); - - this.points.push(x); - this.points.push(y); - //this.points.push({x:x, y:y}); - - this._lastAbsX = x; - this._lastAbsY = y; - } - } else { - //TODO error - } - }, - - /** - * arcAbs - A - * - * @param {Number} rx - * @param {Number} ry - * @param {Number} xAxisRotation - * @param {Boolean} largeArcFlag - * @param {Boolean} sweepFlag - * @param {Number} x - * @param {Number} y - */ - arcAbs: function(rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) { - this.addPoints([x, y]); - }, + __dispatchEvent: function (event) { - /** - * arcRel - a - * - * @param {Number} rx - * @param {Number} ry - * @param {Number} xAxisRotation - * @param {Boolean} largeArcFlag - * @param {Boolean} sweepFlag - * @param {Number} x - * @param {Number} y - */ - arcRel: function(rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) { - this.addPoints([this._lastAbsX + x, this._lastAbsY + y]); - }, + // get all listeners. for each listener, ... + ResourceManager.__listeners.values().each(function (controller) { - /** - * curvetoCubicAbs - C - * - * @param {Number} x1 - * @param {Number} y1 - * @param {Number} x2 - * @param {Number} y2 - * @param {Number} x - * @param {Number} y - */ - curvetoCubicAbs: function(x1, y1, x2, y2, x, y) { - this.addPoints([x, y]); - }, + // .. if listener subscribed to this type of event ... + if (event.action & controller.mask) + return controller.listener(event); + }); + }, - /** - * curvetoCubicRel - c - * - * @param {Number} x1 - * @param {Number} y1 - * @param {Number} x2 - * @param {Number} y2 - * @param {Number} x - * @param {Number} y - */ - curvetoCubicRel: function(x1, y1, x2, y2, x, y) { - this.addPoints([this._lastAbsX + x, this._lastAbsY + y]); - }, + getResource: function (id) { - /** - * linetoHorizontalAbs - H - * - * @param {Number} x - */ - linetoHorizontalAbs: function(x) { - this.addPoints([x, this._lastAbsY]); - }, + // get all possible resources for this. + id = ERDF.__stripHashes(id); + var resources = DataManager.query( + new ERDF.Resource('#' + id), + {prefix: 'raziel', name: 'entry'}, + undefined + ); - /** - * linetoHorizontalRel - h - * - * @param {Number} x - */ - linetoHorizontalRel: function(x) { - this.addPoints([this._lastAbsX + x, this._lastAbsY]); - }, + // check for consistency. + if ((resources.length == 1) && (resources[0].object.isResource())) { + var entryUrl = resources[0].object.value; + return new ResourceManager.__Resource(id, entryUrl); + } - /** - * linetoAbs - L - * - * @param {Number} x - * @param {Number} y - */ - linetoAbs: function(x, y) { - this.addPoints([x, y]); - }, + // else throw an error message. + throw ('Resource with id ' + id + ' not recognized as such. ' + + ((resources.length > 1) ? + ' There is more than one raziel:entry URL.' : + ' There is no raziel:entry URL.')); - /** - * linetoRel - l - * - * @param {Number} x - * @param {Number} y - */ - linetoRel: function(x, y) { - this.addPoints([this._lastAbsX + x, this._lastAbsY + y]); - }, + return false; + }, - /** - * movetoAbs - M - * - * @param {Number} x - * @param {Number} y - */ - movetoAbs: function(x, y) { - this.addPoints([x, y]); - }, + __createResource: function (alternativeDiv) { - /** - * movetoRel - m - * - * @param {Number} x - * @param {Number} y - */ - movetoRel: function(x, y) { - if(this._lastAbsX && this._lastAbsY) { - this.addPoints([this._lastAbsX + x, this._lastAbsY + y]); - } else { - this.addPoints([x, y]); - } - }, + var collectionUrls = DataManager.query( + new ERDF.Resource(''), + // TODO This will become raziel:collection in near future. + {prefix: 'raziel', name: 'collection'}, + undefined + ); - /** - * curvetoQuadraticAbs - Q - * - * @param {Number} x1 - * @param {Number} y1 - * @param {Number} x - * @param {Number} y - */ - curvetoQuadraticAbs: function(x1, y1, x, y) { - this.addPoints([x, y]); - }, + // check for consistency. - /** - * curvetoQuadraticRel - q - * - * @param {Number} x1 - * @param {Number} y1 - * @param {Number} x - * @param {Number} y - */ - curvetoQuadraticRel: function(x1, y1, x, y) { - this.addPoints([this._lastAbsX + x, this._lastAbsY + y]); - }, + if ((collectionUrls.length == 1) && + (collectionUrls[0].object.isResource())) { - /** - * curvetoCubicSmoothAbs - S - * - * @param {Number} x2 - * @param {Number} y2 - * @param {Number} x - * @param {Number} y - */ - curvetoCubicSmoothAbs: function(x2, y2, x, y) { - this.addPoints([x, y]); - }, + // get the collection url. - /** - * curvetoCubicSmoothRel - s - * - * @param {Number} x2 - * @param {Number} y2 - * @param {Number} x - * @param {Number} y - */ - curvetoCubicSmoothRel: function(x2, y2, x, y) { - this.addPoints([this._lastAbsX + x, this._lastAbsY + y]); - }, + var collectionUrl = collectionUrls[0].object.value; + var resource = undefined; - /** - * curvetoQuadraticSmoothAbs - T - * - * @param {Number} x - * @param {Number} y - */ - curvetoQuadraticSmoothAbs: function(x, y) { - this.addPoints([x, y]); - }, + // if there is an old id, serialize the dummy div from there, + // otherwise create a dummy div on the fly. - /** - * curvetoQuadraticSmoothRel - t - * - * @param {Number} x - * @param {Number} y - */ - curvetoQuadraticSmoothRel: function(x, y) { - this.addPoints([this._lastAbsX + x, this._lastAbsY + y]); - }, + var serialization = alternativeDiv ? alternativeDiv : + '
'; - /** - * linetoVerticalAbs - V - * - * @param {Number} y - */ - linetoVerticalAbs: function(y) { - this.addPoints([this._lastAbsX, y]); - }, + ResourceManager.__request( + 'POST', collectionUrl, serialization, - /** - * linetoVerticalRel - v - * - * @param {Number} y - */ - linetoVerticalRel: function(y) { - this.addPoints([this._lastAbsX, this._lastAbsY + y]); - }, + // on success + function () { - /** - * closePath - z or Z - */ - closePath: function() { - return;// do nothing - } + // get div and id that have been generated by the server. -});/* - * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. - * License rights for this program may be obtained from Alfresco Software, Ltd. - * pursuant to a written agreement and any use of this program without such an - * agreement is prohibited. - */ -/* - * All code Copyright 2013 KIS Consultancy all rights reserved - */ + var response = (this.responseXML); + var div = response.childNodes[0]; + var id = div.getAttribute('id'); -/** - * - * Config variables - */ -NAMESPACE_ORYX = "http://www.b3mn.org/oryx"; -NAMESPACE_SVG = "http://www.w3.org/2000/svg/"; + // store div in DOM + if (!$$('.' + PROCESSDATA_REF)[0]) + DataManager.graft(XMLNS.XHTML, + document.getElementsByTagNameNS(XMLNS.XHTML, 'body').item(0), ['div', { + 'class': PROCESSDATA_REF, + 'style': 'display:none;' + }]); -/** - * @classDescription This class wraps the manipulation of a SVG marker. - * @namespace ORYX.Core.SVG - * uses Inheritance (Clazz) - * uses Prototype 1.5.0 - * - */ + $$('.' + PROCESSDATA_REF)[0].appendChild(div.cloneNode(true)); -/** - * Init package - */ -if(!ORYX) {var ORYX = {};} -if(!ORYX.Core) {ORYX.Core = {};} -if(!ORYX.Core.SVG) {ORYX.Core.SVG = {};} + // parse local erdf data once more. -ORYX.Core.SVG.SVGMarker = Clazz.extend({ + DataManager.__synclocal(); - /** - * Constructor - * @param markerElement {SVGMarkerElement} - */ - construct: function(markerElement) { - arguments.callee.$.construct.apply(this, arguments); - - this.id = undefined; - this.element = markerElement; - 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(); //initialisation of all the properties declared above. - }, + // get new resource object. - /** - * Initializes the values that are defined in the constructor. - */ - _init: function() { - //check if this.element is a SVGMarkerElement - if(!( this.element == "[object SVGMarkerElement]")) { - throw "SVGMarker: Argument is not an instance of SVGMarkerElement."; - } + resource = new ResourceManager.getResource(id); - this.id = this.element.getAttributeNS(null, "id"); - - //init svg marker attributes - var refXValue = this.element.getAttributeNS(null, "refX"); - if(refXValue) { - this.refX = parseFloat(refXValue); - } else { - this.refX = 0; - } - var refYValue = this.element.getAttributeNS(null, "refY"); - if(refYValue) { - this.refY = parseFloat(refYValue); - } else { - this.refY = 0; - } - var markerWidthValue = this.element.getAttributeNS(null, "markerWidth"); - if(markerWidthValue) { - this.markerWidth = parseFloat(markerWidthValue); - } else { - this.markerWidth = 3; - } - var markerHeightValue = this.element.getAttributeNS(null, "markerHeight"); - if(markerHeightValue) { - this.markerHeight = parseFloat(markerHeightValue); - } else { - this.markerHeight = 3; - } + // set up an action informing of the creation. - this.oldRefX = this.refX; - this.oldRefY = this.refY; - this.oldMarkerWidth = this.markerWidth; - this.oldMarkerHeight = this.markerHeight; + ResourceManager.__resourceActionSucceeded( + this, RESOURCE_CREATED, undefined); + }, - //init oryx attributes - var optionalAttr = this.element.getAttributeNS(NAMESPACE_ORYX, "optional"); - if(optionalAttr) { - optionalAttr = optionalAttr.strip(); - this.optional = (optionalAttr.toLowerCase() === "yes"); - } else { - this.optional = false; - } + function () { + ResourceManager.__resourceActionFailed( + this, RESOURCE_CREATED, undefined); + }, + false + ); - var enabledAttr = this.element.getAttributeNS(NAMESPACE_ORYX, "enabled"); - if(enabledAttr) { - enabledAttr = enabledAttr.strip(); - this.enabled = !(enabledAttr.toLowerCase() === "no"); - } else { - this.enabled = true; - } + return resource; + } - var minLengthAttr = this.element.getAttributeNS(NAMESPACE_ORYX, "minimumLength"); - if(minLengthAttr) { - this.minimumLength = parseFloat(minLengthAttr); - } + // else + throw 'Could not create resource! raziel:collection URL is missing!'; + return false; - var resizeAttr = this.element.getAttributeNS(NAMESPACE_ORYX, "resize"); - if(resizeAttr) { - resizeAttr = resizeAttr.strip(); - this.resize = (resizeAttr.toLowerCase() === "yes"); - } else { - this.resize = false; - } + }, - //init SVGShape objects - //this.svgShapes = this._getSVGShapes(this.element); - }, + __Resource: function (id, url) { - /** - * - */ - _getSVGShapes: function(svgElement) { - if(svgElement.hasChildNodes) { - var svgShapes = []; - var me = this; - $A(svgElement.childNodes).each(function(svgChild) { - try { - var svgShape = new ORYX.Core.SVG.SVGShape(svgChild); - svgShapes.push(svgShape); - } catch (e) { - svgShapes = svgShapes.concat(me._getSVGShapes(svgChild)); - } - }); - return svgShapes; - } - }, + this.__id = id; + this.__url = url; - /** - * Writes the changed values into the SVG marker. - */ - update: function() { - //TODO mache marker resizebar!!! aber erst wenn der rest der connectingshape funzt! + /* + * Process URL is no longer needed to refer to the shape element on the + * canvas. AReSS uses the id's to gather information on fireing + * behaviour now. + */ -// //update marker attributes -// if(this.refX != this.oldRefX) { -// this.element.setAttributeNS(null, "refX", this.refX); -// } -// if(this.refY != this.oldRefY) { -// this.element.setAttributeNS(null, "refY", this.refY); -// } -// if(this.markerWidth != this.oldMarkerWidth) { -// this.element.setAttributeNS(null, "markerWidth", this.markerWidth); -// } -// if(this.markerHeight != this.oldMarkerHeight) { -// this.element.setAttributeNS(null, "markerHeight", this.markerHeight); -// } +// // find the process url. +// var processUrl = undefined; // -// //update SVGShape objects -// var widthDelta = this.markerWidth / this.oldMarkerWidth; -// var heightDelta = this.markerHeight / this.oldMarkerHeight; -// if(widthDelta != 1 && heightDelta != 1) { -// this.svgShapes.each(function(svgShape) { +// var urls = DataManager.query( +// new ERDF.Resource('#'+this.__id), +// {prefix: 'raziel', name: 'process'}, +// undefined +// ); // -// }); +// if(urls.length == 0) { throw 'The resource with the id ' +id+ ' has no process url.'}; +// +// urls.each( function(triple) { +// +// // if there are more urls, use the last one. +// processUrl = triple.object.value; +// }); +// +// this.__processUrl = processUrl; +// +// // convenience function for getting the process url. +// this.processUrl = function() { +// return this.__processUrl; // } - //update old values to prepare the next update - 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;} - });/* + + // convenience finction for getting the id. + this.id = function () { + return this.__id; + } + + // convenience finction for getting the entry url. + this.url = function () { + return this.__url; + } + + this.reload = function () { + var _url = this.__url; + var _id = this.__id; + ResourceManager.__request( + 'GET', _url, null, + function () { + ResourceManager.__resourceActionSucceeded( + this, RESOURCE_RELOADED, _id); + }, + function () { + ResourceManager.__resourceActionFailed( + this, RESURCE_RELOADED, _id); + }, + USE_ASYNCHRONOUS_REQUESTS + ); + }; + + this.save = function (synchronize) { + var _url = this.__url; + var _id = this.__id; + data = DataManager.serialize($(_id)); + ResourceManager.__request( + 'PUT', _url, data, + function () { + ResourceManager.__resourceActionSucceeded( + this, synchronize ? RESOURCE_SAVED | RESOURCE_SYNCHRONIZED : RESOURCE_SAVED, _id); + }, + function () { + ResourceManager.__resourceActionFailed( + this, synchronize ? RESOURCE_SAVED | RESOURCE_SYNCHRONIZED : RESOURCE.SAVED, _id); + }, + USE_ASYNCHRONOUS_REQUESTS + ); + }; + + this.remove = function () { + var _url = this.__url; + var _id = this.__id; + ResourceManager.__request( + 'DELETE', _url, null, + function () { + ResourceManager.__resourceActionSucceeded( + this, RESOURCE_REMOVED, _id); + }, + function () { + ResourceManager.__resourceActionFailed( + this, RESOURCE_REMOVED, _id); + }, + USE_ASYNCHRONOUS_REQUESTS + ); + }; + }, + + request: function (url, requestOptions) { + + var options = { + method: 'get', + asynchronous: true, + parameters: {} + }; + + Object.extend(options, requestOptions || {}); + + var params = Hash.toQueryString(options.parameters); + if (params) + url += (url.include('?') ? '&' : '?') + params; + + return ResourceManager.__request( + options.method, + url, + options.data, + (options.onSuccess instanceof Function ? function () { + options.onSuccess(this); + } : undefined), + (options.onFailure instanceof Function ? function () { + options.onFailure(this); + } : undefined), + options.asynchronous && USE_ASYNCHRONOUS_REQUESTS, + options.headers); + }, + + __request: function (method, url, data, success, error, async, headers) { + + // get a request object + var httpRequest = Try.these( + /* do the Mozilla/Safari/Opera stuff */ + function () { + return new XMLHttpRequest(); + }, + + /* do the IE stuff */ + function () { + return new ActiveXObject("Msxml2.XMLHTTP"); + }, + function () { + return new ActiveXObject("Microsoft.XMLHTTP") + } + ); + + // if there is no request object ... + if (!httpRequest) { + 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 (success instanceof Function) + httpRequest.onload = success; + if (error instanceof Function) { + httpRequest.onerror = error; + } + + var h = $H(headers) + h.keys().each(function (key) { + + httpRequest.setRequestHeader(key, h[key]); + }); + + try { + + if (SHOW_DEBUG_ALERTS_WHEN_SAVING) + + alert(method + ' ' + url + '\n' + + SHOW_EXTENDED_DEBUG_INFORMATION ? data : ''); + + // TODO Remove synchronous calls to the server as soon as xenodot + // handles asynchronous requests without failure. + httpRequest.open(method, url, !async ? false : true); + httpRequest.send(data); + + } catch (e) { + return false; + } + return true; + }, + + __resourceActionSucceeded: function (transport, action, id) { + + var status = transport.status; + var response = transport.responseText; + + if (SHOW_DEBUG_ALERTS_WHEN_SAVING) + + alert(status + ' ' + url + '\n' + + SHOW_EXTENDED_DEBUG_INFORMATION ? data : ''); + + // if the status code is not in 2xx, throw an error. + if (status >= 300) + throw '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.'); + + switch (action) { + + case RESOURCE_REMOVED: + + // get div and id + var response = (transport.responseXML); + var div = response.childNodes[0]; + var id = div.getAttribute('id'); + + // remove the resource from DOM + var localDiv = document.getElementById(id); + localDiv.parentNode.removeChild(localDiv); + break; + + case RESOURCE_CREATED: + + // nothing remains to be done. + break; + + case RESOURCE_SAVED | RESOURCE_SYNCHRONIZED: + + DataManager.__synclocal(); + + case RESOURCE_SAVED: + + // nothing remains to be done. + break; + + case RESOURCE_RELOADED: + + // get div and id + var response = (transport.responseXML); + var div = response.childNodes[0]; + var id = div.getAttribute('id'); + + // remove the local resource representation from DOM + var localDiv = document.getElementById(id) + localDiv.parentNode.removeChild(localDiv); + + // store div in DOM + 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(div.cloneNode(true)); + DataManager.__synclocal(); + break; + + default: + DataManager.__synclocal(); + + } + + // dispatch to all listeners ... + ResourceManager.__dispatchEvent( + // ... an event describing the change that happened here. + new ResourceManager.__Event(action, id) + ); + }, + + __resourceActionFailed: function (transport, action, id) { + 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?"; + } +}/* * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. * License rights for this program may be obtained from Alfresco Software, Ltd. * pursuant to a written agreement and any use of this program without such an @@ -3548,3052 +1764,1122 @@ ORYX.Core.SVG.SVGMarker = Clazz.extend({ */ /** - * - * Config variables + * The super class for all classes in ORYX. Adds some OOP feeling to javascript. + * See article "Object Oriented Super Class Method Calling with JavaScript" on + * http://truecode.blogspot.com/2006/08/object-oriented-super-class-method.html + * for a documentation on this. Fairly good article that points out errors in + * Douglas Crockford's inheritance and super method calling approach. + * Worth reading. + * @class Clazz */ -NAMESPACE_ORYX = "http://www.b3mn.org/oryx"; -NAMESPACE_SVG = "http://www.w3.org/2000/svg/"; +var Clazz = function () { +}; /** - * @classDescription This class wraps the manipulation of a SVG basic shape or a path. - * @namespace ORYX.Core.SVG - * uses Inheritance (Clazz) - * uses Prototype 1.5.0 - * uses PathParser by Kevin Lindsey (http://kevlindev.com/) - * uses MinMaxPathHandler - * uses EditPathHandler - * + * Empty constructor. + * @methodOf Clazz.prototype */ +Clazz.prototype.construct = function () { +}; -//init package -if(!ORYX) {var ORYX = {};} -if(!ORYX.Core) {ORYX.Core = {};} -if(!ORYX.Core.SVG) {ORYX.Core.SVG = {};} - -ORYX.Core.SVG.SVGShape = Clazz.extend({ - - /** - * Constructor - * @param svgElem {SVGElement} An SVGElement that is a basic shape or a path. - */ - construct: function(svgElem) { - arguments.callee.$.construct.apply(this, arguments); - - this.type; - this.element = svgElem; - 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.anchors = []; - this.anchorLeft = false; - this.anchorRight = false; - this.anchorTop = false; - this.anchorBottom = false; - - //attributes of path elements of edge objects - this.allowDockers = true; - this.resizeMarkerMid = false; - - this.editPathParser; - this.editPathHandler; - - this.init(); //initialisation of all the properties declared above. - }, - - /** - * Initializes the values that are defined in the constructor. - */ - init: function() { - - /**initialize position and size*/ - if(ORYX.Editor.checkClassType(this.element, SVGRectElement) || ORYX.Editor.checkClassType(this.element, SVGImageElement)) { - this.type = "Rect"; - - var xAttr = this.element.getAttributeNS(null, "x"); - if(xAttr) { - this.oldX = parseFloat(xAttr); - } else { - throw "Missing attribute in element " + this.element; - } - var yAttr = this.element.getAttributeNS(null, "y"); - if(yAttr) { - this.oldY = parseFloat(yAttr); - } else { - throw "Missing attribute in element " + this.element; - } - var widthAttr = this.element.getAttributeNS(null, "width"); - if(widthAttr) { - this.oldWidth = parseFloat(widthAttr); - } else { - throw "Missing attribute in element " + this.element; - } - var heightAttr = this.element.getAttributeNS(null, "height"); - if(heightAttr) { - this.oldHeight = parseFloat(heightAttr); - } else { - throw "Missing attribute in element " + this.element; - } +/** + * Can be used to build up inheritances of classes. + * @example + * var MyClass = Clazz.extend({ + * construct: function(myParam){ + * // Do sth. + * } + * }); + * var MySubClass = MyClass.extend({ + * construct: function(myParam){ + * // Use this to call constructor of super class + * arguments.callee.$.construct.apply(this, arguments); + * // Do sth. + * } + * }); + * @param {Object} def The definition of the new class. + */ +Clazz.extend = function (def) { + var classDef = function () { + if (arguments[0] !== Clazz) { + this.construct.apply(this, arguments); + } + }; - } else if(ORYX.Editor.checkClassType(this.element, SVGCircleElement)) { - this.type = "Circle"; - - var cx = undefined; - var cy = undefined; - //var r = undefined; + var proto = new this(Clazz); + var superClass = this.prototype; - var cxAttr = this.element.getAttributeNS(null, "cx"); - if(cxAttr) { - cx = parseFloat(cxAttr); - } else { - throw "Missing attribute in element " + this.element; - } - var cyAttr = this.element.getAttributeNS(null, "cy"); - if(cyAttr) { - cy = parseFloat(cyAttr); - } else { - throw "Missing attribute in element " + this.element; - } - var rAttr = this.element.getAttributeNS(null, "r"); - if(rAttr) { - //r = parseFloat(rAttr); - this.radiusX = parseFloat(rAttr); - } else { - throw "Missing attribute in element " + this.element; - } - this.oldX = cx - this.radiusX; - this.oldY = cy - this.radiusX; - this.oldWidth = 2*this.radiusX; - this.oldHeight = 2*this.radiusX; - - } else if(ORYX.Editor.checkClassType(this.element, SVGEllipseElement)) { - this.type = "Ellipse"; - - var cx = undefined; - var cy = undefined; - //var rx = undefined; - //var ry = undefined; - var cxAttr = this.element.getAttributeNS(null, "cx"); - if(cxAttr) { - cx = parseFloat(cxAttr); - } else { - throw "Missing attribute in element " + this.element; - } - var cyAttr = this.element.getAttributeNS(null, "cy"); - if(cyAttr) { - cy = parseFloat(cyAttr); - } else { - throw "Missing attribute in element " + this.element; - } - var rxAttr = this.element.getAttributeNS(null, "rx"); - if(rxAttr) { - this.radiusX = parseFloat(rxAttr); - } else { - throw "Missing attribute in element " + this.element; - } - var ryAttr = this.element.getAttributeNS(null, "ry"); - if(ryAttr) { - this.radiusY = parseFloat(ryAttr); - } else { - throw "Missing attribute in element " + this.element; - } - this.oldX = cx - this.radiusX; - this.oldY = cy - this.radiusY; - this.oldWidth = 2*this.radiusX; - this.oldHeight = 2*this.radiusY; - - } else if(ORYX.Editor.checkClassType(this.element, SVGLineElement)) { - this.type = "Line"; - - var x1 = undefined; - var y1 = undefined; - var x2 = undefined; - var y2 = undefined; - var x1Attr = this.element.getAttributeNS(null, "x1"); - if(x1Attr) { - x1 = parseFloat(x1Attr); - } else { - throw "Missing attribute in element " + this.element; - } - var y1Attr = this.element.getAttributeNS(null, "y1"); - if(y1Attr) { - y1 = parseFloat(y1Attr); - } else { - throw "Missing attribute in element " + this.element; - } - var x2Attr = this.element.getAttributeNS(null, "x2"); - if(x2Attr) { - x2 = parseFloat(x2Attr); - } else { - throw "Missing attribute in element " + this.element; - } - var y2Attr = this.element.getAttributeNS(null, "y2"); - if(y2Attr) { - y2 = parseFloat(y2Attr); - } else { - throw "Missing attribute in element " + this.element; - } - this.oldX = Math.min(x1,x2); - this.oldY = Math.min(y1,y2); - this.oldWidth = Math.abs(x1-x2); - this.oldHeight = Math.abs(y1-y2); - - } else if(ORYX.Editor.checkClassType(this.element, SVGPolylineElement) || ORYX.Editor.checkClassType(this.element, SVGPolygonElement)) { - this.type = "Polyline"; - - var pointsArray = []; - if (this.element.points&&this.element.points.numberOfItems){ - for(var i=0, size=this.element.points.numberOfItems; i 1) { - var minX = parseFloat(pointsArray[0]); - var minY = parseFloat(pointsArray[1]); - var maxX = parseFloat(pointsArray[0]); - var maxY = parseFloat(pointsArray[1]); - - for(var i = 0; i < pointsArray.length; i++) { - minX = Math.min(minX, parseFloat(pointsArray[i])); - maxX = Math.max(maxX, parseFloat(pointsArray[i])); - i++; - minY = Math.min(minY, parseFloat(pointsArray[i])); - maxY = Math.max(maxY, parseFloat(pointsArray[i])); - } - - this.oldX = minX; - this.oldY = minY; - this.oldWidth = maxX-minX; - this.oldHeight = maxY-minY; - } else { - throw "Missing attribute in element " + this.element; - } + for (var n in def) { + var item = def[n]; + if (item instanceof Function) item.$ = superClass; + proto[n] = item; + } - } 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 parser = new PathParser(); - var handler = new ORYX.Core.SVG.MinMaxPathHandler(); - parser.setHandler(handler); - parser.parsePath(this.element); - - this.oldX = handler.minX; - this.oldY = handler.minY; - this.oldWidth = handler.maxX - handler.minX; - this.oldHeight = handler.maxY - handler.minY; - - delete parser; - delete handler; - } else { - throw "Element is not a shape."; - } + classDef.prototype = proto; - /** initialize attributes of oryx namespace */ - //resize - var resizeAttr = this.element.getAttributeNS(NAMESPACE_ORYX, "resize"); - if(resizeAttr) { - resizeAttr = resizeAttr.toLowerCase(); - if(resizeAttr.match(/horizontal/)) { - this.isHorizontallyResizable = true; - } else { - this.isHorizontallyResizable = false; - } - if(resizeAttr.match(/vertical/)) { - this.isVerticallyResizable = true; - } else { - this.isVerticallyResizable = false; - } - } else { - this.isHorizontallyResizable = false; - this.isVerticallyResizable = false; - } + //Give this new class the same static extend method + classDef.extend = this.extend; + return classDef; +};/* + * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +/* + * All code Copyright 2013 KIS Consultancy all rights reserved + */ - //anchors - var anchorAttr = this.element.getAttributeNS(NAMESPACE_ORYX, "anchors"); - if(anchorAttr) { - anchorAttr = anchorAttr.replace("/,/g", " "); - var anchors = anchorAttr.split(" ").without(""); - - for(var i = 0; i < anchors.length; i++) { - switch(anchors[i].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; - } - } - } - - //allowDockers and resizeMarkerMid - if(ORYX.Editor.checkClassType(this.element, SVGPathElement)) { - var allowDockersAttr = this.element.getAttributeNS(NAMESPACE_ORYX, "allowDockers"); - if(allowDockersAttr) { - if(allowDockersAttr.toLowerCase() === "no") { - this.allowDockers = false; - } else { - this.allowDockers = true; - } - } - - var resizeMarkerMidAttr = this.element.getAttributeNS(NAMESPACE_ORYX, "resizeMarker-mid"); - if(resizeMarkerMidAttr) { - if(resizeMarkerMidAttr.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; - }, +if (!ORYX) var ORYX = {}; - /** - * Writes the changed values into the SVG element. - */ - 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": - //calculate the radius - //var r; -// if(this.width/this.oldWidth <= this.height/this.oldHeight) { -// this.radiusX = ((this.width > this.height) ? this.width : this.height)/2.0; -// } else { - this.radiusX = ((this.width < this.height) ? this.width : this.height)/2.0; - //} - - this.element.setAttributeNS(null, "cx", this.x + this.width/2.0); - this.element.setAttributeNS(null, "cy", this.y + this.height/2.0); - 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 points = this.element.getAttributeNS(null, "points"); - if(points) { - points = points.replace(/,/g, " ").split(" ").without(""); - - if(points && points.length && points.length > 1) { - - //TODO what if oldWidth == 0? - var widthDelta = (this.oldWidth === 0) ? 0 : this.width / this.oldWidth; - var heightDelta = (this.oldHeight === 0) ? 0 : this.height / this.oldHeight; - - var updatedPoints = ""; - for(var i = 0; i < points.length; i++) { - var x = (parseFloat(points[i])-this.oldX)*widthDelta + this.x; - i++; - var y = (parseFloat(points[i])-this.oldY)*heightDelta + this.y; - updatedPoints += x + " " + y + " "; - } - this.element.setAttributeNS(null, "points", updatedPoints); - } else { - //TODO error - } - } else { - //TODO error - } - break; - case "Path": - //calculate scaling delta - //TODO what if oldWidth == 0? - var widthDelta = (this.oldWidth === 0) ? 0 : this.width / this.oldWidth; - var heightDelta = (this.oldHeight === 0) ? 0 : this.height / this.oldHeight; - - //use path parser to edit each point of the path - this.editPathHandler.init(this.x, this.y, this.oldX, this.oldY, widthDelta, heightDelta); - this.editPathParser.parsePath(this.element); - - //change d attribute of path - this.element.setAttributeNS(null, "d", this.editPathHandler.d); - break; - } +if (!ORYX.CONFIG) ORYX.CONFIG = {}; - this.oldX = this.x; - this.oldY = this.y; - this.oldWidth = this.width; - this.oldHeight = this.height; - } - - // Remove cached variables - delete this.visible; - delete this.handler; - }, - - isPointIncluded: function(pointX, pointY) { +/** + * This file contains URI constants that may be used for XMLHTTPRequests. + */ - // Check if there are the right arguments and if the node is visible - if(!pointX || !pointY || !this.isVisible()) { - return false; - } +ORYX.CONFIG.ROOT_PATH = "../../editor/"; //TODO: Remove last slash!! +ORYX.CONFIG.EXPLORER_PATH = "explorer"; +ORYX.CONFIG.LIBS_PATH = "libs"; - switch(this.type) { - case "Rect": - return (pointX >= this.x && pointX <= this.x + this.width && - pointY >= this.y && pointY <= this.y+this.height); - break; - case "Circle": - //calculate the radius -// var r; -// if(this.width/this.oldWidth <= this.height/this.oldHeight) { -// r = ((this.width > this.height) ? this.width : this.height)/2.0; -// } else { -// r = ((this.width < this.height) ? this.width : this.height)/2.0; -// } - return ORYX.Core.Math.isPointInEllipse(pointX, pointY, this.x + this.width/2.0, this.y + this.height/2.0, this.radiusX, this.radiusX); - break; - case "Ellipse": - return ORYX.Core.Math.isPointInEllipse(pointX, pointY, this.x + this.radiusX, this.y + this.radiusY, this.radiusX, this.radiusY); - break; - case "Line": - return ORYX.Core.Math.isPointInLine(pointX, pointY, this.x, this.y, this.x + this.width, this.y + this.height); - break; - case "Polyline": - var points = this.element.getAttributeNS(null, "points"); - - if(points) { - points = points.replace(/,/g , " ").split(" ").without(""); - - points = points.collect(function(n) { - return parseFloat(n); - }); - - return ORYX.Core.Math.isPointInPolygone(pointX, pointY, points); - } else { - return false; - } - break; - case "Path": - - // Cache Path handler - if (!this.handler) { - var parser = new PathParser(); - this.handler = new ORYX.Core.SVG.PointsPathHandler(); - parser.setHandler(this.handler); - parser.parsePath(this.element); - } - - return ORYX.Core.Math.isPointInPolygone(pointX, pointY, this.handler.points); - - break; - default: - return false; - } - }, +/** + * Regular Config + */ +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";/* + * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +/* + * All code Copyright 2013 KIS Consultancy all rights reserved + */ - /** - * Returns true if the element is visible - * @param {SVGElement} elem - * @return boolean - */ - isVisible: function(elem) { - - if (this.visible !== undefined){ - return this.visible; - } - - if (!elem) { - elem = this.element; - } +if (!ORYX) var ORYX = {}; - var hasOwnerSVG = false; - try { - hasOwnerSVG = !!elem.ownerSVGElement; - } catch(e){} - - // Is SVG context - if ( hasOwnerSVG ) { - // IF G-Element - if (ORYX.Editor.checkClassType(elem, SVGGElement)) { - if (elem.className && elem.className.baseVal == "me") { - this.visible = true; - return this.visible; - } - } +if (!ORYX.CONFIG) ORYX.CONFIG = {}; - // Check if fill or stroke is set - var fill = elem.getAttributeNS(null, "fill"); - var stroke = elem.getAttributeNS(null, "stroke"); - if (fill && fill == "none" && stroke && stroke == "none") { - this.visible = false; - } else { - // Check if displayed - var attr = elem.getAttributeNS(null, "display"); - if(!attr) - this.visible = this.isVisible(elem.parentNode); - else if (attr == "none") - this.visible = false; - else - this.visible = true; - } - } else { - this.visible = true; - } - - return this.visible; - }, +/** + * Signavio specific variables + */ +ORYX.CONFIG.BACKEND_SWITCH = true; +ORYX.CONFIG.PANEL_LEFT_WIDTH = 250; +ORYX.CONFIG.PANEL_RIGHT_COLLAPSED = true; +ORYX.CONFIG.PANEL_RIGHT_WIDTH = 300; +ORYX.CONFIG.APPNAME = 'KISBPM'; +ORYX.CONFIG.WEB_URL = "."; - toString: function() { return (this.element) ? "SVGShape " + this.element.id : "SVGShape " + this.element;} - });/* +ORYX.CONFIG.BLANK_IMAGE = ORYX.CONFIG.LIBS_PATH + '/ext-2.0.2/resources/images/default/s.gif'; + +/* Specify offset of header */ +ORYX.CONFIG.OFFSET_HEADER = 61; + +/* Show grid line while dragging */ +ORYX.CONFIG.SHOW_GRIDLINE = true; + +/* Editor-Mode */ +ORYX.CONFIG.MODE_READONLY = "readonly"; +ORYX.CONFIG.MODE_FULLSCREEN = "fullscreen"; +ORYX.CONFIG.WINDOW_HEIGHT = 800; +ORYX.CONFIG.PREVENT_LOADINGMASK_AT_READY = false; + +/* Plugins */ +ORYX.CONFIG.PLUGINS_ENABLED = true; +ORYX.CONFIG.PLUGINS_FOLDER = "Plugins/"; + +ORYX.CONFIG.BPMN20_SCHEMA_VALIDATION_ON = true; + +/* Namespaces */ +ORYX.CONFIG.NAMESPACE_ORYX = "http://www.b3mn.org/oryx"; +ORYX.CONFIG.NAMESPACE_SVG = "http://www.w3.org/2000/svg"; + +/* UI */ +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; // Updated so the form editor shows all elements at once + +ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET_CORNER = 30; +ORYX.CONFIG.SHAPEMENU_CREATE_OFFSET = 45; + +/* Shape-Menu Align */ +ORYX.CONFIG.SHAPEMENU_RIGHT = "Oryx_Right"; +ORYX.CONFIG.SHAPEMENU_BOTTOM = "Oryx_Bottom"; +ORYX.CONFIG.SHAPEMENU_LEFT = "Oryx_Left"; +ORYX.CONFIG.SHAPEMENU_TOP = "Oryx_Top"; + + +/* Morph-Menu Item */ +ORYX.CONFIG.MORPHITEM_DISABLED = "Oryx_MorphItem_disabled"; + +/* Property type names */ +ORYX.CONFIG.TYPE_STRING = "string"; +ORYX.CONFIG.TYPE_BOOLEAN = "boolean"; +ORYX.CONFIG.TYPE_INTEGER = "integer"; +ORYX.CONFIG.TYPE_FLOAT = "float"; +ORYX.CONFIG.TYPE_COLOR = "color"; +ORYX.CONFIG.TYPE_DATE = "date"; +ORYX.CONFIG.TYPE_CHOICE = "choice"; +ORYX.CONFIG.TYPE_URL = "url"; +ORYX.CONFIG.TYPE_DIAGRAM_LINK = "diagramlink"; +ORYX.CONFIG.TYPE_COMPLEX = "complex"; +ORYX.CONFIG.TYPE_MULTIPLECOMPLEX = "multiplecomplex"; +ORYX.CONFIG.TYPE_TEXT = "text"; +ORYX.CONFIG.TYPE_KISBPM_MULTIINSTANCE = "kisbpm-multiinstance"; +ORYX.CONFIG.TYPE_MODEL_LINK = "modellink"; +ORYX.CONFIG.TYPE_FORM_FLOW_LINK = "formflowlink"; +ORYX.CONFIG.TYPE_FORM_LINK = "formlink"; +ORYX.CONFIG.TYPE_SUB_PROCESS_LINK = "subprocesslink"; +ORYX.CONFIG.TYPE_SERVICE_LINK = "servicelink"; +ORYX.CONFIG.TYPE_CONDITIONS = "conditions"; +ORYX.CONFIG.TYPE_VARIABLES = "variables"; +ORYX.CONFIG.TYPE_LISTENER = "listener"; +ORYX.CONFIG.TYPE_EPC_FREQ = "epcfrequency"; +ORYX.CONFIG.TYPE_GLOSSARY_LINK = "glossarylink"; +ORYX.CONFIG.TYPE_EXPRESSION = "expression"; +ORYX.CONFIG.TYPE_DATASOURCE = "datasource"; +ORYX.CONFIG.TYPE_DATASOURCE_MINIMAL = "datasource-minimal"; +ORYX.CONFIG.TYPE_VALIDATORS = "validators"; + + +/* Vertical line distance of multiline labels */ +ORYX.CONFIG.LABEL_LINE_DISTANCE = 2; +ORYX.CONFIG.LABEL_DEFAULT_LINE_HEIGHT = 12; + +/* Open Morph Menu with Hover */ +ORYX.CONFIG.ENABLE_MORPHMENU_BY_HOVER = false; + + +/* Editor constants come here */ +ORYX.CONFIG.EDITOR_ALIGN_BOTTOM = 0x01; +ORYX.CONFIG.EDITOR_ALIGN_MIDDLE = 0x02; +ORYX.CONFIG.EDITOR_ALIGN_TOP = 0x04; +ORYX.CONFIG.EDITOR_ALIGN_LEFT = 0x08; +ORYX.CONFIG.EDITOR_ALIGN_CENTER = 0x10; +ORYX.CONFIG.EDITOR_ALIGN_RIGHT = 0x20; +ORYX.CONFIG.EDITOR_ALIGN_SIZE = 0x30; + +/* Event types */ +ORYX.CONFIG.EVENT_MOUSEDOWN = "mousedown"; +ORYX.CONFIG.EVENT_MOUSEUP = "mouseup"; +ORYX.CONFIG.EVENT_MOUSEOVER = "mouseover"; +ORYX.CONFIG.EVENT_MOUSEOUT = "mouseout"; +ORYX.CONFIG.EVENT_MOUSEMOVE = "mousemove"; +ORYX.CONFIG.EVENT_DBLCLICK = "dblclick"; +ORYX.CONFIG.EVENT_KEYDOWN = "keydown"; +ORYX.CONFIG.EVENT_KEYUP = "keyup"; + +ORYX.CONFIG.EVENT_LOADED = "editorloaded"; +ORYX.CONFIG.EVENT_SAVED = "editorSaved"; + +ORYX.CONFIG.EVENT_EXECUTE_COMMANDS = "executeCommands"; +ORYX.CONFIG.EVENT_STENCIL_SET_LOADED = "stencilSetLoaded"; +ORYX.CONFIG.EVENT_SELECTION_CHANGED = "selectionchanged"; +ORYX.CONFIG.EVENT_SHAPEADDED = "shapeadded"; +ORYX.CONFIG.EVENT_SHAPEREMOVED = "shaperemoved"; +ORYX.CONFIG.EVENT_PROPERTY_CHANGED = "propertyChanged"; +ORYX.CONFIG.EVENT_DRAGDROP_START = "dragdrop.start"; +ORYX.CONFIG.EVENT_SHAPE_MENU_CLOSE = "shape.menu.close"; +ORYX.CONFIG.EVENT_DRAGDROP_END = "dragdrop.end"; +ORYX.CONFIG.EVENT_RESIZE_START = "resize.start"; +ORYX.CONFIG.EVENT_RESIZE_END = "resize.end"; +ORYX.CONFIG.EVENT_DRAGDOCKER_DOCKED = "dragDocker.docked"; +ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW = "highlight.showHighlight"; +ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE = "highlight.hideHighlight"; +ORYX.CONFIG.EVENT_LOADING_ENABLE = "loading.enable"; +ORYX.CONFIG.EVENT_LOADING_DISABLE = "loading.disable"; +ORYX.CONFIG.EVENT_LOADING_STATUS = "loading.status"; +ORYX.CONFIG.EVENT_OVERLAY_SHOW = "overlay.show"; +ORYX.CONFIG.EVENT_OVERLAY_HIDE = "overlay.hide"; +ORYX.CONFIG.EVENT_ARRANGEMENT_TOP = "arrangement.setToTop"; +ORYX.CONFIG.EVENT_ARRANGEMENT_BACK = "arrangement.setToBack"; +ORYX.CONFIG.EVENT_ARRANGEMENT_FORWARD = "arrangement.setForward"; +ORYX.CONFIG.EVENT_ARRANGEMENT_BACKWARD = "arrangement.setBackward"; +ORYX.CONFIG.EVENT_PROPWINDOW_PROP_CHANGED = "propertyWindow.propertyChanged"; +ORYX.CONFIG.EVENT_LAYOUT_ROWS = "layout.rows"; +ORYX.CONFIG.EVENT_LAYOUT_BPEL = "layout.BPEL"; +ORYX.CONFIG.EVENT_LAYOUT_BPEL_VERTICAL = "layout.BPEL.vertical"; +ORYX.CONFIG.EVENT_LAYOUT_BPEL_HORIZONTAL = "layout.BPEL.horizontal"; +ORYX.CONFIG.EVENT_LAYOUT_BPEL_SINGLECHILD = "layout.BPEL.singlechild"; +ORYX.CONFIG.EVENT_LAYOUT_BPEL_AUTORESIZE = "layout.BPEL.autoresize"; +ORYX.CONFIG.EVENT_AUTOLAYOUT_LAYOUT = "autolayout.layout"; +ORYX.CONFIG.EVENT_UNDO_EXECUTE = "undo.execute"; +ORYX.CONFIG.EVENT_UNDO_ROLLBACK = "undo.rollback"; +ORYX.CONFIG.EVENT_BUTTON_UPDATE = "toolbar.button.update"; +ORYX.CONFIG.EVENT_LAYOUT = "layout.dolayout"; +ORYX.CONFIG.EVENT_GLOSSARY_LINK_EDIT = "glossary.link.edit"; +ORYX.CONFIG.EVENT_GLOSSARY_SHOW = "glossary.show.info"; +ORYX.CONFIG.EVENT_GLOSSARY_NEW = "glossary.show.new"; +ORYX.CONFIG.EVENT_DOCKERDRAG = "dragTheDocker"; +ORYX.CONFIG.EVENT_CANVAS_SCROLL = "canvas.scroll"; + +ORYX.CONFIG.EVENT_SHOW_PROPERTYWINDOW = "propertywindow.show"; +ORYX.CONFIG.EVENT_ABOUT_TO_SAVE = "file.aboutToSave"; + +/* Selection Shapes Highlights */ +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; + +/* Copy & Paste */ +ORYX.CONFIG.EDIT_OFFSET_PASTE = 10; + +/* Key-Codes */ +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; + +// TODO Determine where the lowercase constants are still used and remove them from here. +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; + +/* Supported Meta Keys */ + +ORYX.CONFIG.META_KEY_META_CTRL = "metactrl"; +ORYX.CONFIG.META_KEY_ALT = "alt"; +ORYX.CONFIG.META_KEY_SHIFT = "shift"; + +/* Key Actions */ + +ORYX.CONFIG.KEY_ACTION_DOWN = "down"; +ORYX.CONFIG.KEY_ACTION_UP = "up"; + + +/* Form Rowlayouting */ +ORYX.CONFIG.FORM_ROW_WIDTH = 350; +ORYX.CONFIG.FORM_GROUP_MARGIN = 5; +ORYX.CONFIG.FORM_GROUP_EMPTY_HEIGHT = 100; + +/* Form element types */ +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'; + +/* * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. * License rights for this program may be obtained from Alfresco Software, Ltd. * pursuant to a written agreement and any use of this program without such an * agreement is prohibited. */ + /* * All code Copyright 2013 KIS Consultancy all rights reserved */ -/** - * Init namespaces - */ -if(!ORYX) {var ORYX = {};} -if(!ORYX.Core) {ORYX.Core = {};} -if(!ORYX.Core.SVG) {ORYX.Core.SVG = {};} +function printf() { -/** - * @classDescription Class for adding text to a shape. - * - */ -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], - - /** - * Constructor - * @param options {Object} : - * textElement - * - */ - construct: function(options) { - arguments.callee.$.construct.apply(this, arguments); - - if(!options.textElement) { - throw "Label: No parameter textElement." - } else if (!ORYX.Editor.checkClassType( options.textElement, SVGTextElement ) ) { - throw "Label: Parameter textElement is not an SVGTextElement." - } - - this.invisibleRenderPoint = -5000; - - this.node = options.textElement; - - - this.node.setAttributeNS(null, 'stroke-width', '0pt'); - this.node.setAttributeNS(null, 'letter-spacing', '-0.01px'); - - this.shapeId = options.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.anchors = []; - this.anchorLeft; - this.anchorRight; - this.anchorTop; - this.anchorBottom; - - this._isChanged = true; - - //if the text element already has an id, don't change it. - var _id = this.node.getAttributeNS(null, 'id'); - if(_id) { - this.id = _id; - } - - //initialization - - //set referenced element the text is fit to - this.fitToElemId = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'fittoelem'); - if(this.fitToElemId) - this.fitToElemId = this.shapeId + this.fitToElemId; - - //set alignment - var alignValues = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'align'); - if(alignValues) { - alignValues = alignValues.replace(/,/g, " "); - alignValues = alignValues.split(" "); - alignValues = alignValues.without(""); - - alignValues.each((function(alignValue) { - switch (alignValue) { - case 'top': - case 'middle': - case 'bottom': - if(!this._verticalAlign){this._originVerticalAlign = this._verticalAlign = alignValue;} - break; - case 'left': - case 'center': - case 'right': - if(!this._horizontalAlign){this._originHorizontalAlign = this._horizontalAlign = alignValue;} - break; - } - }).bind(this)); - } - - //set edge position (only in case the label belongs to an edge) - this.edgePosition = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'edgePosition'); - if(this.edgePosition) { - this.originEdgePosition = this.edgePosition = this.edgePosition.toLowerCase(); - } - - - //get offset top - this.offsetTop = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'offsetTop') || ORYX.CONFIG.OFFSET_EDGE_LABEL_TOP; - if(this.offsetTop) { - this.offsetTop = parseInt(this.offsetTop); - } - - //get offset top - this.offsetBottom = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'offsetBottom') || ORYX.CONFIG.OFFSET_EDGE_LABEL_BOTTOM; - if(this.offsetBottom) { - this.offsetBottom = parseInt(this.offsetBottom); - } - - - //set rotation - var rotateValue = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'rotate'); - if(rotateValue) { - try { - this._rotate = parseFloat(rotateValue); - } catch (e) { - this._rotate = 0; - } - } else { - this._rotate = 0; - } - - //anchors - var anchorAttr = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, "anchors"); - if(anchorAttr) { - anchorAttr = anchorAttr.replace("/,/g", " "); - var anchors = anchorAttr.split(" ").without(""); - - for(var i = 0; i < anchors.length; i++) { - switch(anchors[i].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 no alignment defined, set default alignment - if(!this._verticalAlign) { this._verticalAlign = 'bottom'; } - if(!this._horizontalAlign) { this._horizontalAlign = 'left'; } - - var xValue = this.node.getAttributeNS(null, 'x'); - if(xValue) { - this.oldX = this.x = parseFloat(xValue); - } else { - //TODO error - } - - var yValue = this.node.getAttributeNS(null, 'y'); - if(yValue) { - this.oldY = this.y = parseFloat(yValue); - } else { - //TODO error - } - - //set initial text - this.text(this.node.textContent); - }, - - /** - * Reset the anchor position to the original value - * which was specified in the stencil set - * - */ - 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; }, - - /** - * Returns the x coordinate - * @return {number} - */ - getX: function(){ - try { - var x = this.node.x.baseVal.getItem(0).value; - switch(this.horizontalAlign()){ - case "left": return x; - case "center": return x - (this.getWidth()/2); - case "right": return x - this.getWidth(); - } - return this.node.getBBox().x; - } catch(e){ - return this.x; - } - }, - - setX: function(x){ - if (this.position) - this.position.x = x; - else - this.setOriginX(x); - }, - - - /** - * Returns the y coordinate - * @return {number} - */ - getY: function(){ - try { - return this.node.getBBox().y; - } catch(e){ - return this.y; - } - }, - - setY: function(y){ - if (this.position) - this.position.y = y; - else - this.setOriginY(y); - }, - - setOriginX: function(x){ - this.x = x; - }, - - setOriginY: function(y){ - this.y = y; - }, + var result = arguments[0]; + for (var i = 1; i < arguments.length; i++) + result = result.replace('%' + (i - 1), arguments[i]); + return result; +} - - /** - * Returns the width of the label - * @return {number} - */ - getWidth: function(){ - try { - try { - var width, cn = this.node.childNodes; - if (cn.length == 0) { - width = this.node.getBBox().width; - } else { - for (var i = 0, size = cn.length; i < size; ++i) { - var w = cn[i].getComputedTextLength(); - if ("undefined" == typeof width || width < w) { - width = w; - } - } - } - return width+(width%2==0?0:1); - } catch (ee) { - return this.node.getBBox().width; - } - } catch(e){ - return 0; - } - }, - - getOriginUpperLeft: function(){ - var x = this.x, y = this.y; - switch (this._horizontalAlign){ - case 'center' : - x -= this.getWidth()/2; - break; - case 'right' : - x -= this.getWidth(); - break; - } - switch (this._verticalAlign){ - case 'middle' : - y -= this.getHeight()/2; - break; - case 'bottom' : - y -= this.getHeight(); - break; - } - return {x:x, y:y}; - }, - - /** - * Returns the height of the label - * @return {number} - */ - getHeight: function(){ - try { - return this.node.getBBox().height; - } catch(e){ - return 0; - } - }, - - /** - * Returns the relative center position of the label - * to its parent shape. - * @return {Object} - */ - getCenter: function(){ - var up = {x: this.getX(), y: this.getY()}; - up.x += this.getWidth()/2; - up.y += this.getHeight()/2; - return up; - }, - - /** - * Sets the position of a label relative to the parent. - * @param {Object} position - */ - setPosition: function(position){ - if (!position || position.x === undefined || position.y === undefined) { - delete this.position; - } else { - this.position = position; - } - - if (this.position){ - delete this._referencePoint; - delete this.edgePosition; - } - - this._isChanged = true; - this.update(); - }, - - /** - * Return the position - */ - getPosition: function(){ - return this.position; - }, - - setReferencePoint: function(ref){ - if (ref) { - this._referencePoint = ref; - } else { - delete this._referencePoint; - } - if (this._referencePoint){ - delete this.position; - } - }, - - getReferencePoint: function(){ - return this._referencePoint || undefined; - }, - - changed: function() { - this._isChanged = true; - }, - - /** - * Register a callback which will be called if the label - * was rendered. - * @param {Object} fn - */ - registerOnChange: function(fn){ - if (!this.changeCallbacks){ - this.changeCallbacks = []; - } - if (fn instanceof Function && !this.changeCallbacks.include(fn)){ - this.changeCallbacks.push(fn); - } - }, - - /** - * Unregister the callback for changes. - * @param {Object} fn - */ - unregisterOnChange: function(fn){ - if (this.changeCallbacks && fn instanceof Function && this.changeCallbacks.include(fn)){ - this.changeCallbacks = this.changeCallbacks.without(fn); - } - }, - - /** - * Returns TRUE if the labe is currently in - * the update mechanism. - * @return {Boolean} - */ - isUpdating: function(){ - return !!this._isUpdating; - }, - - - getOriginEdgePosition: function(){ - return this.originEdgePosition; - }, - - /** - * Returns the edgeposition. - * - * @return {String} "starttop", "startmiddle", "startbottom", - * "midtop", "midbottom", "endtop", "endbottom" or null - */ - getEdgePosition: function(){ - return this.edgePosition || null; - }, - - /** - * Set the edge position, must be one of the valid - * edge positions (see getEdgePosition). - * Removes the reference point and the absolute position as well. - * - * @param {Object} position - */ - setEdgePosition: function(position){ - if (["starttop", "startmiddle", "startbottom", - "midtop", "midbottom", "endtop", "endbottom"].include(position)){ - this.edgePosition = position; - delete this.position; - delete this._referencePoint; - } else { - delete this.edgePosition; - } - }, - - /** - * Update the SVG text element. - */ - update: function(force) { - - var x = this.x, y = this.y; - if (this.position){ - x = this.position.x; - y = this.position.y; - } - x = Math.floor(x); y = Math.floor(y); - - if(this._isChanged || x !== this.oldX || y !== this.oldY || force === true) { - if (this.isVisible) { - this._isChanged = false; - this._isUpdating = true; - - this.node.setAttributeNS(null, 'x', x); - this.node.setAttributeNS(null, 'y', y); - this.node.removeAttributeNS(null, "fill-opacity"); - - //this.node.setAttributeNS(null, 'font-size', this._fontSize); - //this.node.setAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'align', this._horizontalAlign + " " + this._verticalAlign); - - this.oldX = x; - this.oldY = y; - - //set rotation - 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(x) + ' ' + Math.floor(y) + ')'); - } - } else { - this.node.removeAttributeNS(null, 'transform'); - } - - var textLines = this._text.split("\n"); - while (textLines.last() == "") - textLines.pop(); - - - if (this.node.ownerDocument) { - // Only reset the tspans if the text - // has changed or has to be wrapped - if (this.fitToElemId || this._textHasChanged){ - this.node.textContent = ""; // Remove content - textLines.each((function(textLine, index){ - var tspan = this.node.ownerDocument.createElementNS(ORYX.CONFIG.NAMESPACE_SVG, 'tspan'); - tspan.textContent = textLine.trim(); - if (this.fitToElemId) { - tspan.setAttributeNS(null, 'x', this.invisibleRenderPoint); - tspan.setAttributeNS(null, 'y', this.invisibleRenderPoint); - } - - /* - * Chrome's getBBox() method fails, if a text node contains an empty tspan element. - * So, we add a whitespace to such a tspan element. - */ - if(tspan.textContent === "") { - tspan.textContent = " "; - } - - //append tspan to text node - this.node.appendChild(tspan); - }).bind(this)); - delete this._textHasChanged; - delete this.indices; - } - - //Work around for Mozilla bug 293581 - if (this.isVisible && this.fitToElemId) { - this.node.setAttributeNS(null, 'visibility', 'hidden'); - } - - if (this.fitToElemId) { - window.setTimeout(this._checkFittingToReferencedElem.bind(this), 0); - //this._checkFittingToReferencedElem(); - } else { - window.setTimeout(this._positionText.bind(this), 0); - //this._positionText(); - } - } - } else { - this.node.textContent = ""; - //this.node.setAttributeNS(null, "fill-opacity", "0.2"); - } - } - }, - - _checkFittingToReferencedElem: function() { - try { - var tspans = $A(this.node.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'tspan')); - - //only do this in firefox 3. all other browsers do not support word wrapping!!!!! - //if (/Firefox[\/\s](\d+\.\d+)/.test(navigator.userAgent) && new Number(RegExp.$1)>=3) { - var newtspans = []; - - var refNode = this.node.ownerDocument.getElementById(this.fitToElemId); - - if (refNode) { - var refbb = refNode.getBBox(); - - var fontSize = this.getFontSize(); - - for (var j = 0; j < tspans.length; j++) { - var tspan = tspans[j]; - - var textLength = this._getRenderedTextLength(tspan, undefined, undefined, fontSize); - - var refBoxLength = (this._rotate != 0 - && this._rotate % 180 != 0 - && this._rotate % 90 == 0 ? - refbb.height : refbb.width); - - if (textLength > refBoxLength) { - - var startIndex = 0; - var lastSeperatorIndex = 0; - - var numOfChars = this.getTrimmedTextLength(tspan.textContent); - for (var i = 0; i < numOfChars; i++) { - var sslength = this._getRenderedTextLength(tspan, startIndex, i-startIndex, fontSize); - - if (sslength > refBoxLength - 2) { - var newtspan = this.node.ownerDocument.createElementNS(ORYX.CONFIG.NAMESPACE_SVG, 'tspan'); - if (lastSeperatorIndex <= startIndex) { - lastSeperatorIndex = (i == 0) ? i : i-1; - newtspan.textContent = tspan.textContent.slice(startIndex, lastSeperatorIndex).trim(); - //lastSeperatorIndex = i; - } - else { - newtspan.textContent = tspan.textContent.slice(startIndex, ++lastSeperatorIndex).trim(); - } - - newtspan.setAttributeNS(null, 'x', this.invisibleRenderPoint); - newtspan.setAttributeNS(null, 'y', this.invisibleRenderPoint); - - //insert tspan to text node - //this.node.insertBefore(newtspan, tspan); - newtspans.push(newtspan); - - startIndex = lastSeperatorIndex; - } - else { - var curChar = tspan.textContent.charAt(i); - if (curChar == ' ' || - curChar == '-' || - curChar == "." || - curChar == "," || - curChar == ";" || - curChar == ":") { - lastSeperatorIndex = i; - } - } - } - - tspan.textContent = tspan.textContent.slice(startIndex).trim(); - } - - newtspans.push(tspan); - } - - while (this.node.hasChildNodes()) - this.node.removeChild(this.node.childNodes[0]); - - while (newtspans.length > 0) { - this.node.appendChild(newtspans.shift()); - } - } - //} - } catch (e) { - ORYX.Log.fatal("Error " + e); - } - window.setTimeout(this._positionText.bind(this), 0); - //this._positionText(); - }, - - /** - * This is a work around method for Mozilla bug 293581. - * Before the method getComputedTextLength works, the text has to be rendered. - */ - _positionText: function() { - try { - - var tspans = this.node.childNodes; - - var fontSize = this.getFontSize(this.node); - - var invalidTSpans = []; - - var x = this.x, y = this.y; - if (this.position){ - x = this.position.x; - y = this.position.y; - } - x = Math.floor(x); y = Math.floor(y); - - var i = 0, indic = []; // Cache indices if the _positionText is called again, before update is called - var is =(this.indices || $R(0,tspans.length-1).toArray()); - var length = is.length; - is.each((function(index){ - if ("undefined" == typeof index){ - return; - } - - var tspan = tspans[i++]; - - if(tspan.textContent.trim() === "") { - invalidTSpans.push(tspan); - } else { - //set vertical position - var dy = 0; - switch (this._verticalAlign) { - case 'bottom': - dy = -(length - index - 1) * (fontSize); - break; - case 'middle': - dy = -(length / 2.0 - index - 1) * (fontSize); - dy -= ORYX.CONFIG.LABEL_LINE_DISTANCE / 2; - break; - case 'top': - dy = index * (fontSize); - dy += fontSize; - break; - } - tspan.setAttributeNS(null, 'dy', Math.floor(dy)); - - tspan.setAttributeNS(null, 'x', x); - tspan.setAttributeNS(null, 'y', y); - indic.push(index); - } - - }).bind(this)); - - indic.length = tspans.length; - this.indices = this.indices || indic; - - invalidTSpans.each(function(tspan) { - this.node.removeChild(tspan) - }.bind(this)); - - //set horizontal alignment - 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(e) { - //console.log(e); - this._isChanged = true; - } - - - if(this.isVisible) { - this.node.removeAttributeNS(null, 'visibility'); - } - - - // Finished - delete this._isUpdating; - - // Raise change event - (this.changeCallbacks||[]).each(function(fn){ - fn.apply(fn); - }) - - }, - - /** - * Returns the text length of the text content of an SVG tspan element. - * For all browsers but Firefox 3 the values are estimated. - * @param {TSpanSVGElement} tspan - * @param {int} startIndex Optional, for sub strings - * @param {int} endIndex Optional, for sub strings - */ - _getRenderedTextLength: function(tspan, startIndex, endIndex, fontSize) { - //if (/Firefox[\/\s](\d+\.\d+)/.test(navigator.userAgent) && new Number(RegExp.$1) >= 3) { - if(startIndex === undefined) { -//test string: abcdefghijklmnopqrstuvwxyz????????????????,.-#+ 1234567890?????ABCDEFGHIJKLMNOPQRSTUVWXYZ;:_'*???????????????!"????$%&/()=?[]{}|<>'~????`\^?????????@????????????????? -// for(var i = 0; i < tspan.textContent.length; i++) { -// console.log(tspan.textContent.charAt(i), tspan.getSubStringLength(i,1), this._estimateCharacterWidth(tspan.textContent.charAt(i))*(fontSize/14.0)); -// } - return tspan.getComputedTextLength(); - } else { - return tspan.getSubStringLength(startIndex, endIndex); - } - /*} else { - if(startIndex === undefined) { - return this._estimateTextWidth(tspan.textContent, fontSize); - } else { - return this._estimateTextWidth(tspan.textContent.substr(startIndex, endIndex).trim(), fontSize); - } - }*/ - }, - - /** - * Estimates the text width for a string. - * Used for word wrapping in all browser but FF3. - * @param {Object} text - */ - _estimateTextWidth: function(text, fontSize) { - var sum = 0.0; - for(var i = 0; i < text.length; i++) { - sum += this._estimateCharacterWidth(text.charAt(i)); - } - - return sum*(fontSize/14.0); - }, - - /** - * Estimates the width of a single character for font size 14. - * Used for word wrapping in all browser but FF3. - * @param {Object} character - */ - _estimateCharacterWidth: function(character) { - for(var i = 0; i < this._characterSets.length; i++) { - if(this._characterSets[i].indexOf(character) >= 0) { - return this._characterSetValues[i]; - } - } - return 9; - }, - - getReferencedElementWidth: function() { - var refNode = this.node.ownerDocument.getElementById(this.fitToElemId); - - if(refNode) { - var refbb = refNode.getBBox(); - - if(refbb) { - return (this._rotate != 0 - && this._rotate % 180 != 0 - && this._rotate % 90 == 0 ? - refbb.height : refbb.width); - } - } - - return undefined; - }, - - /** - * If no parameter is provided, this method returns the current text. - * @param text {String} Optional. Replaces the old text with this one. - */ - text: function() { - switch (arguments.length) { - case 0: - return this._text - break; - - case 1: - var oldText = this._text; - if(arguments[0]) { - // Filter out multiple spaces to fix issue in chrome for line-wrapping - this._text = arguments[0].toString(); - if(this._text != null && this._text != undefined) { - this._text = this._text.replace(/ {2,}/g,' '); - } - } else { - this._text = ""; - } - if(oldText !== this._text) { - this._isChanged = true; - this._textHasChanged = true; - } - break; - - default: - //TODO error - 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 oldValue = this._verticalAlign; - this._verticalAlign = arguments[0]; - if(this._verticalAlign !== oldValue) { - this._isChanged = true; - } - } - break; - - default: - //TODO error - 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 oldValue = this._horizontalAlign; - this._horizontalAlign = arguments[0]; - if(this._horizontalAlign !== oldValue) { - this._isChanged = true; - } - } - break; - - default: - //TODO error - 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; - - // Since text is removed from the tspan when "hidden", mark - // the text as changed to get it redrawn - this._textHasChanged = true; - } - }, - - /** - * iterates parent nodes till it finds a SVG font-size - * attribute. - * @param {SVGElement} node - */ - getInheritedFontSize: function(node) { - if(!node || !node.getAttributeNS) - return; - - var attr = node.getAttributeNS(null, "font-size"); - if(attr) { - return parseFloat(attr); - } else if(!ORYX.Editor.checkClassType(node, SVGSVGElement)) { - return this.getInheritedFontSize(node.parentNode); - } - }, - - getFontSize: function(node) { - var tspans = this.node.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'tspan'); - - //trying to get an inherited font-size attribute - //NO CSS CONSIDERED! - var fontSize = this.getInheritedFontSize(this.node); - - if (!fontSize) { - //because this only works in firefox 3, all other browser use the default line height - if (tspans[0] && /Firefox[\/\s](\d+\.\d+)/.test(navigator.userAgent) && new Number(RegExp.$1) >= 3) { - fontSize = tspans[0].getExtentOfChar(0).height; - } - else { - fontSize = ORYX.CONFIG.LABEL_DEFAULT_LINE_HEIGHT; - } - - //handling of unsupported method in webkit - if (fontSize <= 0) { - fontSize = ORYX.CONFIG.LABEL_DEFAULT_LINE_HEIGHT; - } - } - - if(fontSize) - this.node.setAttribute("oryx:fontSize", fontSize); - - return fontSize; - }, - - /** - * Get trimmed text length for use with - * getExtentOfChar and getSubStringLength. - * @param {String} text - */ - getTrimmedTextLength: function(text) { - text = text.strip().gsub(' ', ' '); - - var oldLength; - do { - oldLength = text.length; - text = text.gsub(' ', ' '); - } while (oldLength > text.length); - - return text.length; - }, - - /** - * Returns the offset from - * edge to the label which is - * positioned under the edge - * @return {int} - */ - getOffsetBottom: function(){ - return this.offsetBottom; - }, - - - /** - * Returns the offset from - * edge to the label which is - * positioned over the edge - * @return {int} - */ - getOffsetTop: function(){ - return this.offsetTop; - }, - - /** - * - * @param {Object} obj - */ - deserialize: function(obj, shape){ - if (obj && "undefined" != typeof obj.x && "undefined" != typeof obj.y){ - this.setPosition({x:obj.x, y:obj.y}); - - if ("undefined" != typeof obj.distance){ - var from = shape.dockers[obj.from]; - var to = shape.dockers[obj.to]; - if (from && to){ - this.setReferencePoint({ - dirty : true, - distance : obj.distance, - intersection : {x: obj.x, y: obj.y}, - orientation : obj.orientation, - segment: { - from: from, - fromIndex: obj.from, - fromPosition: from.bounds.center(), - to: to, - toIndex: obj.to, - toPosition: to.bounds.center() - } - }) - } - } - - if (obj.left) this.anchorLeft = true; - if (obj.right) this.anchorRight = true; - if (obj.top) this.anchorTop = true; - if (obj.bottom) this.anchorBottom = true; - if (obj.valign) this.verticalAlign(obj.valign); - if (obj.align) this.horizontalAlign(obj.align); - - } else if (obj && "undefined" != typeof obj.edge){ - this.setEdgePosition(obj.edge); - } - }, +// oryx constants. +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; - /** - * - * @return {Object} - */ - serialize: function(){ - - // On edge position - if (this.getEdgePosition()){ - if (this.getOriginEdgePosition() !== this.getEdgePosition()){ - return {edge: this.getEdgePosition()}; - } else { - return null; - } - } - - // On self defined position - if (this.position){ - var pos = {x: this.position.x, y: this.position.y}; - if (this.isAnchorLeft() && this.isAnchorLeft() !== this.isOriginAnchorLeft()){ - pos.left = true; - } - if (this.isAnchorRight() && this.isAnchorRight() !== this.isOriginAnchorRight()){ - pos.right = true; - } - if (this.isAnchorTop() && this.isAnchorTop() !== this.isOriginAnchorTop()){ - pos.top = true; - } - if (this.isAnchorBottom() && this.isAnchorBottom() !== this.isOriginAnchorBottom()){ - pos.bottom = true; - } - - if (this.getOriginVerticalAlign() !== this.verticalAlign()){ - pos.valign = this.verticalAlign(); - } - if (this.getOriginHorizontalAlign() !== this.horizontalAlign()){ - pos.align = this.horizontalAlign(); - } - - return pos; - } - - // On reference point which is interesting for edges - if (this.getReferencePoint()){ - var ref = this.getReferencePoint(); - return { - distance : ref.distance, - x : ref.intersection.x, - y : ref.intersection.y, - from : ref.segment.fromIndex, - to : ref.segment.toIndex, - orientation : ref.orientation, - valign : this.verticalAlign(), - align : this.horizontalAlign() - } - } - return null; - }, - - toString: function() { return "Label " + this.id } - });/* - * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. - * License rights for this program may be obtained from Alfresco Software, Ltd. - * pursuant to a written agreement and any use of this program without such an - * agreement is prohibited. - */ -/* - * All code Copyright 2013 KIS Consultancy all rights reserved - */ +if (!ORYX) var ORYX = {}; -/** - * Init namespaces - */ -if(!ORYX) {var ORYX = {};} -if(!ORYX.Core) {ORYX.Core = {};} -if(!ORYX.Core.Math) {ORYX.Core.Math = {};} - -/** - * Calculate the middle point between two given points - * @param {x:double, y:double} point1 - * @param {x:double, y:double} point2 - * @return the middle point - */ -ORYX.Core.Math.midPoint = function(point1, point2) { - return { - x: (point1.x + point2.x) / 2.0, - y: (point1.y + point2.y) / 2.0 - } -} - -/** - * Returns a TRUE if the point is over a line (defined by - * point1 and point 2). In Addition a threshold can be set, - * which defines the weight of those line. - * - * @param {int} pointX - Point X - * @param {int} pointY - Point Y - * @param {int} lPoint1X - Line first Point X - * @param {int} lPoint1Y - Line first Point Y - * @param {int} lPoint2X - Line second Point X - * @param {int} lPoint2Y - Line second Point y - * @param {int} offset {optional} - maximal distance to line - * @class ORYX.Core.Math.prototype - */ -ORYX.Core.Math.isPointInLine = function (pointX, pointY, lPoint1X, lPoint1Y, lPoint2X, lPoint2Y, offset) { +ORYX = Object.extend(ORYX, { - offset = offset ? Math.abs(offset) : 1; - - // Check if the edge is vertical - if(Math.abs(lPoint1X-lPoint2X)<=offset && Math.abs(pointX-lPoint1X)<=offset && pointY-Math.max(lPoint1Y, lPoint2Y)<=offset && Math.min(lPoint1Y, lPoint2Y)-pointY<=offset) { - return true - } - - // Check if the edge is horizontal - if(Math.abs(lPoint1Y-lPoint2Y)<=offset && Math.abs(pointY-lPoint1Y)<=offset && pointX-Math.max(lPoint1X, lPoint2X)<=offset && Math.min(lPoint1X, lPoint2X)-pointX<=offset) { - return true - } - - if(pointX > Math.max(lPoint1X, lPoint2X) || pointX < Math.min(lPoint1X, lPoint2X)) { - return false - } - - if(pointY > Math.max(lPoint1Y, lPoint2Y) || pointY < Math.min(lPoint1Y, lPoint2Y)) { - return false - } - - var s = (lPoint1Y - lPoint2Y) / (lPoint1X - lPoint2X); - - return Math.abs(pointY - ((s * pointX) + lPoint1Y - s * lPoint1X)) < offset -} + //set the path in the config.js file!!!! + PATH: ORYX.CONFIG.ROOT_PATH, + //CONFIGURATION: "config.js", -/** - * Get a boolean if the point is in the polygone - * - */ -ORYX.Core.Math.isPointInEllipse = function (pointX, pointY, cx, cy, rx, ry) { + URLS: [], - if(cx === undefined || cy === undefined || rx === undefined || ry === undefined) { - throw "ORYX.Core.Math.isPointInEllipse needs a ellipse with these properties: x, y, radiusX, radiusY" - } - - var tx = (pointX - cx) / rx; - var ty = (pointY - cy) / ry; - - return tx * tx + ty * ty < 1.0; -} - -/** - * Get a boolean if the point is in the polygone - * @param {int} pointX - * @param {int} pointY - * @param {[int]} Cornerpoints of the Polygone (x,y,x,y,...) - */ -ORYX.Core.Math.isPointInPolygone = function(pointX, pointY, polygone){ - - if (arguments.length < 3) { - throw "ORYX.Core.Math.isPointInPolygone needs two arguments" - } - - var lastIndex = polygone.length-1; - - if (polygone[0] !== polygone[lastIndex - 1] || polygone[1] !== polygone[lastIndex]) { - polygone.push(polygone[0]); - polygone.push(polygone[1]); - } - - var crossings = 0; - - var x1, y1, x2, y2, d; - - for (var i = 0; i < polygone.length - 3; ) { - x1=polygone[i]; - y1=polygone[++i]; - x2=polygone[++i]; - y2=polygone[i+1]; - d=(pointY - y1) * (x2 - x1) - (pointX - x1) * (y2 - y1); + alreadyLoaded: [], - if ((y1 >= pointY) != (y2 >= pointY)) { - crossings += y2 - y1 >= 0 ? d >= 0 : d <= 0; - } - if (!d && Math.min(x1,x2) <= pointX && pointX <= Math.max(x1,x2) - && Math.min(y1,y2) <= pointY && pointY <= Math.max(y1,y2)) { - return true; - } - } - return (crossings%2)?true:false; -} + configrationRetries: 0, -/** - * Calculates the distance between a point and a line. It is also testable, if - * the distance orthogonal to the line, matches the segment of the line. - * - * @param {float} lineP1 - * The starting point of the line segment - * @param {float} lineP2 - * The end point of the line segment - * @param {Point} point - * The point to calculate the distance to. - * @param {boolean} toSegmentOnly - * Flag to signal if only the segment of the line shell be evaluated. - */ -ORYX.Core.Math.distancePointLinie = function( - lineP1, - lineP2, - point, - toSegmentOnly) { - - var intersectionPoint = - ORYX.Core.Math.getPointOfIntersectionPointLine(lineP1, - lineP2, - point, - toSegmentOnly); - - if(!intersectionPoint) { - return null; - } - - return ORYX.Core.Math.getDistancePointToPoint(point, intersectionPoint); -}; + Version: '0.1.1', -/** - * Calculates the distance between two points. - * - * @param {point} point1 - * @param {point} point2 - */ -ORYX.Core.Math.getDistancePointToPoint = function(point1, point2) { - return Math.sqrt(Math.pow(point1.x - point2.x, 2) + Math.pow(point1.y - point2.y, 2)); -}; + availablePlugins: [], -/** - * Calculates the relative distance of a point which is between two other points. - * - * @param {point} between1 - * @param {point} between2 - * @param {point} point - */ -ORYX.Core.Math.getDistanceBetweenTwoPoints = function(between1, between2, point) { - return ORYX.Core.Math.getDistancePointToPoint(point, between1) / - ORYX.Core.Math.getDistancePointToPoint(between1, between2); -}; + /** + * The ORYX.Log logger. + */ + Log: { + __appenders: [ + { + append: function (message) { + if (typeof (console) !== "undefined" && console.log !== undefined) { + console.log(message); + } + } + } + ], -/** - * Returns true, if the point is of the left hand - * side of the regarding the line. - * - * @param {point} lineP1 Line first point - * @param {point} lineP2 Line second point - * @param {point} point - */ -ORYX.Core.Math.pointIsLeftOfLine = function(lineP1, lineP2, point){ - - var vec1 = ORYX.Core.Math.getVector(lineP1, lineP2); - var vec2 = ORYX.Core.Math.getVector(lineP1, point); - // if the cross produkt is more than 0 - return ((vec1.x*vec2.y) - (vec2.x*vec1.y)) > 0 -}; + 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); + }, -/** - * Calculates the a point which is relatively between two other points. - * - * @param {point} point1 - * @param {point} point2 - * @param {number} relative Relative which is between 0 and 1 - */ -ORYX.Core.Math.getPointBetweenTwoPoints = function(point1, point2, relative) { - relative = Math.max(Math.min(relative || 0, 1), 0); - - if (relative === 0){ - return point1; - } else if (relative === 1){ - return point2; - } - - return { - x: point1.x + ((point2.x - point1.x) * relative), - y: point1.y + ((point2.y - point1.y) * relative) - } -}; + __log: function (prefix, messageParts) { + messageParts[0] = (new Date()).getTime() + " " + + prefix + " " + messageParts[0]; + var message = printf.apply(null, messageParts); -/** - * Returns the vector of the both points - * - * @param {point} point1 - * @param {point} point2 - */ -ORYX.Core.Math.getVector = function(point1, point2){ - return { - x: point2.x - point1.x, - y: point2.y - point1.y - } -} + ORYX.Log.__appenders.each(function (appender) { + appender.append(message); + }); + }, -/** - * Returns the an identity vector of the given vector, - * which has the length ot one. - * - * @param {point} vector - * or - * @param {point} point1 - * @param {point} point2 - */ -ORYX.Core.Math.getIdentityVector = function(vector){ - - if (arguments.length == 2){ - vector = ORYX.Core.Math.getVector(arguments[0], arguments[1]); - } - - var length = Math.sqrt((vector.x*vector.x)+(vector.y*vector.y)) - return { - x: vector.x / (length || 1), - y: vector.y / (length || 1) - } -} + addAppender: function (appender) { + ORYX.Log.__appenders.push(appender); + } + }, + /** + * First bootstrapping layer. The Oryx loading procedure begins. In this + * step, all preliminaries that are not in the responsibility of Oryx to be + * met have to be checked here, such as the existance of the prototpe + * library in the current execution environment. After that, the second + * bootstrapping layer is being invoked. Failing to ensure that any + * preliminary condition is not met has to fail with an error. + */ + load: function () { -ORYX.Core.Math.getOrthogonalIdentityVector = function(point1, point2){ - var vec = arguments.length == 1 ? point1 : ORYX.Core.Math.getIdentityVector(point1, point2); - return { - x: vec.y, - y: -vec.x - } -} + ORYX.Log.debug("Oryx begins loading procedure."); + // check for prototype + if ((typeof Prototype == 'undefined') || + (typeof Element == 'undefined') || + (typeof Element.Methods == 'undefined') || + parseFloat(Prototype.Version.split(".")[0] + "." + + Prototype.Version.split(".")[1]) < 1.5) -/** - * Returns the intersection point of a line and a point that defines a line - * orthogonal to the given line. - * - * @param {float} lineP1 - * The starting point of the line segment - * @param {float} lineP2 - * The end point of the line segment - * @param {Point} point - * The point to calculate the distance to. - * @param {boolean} onSegmentOnly - * Flag to signal if only the segment of the line shell be evaluated. - */ -ORYX.Core.Math.getPointOfIntersectionPointLine = function( - lineP1, - lineP2, - point, - onSegmentOnly) { + throw("Application requires the Prototype JavaScript framework >= 1.5.3"); - /* - * [P3 - P1 - u(P2 - P1)] dot (P2 - P1) = 0 - * u =((x3-x1)(x2-x1)+(y3-y1)(y2-y1))/(p2-p1)?? - */ - var denominator = Math.pow(lineP2.x - lineP1.x, 2) - + Math.pow(lineP2.y - lineP1.y, 2); - if(denominator == 0) { - return undefined; - } - - var u = ((point.x - lineP1.x) * (lineP2.x - lineP1.x) - + (point.y - lineP1.y) * (lineP2.y - lineP1.y)) - / denominator; - - if(onSegmentOnly) { - if (!(0 <= u && u <= 1)) { - return undefined; - } - } - - pointOfIntersection = new Object(); - pointOfIntersection.x = lineP1.x + u * (lineP2.x - lineP1.x); - pointOfIntersection.y = lineP1.y + u * (lineP2.y - lineP1.y); - - return pointOfIntersection; -}; + ORYX.Log.debug("Prototype > 1.5 found."); -/** - * Translated the point with the given matrix. - * @param {Point} point - * @param {Matrix} matrix - * @return {Object} Includes x, y - */ -ORYX.Core.Math.getTranslatedPoint = function(point, matrix){ - var x = matrix.a*point.x+matrix.c*point.y+matrix.e*1; - var y = matrix.b*point.x+matrix.d*point.y+matrix.f*1; - return {x:x, y:y} -} + // continue loading. + ORYX._load(); + }, + /** + * Second bootstrapping layer. The oryx configuration is checked. When not + * yet loaded, config.js is being requested from the server. A repeated + * error in retrieving the configuration will result in an error to be + * thrown after a certain time of retries. Once the configuration is there, + * all urls that are registered with oryx loading are being requested from + * the server. Once everything is loaded, the third layer is being invoked. + */ + _load: function () { + /* + // if configuration not there already, + if(!(ORYX.CONFIG)) { -/** - * Returns the inverse matrix of the given SVG transformation matrix - * @param {SVGTransformationMatrix} matrix - * @return {Matrix} - */ -ORYX.Core.Math.getInverseMatrix = function(matrix){ - - var det = ORYX.Core.Math.getDeterminant(matrix), m = matrix; - // +- -+ - // | a c e | - // | b d f | - // | 0 0 1 | - // +- -+ - return { - a: det * ((m.d*1)-(m.f*0)), - b: det * ((m.f*0)-(m.b*1)), - c: det * ((m.e*0)-(m.c*1)), - d: det * ((m.a*1)-(m.e*0)), - e: det * ((m.c*m.f)-(m.e*m.d)), - f: det * ((m.e*m.b)-(m.a*m.f)) - } -} + // if this is the first attempt... + if(ORYX.configrationRetries == 0) { -/** - * Returns the determinant of the svg transformation matrix - * @param {SVGTranformationMatrix} matrix - * @return {Number} - * - */ -ORYX.Core.Math.getDeterminant = function(m){ - // a11a22a33+a12a23a31+a13a21a32-a13a22a31-a12a21a33-a11a23a32 - return (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); -} + // get the path and filename. + var configuration = ORYX.PATH + ORYX.CONFIGURATION; -/** - * Returns the bounding box of the given node. Translates the - * origin bounding box with the tranlation matrix. - * @param {SVGElement} node - * @return {Object} Includes x, y, width, height - */ -ORYX.Core.Math.getTranslatedBoundingBox = function(node){ - var matrix = node.getCTM(); - var bb = node.getBBox(); - var ul = ORYX.Core.Math.getTranslatedPoint({x:bb.x, y:bb.y}, matrix); - var ll = ORYX.Core.Math.getTranslatedPoint({x:bb.x, y:bb.y+bb.height}, matrix); - var ur = ORYX.Core.Math.getTranslatedPoint({x:bb.x+bb.width, y:bb.y}, matrix); - var lr = ORYX.Core.Math.getTranslatedPoint({x:bb.x+bb.width, y:bb.y+bb.height}, matrix); - - var minPoint = { - x: Math.min(ul.x, ll.x, ur.x, lr.x), - y: Math.min(ul.y, ll.y, ur.y, lr.y) - } - var maxPoint = { - x: Math.max(ul.x, ll.x, ur.x, lr.x), - y: Math.max(ul.y, ll.y, ur.y, lr.y) - } - return { - x: minPoint.x, - y: minPoint.y, - width: maxPoint.x - minPoint.x, - height: maxPoint.y - minPoint.y - } -}; + ORYX.Log.debug("Configuration not found, loading from '%0'.", + configuration); + // require configuration file. + Kickstart.require(configuration); -/** - * Returns the angle of the given line, which is representated by the two points - * @param {Point} p1 - * @param {Point} p2 - * @return {Number} 0 <= x <= 359.99999 - */ -ORYX.Core.Math.getAngle = function(p1, p2){ - if(p1.x == p2.x && p1.y == p2.y) - return 0; - - var angle = Math.asin(Math.sqrt(Math.pow(p1.y-p2.y, 2)) - /(Math.sqrt(Math.pow(p2.x-p1.x, 2)+Math.pow(p1.y-p2.y, 2)))) - *180/Math.PI; - - if(p2.x >= p1.x && p2.y <= p1.y) - return angle; - else if(p2.x < p1.x && p2.y <= p1.y) - return 180 - angle; - else if(p2.x < p1.x && p2.y > p1.y) - return 180 + angle; - else - return 360 - angle; -}; + // else if attempts exceeded ... + } else if(ORYX.configrationRetries >= ORYX_CONFIGURATION_WAIT_ATTEMPTS) { + throw "Tried to get configuration" + + ORYX_CONFIGURATION_WAIT_ATTEMPTS + + " times from '" + configuration + "'. Giving up." -/** - * Implementation of the cohen-sutherland algorithm - */ -new function(){ - - var RIGHT = 2, TOP = 8, BOTTOM = 4, LEFT = 1; - - function computeOutCode (x, y, xmin, ymin, xmax, ymax) { - var code = 0; - if (y > ymax) - code |= TOP; - else if (y < ymin) - code |= BOTTOM; - if (x > xmax) - code |= RIGHT; - else if (x < xmin) - code |= LEFT; - return code; - } - - /** - * Returns TRUE if the rectangle is over the edge and has intersection points or includes it - * @param {Object} x1 Point A of the line - * @param {Object} y1 - * @param {Object} x2 Point B of the line - * @param {Object} y2 - * @param {Object} xmin Point A of the rectangle - * @param {Object} ymin - * @param {Object} xmax Point B of the rectangle - * @param {Object} ymax - */ - ORYX.Core.Math.isRectOverLine = function(x1, y1, x2, y2, xmin, ymin, xmax, ymax){ - return !!ORYX.Core.Math.clipLineOnRect.apply(ORYX.Core.Math, arguments); - } - - /** - * Returns the clipped line on the given rectangle. If there is - * no intersection, it will return NULL. - * - * @param {Object} x1 Point A of the line - * @param {Object} y1 - * @param {Object} x2 Point B of the line - * @param {Object} y2 - * @param {Object} xmin Point A of the rectangle - * @param {Object} ymin - * @param {Object} xmax Point B of the rectangle - * @param {Object} ymax - */ - ORYX.Core.Math.clipLineOnRect = function(x1, y1, x2, y2, xmin, ymin, xmax, ymax){ - //Outcodes for P0, P1, and whatever point lies outside the clip rectangle - var outcode0, outcode1, outcodeOut, hhh = 0; - var accept = false, done = false; - - //compute outcodes - outcode0 = computeOutCode(x1, y1, xmin, ymin, xmax, ymax); - outcode1 = computeOutCode(x2, y2, xmin, ymin, xmax, ymax); - - do { - if ((outcode0 | outcode1) == 0 ){ - accept = true; - done = true; - } else if ( (outcode0 & outcode1) > 0 ) { - done = true; - } else { - //failed both tests, so calculate the line segment to clip - //from an outside point to an intersection with clip edge - var x = 0, y = 0; - //At least one endpoint is outside the clip rectangle; pick it. - outcodeOut = outcode0 != 0 ? outcode0: outcode1; - //Now find the intersection point; - //use formulas y = y0 + slope * (x - x0), x = x0 + (1/slope)* (y - y0) - if ( (outcodeOut & TOP) > 0 ) { - x = x1 + (x2 - x1) * (ymax - y1)/(y2 - y1); - y = ymax; - } else if ((outcodeOut & BOTTOM) > 0 ) { - x = x1 + (x2 - x1) * (ymin - y1)/(y2 - y1); - y = ymin; - } else if ((outcodeOut & RIGHT)> 0) { - y = y1 + (y2 - y1) * (xmax - x1)/(x2 - x1); - x = xmax; - } else if ((outcodeOut & LEFT) > 0) { - y = y1 + (y2 - y1) * (xmin - x1)/(x2 - x1); - x = xmin; - } - - //Now we move outside point to intersection point to clip - //and get ready for next pass. - if (outcodeOut == outcode0) { - x1 = x; - y1 = y; - outcode0 = computeOutCode (x1, y1, xmin, ymin, xmax, ymax); - } else { - x2 = x; - y2 = y; - outcode1 = computeOutCode (x2, y2, xmin, ymin, xmax, ymax); - } - } - hhh ++; - } while (done != true && hhh < 5000); - - if(accept) { - return {a:{x:x1, y:y1}, b:{x:x2, y:y2}}; - } - return null; - } -}(); + } else if(ORYX.configrationRetries > 0){ + // point out how many attempts are left... + ORYX.Log.debug("Waiting once more (%0 attempts left)", + (ORYX_CONFIGURATION_WAIT_ATTEMPTS - + ORYX.configrationRetries)); -/* - * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. - * License rights for this program may be obtained from Alfresco Software, Ltd. - * pursuant to a written agreement and any use of this program without such an - * agreement is prohibited. - */ -/* - * All code Copyright 2013 KIS Consultancy all rights reserved - */ + } -/** - * Init namespace - */ -if(!ORYX) {var ORYX = {};} -if(!ORYX.Core) {ORYX.Core = {};} -if(!ORYX.Core.StencilSet) {ORYX.Core.StencilSet = {};} + // any case: continue in a moment with increased retry count. + ORYX.configrationRetries++; + window.setTimeout(ORYX._load, ORYX_CONFIGURATION_DELAY); + return; + } -/** - * Class Stencil - * uses Prototpye 1.5.0 - * uses Inheritance - * - * This class represents one stencil of a stencil set. - */ -ORYX.Core.StencilSet.Stencil = { + ORYX.Log.info("Configuration loaded."); - /** - * Constructor - */ - construct: function(jsonStencil, namespace, source, stencilSet, propertyPackages, defaultPosition) { - arguments.callee.$.construct.apply(this, arguments); // super(); - - // check arguments and set defaults. - if(!jsonStencil) throw "Stencilset seems corrupt."; - if(!namespace) throw "Stencil does not provide namespace."; - if(!source) throw "Stencil does not provide SVG source."; - if(!stencilSet) throw "Fatal internal error loading stencilset."; - //if(!propertyPackages) throw "Fatal internal error loading stencilset."; - - this._source = source; - this._jsonStencil = jsonStencil; - this._stencilSet = stencilSet; - this._namespace = namespace; - this._propertyPackages = propertyPackages; - - if(defaultPosition && !this._jsonStencil.position) - this._jsonStencil.position = defaultPosition; - - this._view; - this._properties = new Hash(); - - // check stencil consistency and set defaults. - /*with(this._jsonStencil) { - - if(!type) throw "Stencil does not provide type."; - if((type != "edge") && (type != "node")) - throw "Stencil type must be 'edge' or 'node'."; - if(!id || id == "") throw "Stencil does not provide valid id."; - if(!title || title == "") - throw "Stencil does not provide title"; - if(!description) { description = ""; }; - if(!groups) { groups = []; } - if(!roles) { roles = []; } + // load necessary scripts. + ORYX.URLS.each(function(url) { + ORYX.Log.debug("Requireing '%0'", url); + Kickstart.require(ORYX.PATH + url) }); + */ + // configurate logging and load plugins. + ORYX.loadPlugins(); + }, - // add id of stencil to its roles - roles.push(id); - }*/ - - //init all JSON values - 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."; - } + /** + * Third bootstrapping layer. This is where first the plugin coniguration + * file is loaded into oryx, analyzed, and where all plugins are being + * requested by the server. Afterwards, all editor instances will be + * initialized. + */ + loadPlugins: function () { - if(!this._jsonStencil.description) { this._jsonStencil.description = ""; }; - if(!this._jsonStencil.groups) { this._jsonStencil.groups = []; } - if(!this._jsonStencil.roles) { this._jsonStencil.roles = []; } - - //add id of stencil to its roles - this._jsonStencil.roles.push(this._jsonStencil.id); + // load plugins if enabled. + if (ORYX.CONFIG.PLUGINS_ENABLED) + ORYX._loadPlugins() + else + ORYX.Log.warn("Ignoring plugins, loading Core only."); - //prepend namespace to each role - this._jsonStencil.roles.each((function(role, index) { - this._jsonStencil.roles[index] = namespace + role; - }).bind(this)); + // init the editor instances. + init(); + }, - //delete duplicate roles - this._jsonStencil.roles = this._jsonStencil.roles.uniq(); + _loadPlugins: function () { - //make id unique by prepending namespace of stencil set - this._jsonStencil.id = namespace + this._jsonStencil.id; + // load plugin configuration file. + var source = ORYX.CONFIG.PLUGINS_CONFIG; - this.postProcessProperties(); - - // init serialize callback - if(!this._jsonStencil.serialize) { - this._jsonStencil.serialize = {}; - //this._jsonStencil.serialize = function(shape, data) { return data;}; - } - - // init deserialize callback - if(!this._jsonStencil.deserialize) { - this._jsonStencil.deserialize = {}; - //this._jsonStencil.deserialize = function(shape, data) { return data;}; - } - - // init layout callback - if(!this._jsonStencil.layout) { - this._jsonStencil.layout = [] - //this._jsonStencil.layout = function() {return true;} - } - - //TODO does not work correctly, if the url does not exist - //How to guarantee that the view is loaded correctly before leaving the constructor??? - var url = source + "view/" + jsonStencil.view; - // override content type when this is webkit. - - if(this._jsonStencil.view.trim().match(/ 0) { + globalProperties.push(property) + } + ; + }); + }); - 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); - }, + // TODO Why are we using XML if we don't respect structure anyway? + // for each plugin element in the configuration.. + var plugin = resultXml.getElementsByTagName("plugin"); + $A(plugin).each(function (node) { - view: function() { - return this._view.cloneNode(true) || this._view; - }, + // get all element's attributes. + // TODO: What about: var pluginData = $H(node.attributes) !? + var pluginData = new Hash(); + $A(node.attributes).each(function (attr) { + pluginData[attr.nodeName] = attr.nodeValue + }); - 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(); - }, + // ensure there's a name attribute. + if (!pluginData['name']) { + ORYX.Log.error("A plugin is not providing a name. Ingnoring this plugin."); + return; + } - property: function(id) { - return this._properties[id]; - }, + // ensure there's a source attribute. + if (!pluginData['source']) { + ORYX.Log.error("Plugin with name '%0' doesn't provide a source attribute.", pluginData['name']); + return; + } - roles: function() { - return this._jsonStencil.roles; - }, - - defaultAlign: function() { - if(!this._jsonStencil.defaultAlign) - return "east"; - return this._jsonStencil.defaultAlign; - }, + // Get all private Properties + var propertyNodes = node.getElementsByTagName("property"); + var properties = []; + $A(propertyNodes).each(function (prop) { + var property = new Hash(); - serialize: function(shape, data) { - return this._jsonStencil.serialize; - //return this._jsonStencil.serialize(shape, data); - }, - - deserialize: function(shape, data) { - return this._jsonStencil.deserialize; - //return this._jsonStencil.deserialize(shape, data); - }, - - // in which case is targetShape used? -// layout: function(shape, targetShape) { -// return this._jsonStencil.layout(shape, targetShape); -// }, - // layout property to store events for layouting in plugins - layout: function(shape) { - return this._jsonStencil.layout - }, - - addProperty: function(property, namespace) { - if(property && namespace) { - var oProp = new ORYX.Core.StencilSet.Property(property, namespace, this); - this._properties[oProp.prefix() + "-" + oProp.id()] = oProp; - } - }, - - removeProperty: function(propertyId) { - if(propertyId) { - var oProp = this._properties.values().find(function(prop) { - return (propertyId == prop.id()); - }); - if(oProp) - delete this._properties[oProp.prefix() + "-" + oProp.id()]; - } - }, + // Get all Attributes from the Node + var attributes = $A(prop.attributes) + attributes.each(function (attr) { + property[attr.nodeName] = attr.nodeValue + }); + if (attributes.length > 0) { + properties.push(property) + } + ; - _loadSVGOnSuccess: function(result) { - - var xml = null; - - /* - * We want to get a dom object for the requested file. Unfortunately, - * safari has some issues here. this is meant as a fallback for all - * browsers that don't recognize the svg mimetype as XML but support - * data: urls on Ajax calls. - */ - - // responseXML != undefined. - // if(!(result.responseXML)) - - // get the dom by data: url. - // xml = _evenMoreEvilHack(result.responseText, 'text/xml'); - - // else - - // get it the usual way. - xml = result.responseXML; - - //check if result is a SVG document - if( ORYX.Editor.checkClassType( xml.documentElement, SVGSVGElement )) { - - this._view = xml.documentElement; - - } else { - throw "ORYX.Core.StencilSet.Stencil(_loadSVGOnSuccess): The response is not a SVG document." - } - }, + }); - _loadSVGOnFailure: function(result) { - throw "ORYX.Core.StencilSet.Stencil(_loadSVGOnFailure): Loading SVG document failed." - }, + // Set all Global-Properties to the Properties + properties = properties.concat(globalProperties); - toString: function() { return "Stencil " + this.title() + " (" + this.id() + ")"; } -}; + // Set Properties to Plugin-Data + pluginData['properties'] = properties; -ORYX.Core.StencilSet.Stencil = Clazz.extend(ORYX.Core.StencilSet.Stencil); + // Get the RequieredNodes + var requireNodes = node.getElementsByTagName("requires"); + var requires; + $A(requireNodes).each(function (req) { + var namespace = $A(req.attributes).find(function (attr) { + return attr.name == "namespace" + }) + if (namespace && namespace.nodeValue) { + if (!requires) { + requires = {namespaces: []} + } -/** - * Transform a string into an xml document, the Safari way, as long as - * the nightlies are broken. Even more evil version. - * @param {Object} str - * @param {Object} contentType - */ -function _evenMoreEvilHack(str, contentType) { - - /* - * This even more evil hack was taken from - * http://web-graphics.com/mtarchive/001606.php#chatty004999 - */ - - if (window.ActiveXObject) { - var d = new ActiveXObject("MSXML.DomDocument"); - d.loadXML(str); - return d; - } else if (window.XMLHttpRequest) { - var req = new XMLHttpRequest; - req.open("GET", "data:" + (contentType || "application/xml") + - ";charset=utf-8," + encodeURIComponent(str), false); - if (req.overrideMimeType) { - req.overrideMimeType(contentType); - } - req.send(null); - return req.responseXML; - } -} + requires.namespaces.push(namespace.nodeValue) + } + }); -/** - * Transform a string into an xml document, the Safari way, as long as - * the nightlies are broken. - * @param {Object} result the xml document object. - */ -function _evilSafariHack(serializedXML) { - - /* - * The Dave way. Taken from: - * http://web-graphics.com/mtarchive/001606.php - * - * There is another possibility to parse XML in Safari, by implementing - * the DOMParser in javascript. However, in the latest nightlies of - * WebKit, DOMParser is already available, but still buggy. So, this is - * the best compromise for the time being. - */ - - var xml = serializedXML; - var url = "data:text/xml;charset=utf-8," + encodeURIComponent(xml); - var dom = null; - - // your standard AJAX stuff - var req = new XMLHttpRequest(); - req.open("GET", url); - req.onload = function() { dom = req.responseXML; } - req.send(null); - - return dom; -} - /* - * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. - * License rights for this program may be obtained from Alfresco Software, Ltd. - * pursuant to a written agreement and any use of this program without such an - * agreement is prohibited. - */ -/* - * All code Copyright 2013 KIS Consultancy all rights reserved - */ + // Set Requires to the Plugin-Data, if there is one + if (requires) { + pluginData['requires'] = requires; + } -/** - * Init namespace - */ -if (!ORYX) { - var ORYX = {}; -} -if (!ORYX.Core) { - ORYX.Core = {}; -} -if (!ORYX.Core.StencilSet) { - ORYX.Core.StencilSet = {}; + + // Get the RequieredNodes + var notUsesInNodes = node.getElementsByTagName("notUsesIn"); + var notUsesIn; + $A(notUsesInNodes).each(function (not) { + var namespace = $A(not.attributes).find(function (attr) { + return attr.name == "namespace" + }) + if (namespace && namespace.nodeValue) { + if (!notUsesIn) { + notUsesIn = {namespaces: []} + } + + notUsesIn.namespaces.push(namespace.nodeValue) + } + }); + + // Set Requires to the Plugin-Data, if there is one + if (notUsesIn) { + pluginData['notUsesIn'] = notUsesIn; + } + + + var url = ORYX.PATH + ORYX.CONFIG.PLUGINS_FOLDER + pluginData['source']; + + ORYX.Log.debug("Requireing '%0'", url); + + // Add the Script-Tag to the Site + //Kickstart.require(url); + + ORYX.Log.info("Plugin '%0' successfully loaded.", pluginData['name']); + + // Add the Plugin-Data to all available Plugins + ORYX.availablePlugins.push(pluginData); + + }); + + }, + onFailure: this._loadPluginsOnFails + }); + + }, + + _loadPluginsOnFails: function (result) { + + ORYX.Log.error("Plugin configuration file not available."); + } +}); + + +/* + * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +/* + * All code Copyright 2013 KIS Consultancy all rights reserved + */ + +/** + * Init namespaces + */ +if (!ORYX) { + var ORYX = {}; +} +if (!ORYX.Core) { + ORYX.Core = {}; +} +if (!ORYX.Core.SVG) { + ORYX.Core.SVG = {}; } + /** - * Class Property - * uses Prototpye 1.5.0 - * uses Inheritance + * EditPathHandler + * + * Edit SVG paths' coordinates according to specified from-to movement and + * horizontal and vertical scaling factors. + * The resulting path's d attribute is stored in instance variable d. + * + * @constructor */ -ORYX.Core.StencilSet.Property = Clazz.extend({ +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 = ""; + }, /** - * Constructor + * init + * + * @param {float} x Target point's x-coordinate + * @param {float} y Target point's y-coordinate + * @param {float} oldX Reference point's x-coordinate + * @param {float} oldY Reference point's y-coordinate + * @param {float} deltaWidth Horizontal scaling factor + * @param {float} deltaHeight Vertical scaling factor */ - construct: function(jsonProp, namespace, stencil){ - arguments.callee.$.construct.apply(this, arguments); - - this._jsonProp = jsonProp || ORYX.Log.error("Parameter jsonProp is not defined."); - this._namespace = namespace || ORYX.Log.error("Parameter namespace is not defined."); - this._stencil = stencil || ORYX.Log.error("Parameter stencil is not defined."); - - this._items = {}; - this._complexItems = {}; - - // Flag to indicate whether or not the property should be hidden - // This can be for example when the stencil set is upgraded, but the model - // has a value for that specific property filled in which we still want to show. - // If the value is missing, the property can simply be not shown. - this._hidden = false; - - jsonProp.id = jsonProp.id || ORYX.Log.error("ORYX.Core.StencilSet.Property(construct): Id is not defined."); - jsonProp.id = jsonProp.id.toLowerCase(); - - if (!jsonProp.type) { - ORYX.Log.info("Type is not defined for stencil '%0', id '%1'. Falling back to 'String'.", stencil, jsonProp.id); - jsonProp.type = "string"; - } - else { - jsonProp.type = jsonProp.type.toLowerCase(); - } - - jsonProp.prefix = jsonProp.prefix || "oryx"; - jsonProp.title = jsonProp.title || ""; - jsonProp.value = jsonProp.value || ""; - jsonProp.description = jsonProp.description || ""; - jsonProp.readonly = jsonProp.readonly || false; - jsonProp.optional = jsonProp.optional !== false; - - //init refToView - if (this._jsonProp.refToView) { - if (!(this._jsonProp.refToView instanceof Array)) { - this._jsonProp.refToView = [this._jsonProp.refToView]; - } - } - else { - this._jsonProp.refToView = []; - } - - var globalMin = this.getMinForType(jsonProp.type); - if (jsonProp.min === undefined || jsonProp.min === null) { - jsonProp.min =globalMin; - } else if (jsonProp.min < globalMin) { - jsonProp.min = globalMin; - } - - var globalMax = this.getMaxForType(jsonProp.type); - if (jsonProp.max === undefined || jsonProp.max === null) { - jsonProp.max = globalMax; - } else if (jsonProp.max > globalMax) { - jsonProp.min = globalMax; - } - - if (!jsonProp.fillOpacity) { - jsonProp.fillOpacity = false; - } - - if ("number" != typeof jsonProp.lightness) { - jsonProp.lightness = 1; - } else { - jsonProp.lightness = Math.max(0, Math.min(1, jsonProp.lightness)); - } - - if (!jsonProp.strokeOpacity) { - jsonProp.strokeOpacity = false; - } - - if (jsonProp.length === undefined || jsonProp.length === null) { - jsonProp.length = Number.MAX_VALUE; - } - - if (!jsonProp.wrapLines) { - jsonProp.wrapLines = false; - } - - if (!jsonProp.dateFormat) { - jsonProp.dateFormat = ORYX.I18N.PropertyWindow.dateFormat || "m/d/y"; - } - - if (!jsonProp.fill) { - jsonProp.fill = false; - } - - if (!jsonProp.stroke) { - jsonProp.stroke = false; - } - - if(!jsonProp.inverseBoolean) { - jsonProp.inverseBoolean = false; - } - - if(!jsonProp.directlyEditable && jsonProp.directlyEditable != false) { - jsonProp.directlyEditable = true; - } - - if(jsonProp.visible !== false) { - jsonProp.visible = true; - } - - if(jsonProp.isList !== true) { - jsonProp.isList = false; - - if(!jsonProp.list || !(jsonProp.list instanceof Array)) { - jsonProp.list = []; - } - } - - if(!jsonProp.category) { - if (jsonProp.popular) { - jsonProp.category = "popular"; - } else { - jsonProp.category = "others"; - } - } - - if(!jsonProp.alwaysAppearInMultiselect) { - jsonProp.alwaysAppearInMultiselect = false; - } - - if (jsonProp.type === ORYX.CONFIG.TYPE_CHOICE) { - if (jsonProp.items && jsonProp.items instanceof Array) { - jsonProp.items.each((function(jsonItem){ - // why is the item's value used as the key??? - this._items[jsonItem.value.toLowerCase()] = new ORYX.Core.StencilSet.PropertyItem(jsonItem, namespace, this); - }).bind(this)); - } - else { - throw "ORYX.Core.StencilSet.Property(construct): No property items defined." + init: function (x, y, oldX, oldY, deltaWidth, deltaHeight) { + this.x = x; + this.y = y; + this.oldX = oldX; + this.oldY = oldY; + this.deltaWidth = deltaWidth; + this.deltaHeight = deltaHeight; + + this.d = ""; + }, + + /** + * editPointsAbs + * + * @param {Array} points Array of absolutePoints + */ + editPointsAbs: function (points) { + if (points instanceof Array) { + var newPoints = []; + var x, y; + for (var i = 0; i < points.length; i++) { + x = (parseFloat(points[i]) - this.oldX) * this.deltaWidth + this.x; + i++; + y = (parseFloat(points[i]) - this.oldY) * this.deltaHeight + this.y; + newPoints.push(x); + newPoints.push(y); } - // extended by Kerstin (start) + + return newPoints; + } else { + //TODO error } - else - if (jsonProp.type === ORYX.CONFIG.TYPE_COMPLEX || jsonProp.type == ORYX.CONFIG.TYPE_MULTIPLECOMPLEX) { - if (jsonProp.complexItems && jsonProp.complexItems instanceof Array) { - jsonProp.complexItems.each((function(jsonComplexItem){ - this._complexItems[jsonComplexItem.id.toLowerCase()] = new ORYX.Core.StencilSet.ComplexPropertyItem(jsonComplexItem, namespace, this); - }).bind(this)); - } - } - // extended by Kerstin (end) }, - - getMinForType : function(type) { - if (type.toLowerCase() == ORYX.CONFIG.TYPE_INTEGER) { - return -Math.pow(2,31) - } else { - return -Number.MAX_VALUE+1; - } - }, - getMaxForType : function(type) { - if (type.toLowerCase() == ORYX.CONFIG.TYPE_INTEGER) { - return Math.pow(2,31)-1 - } else { - return Number.MAX_VALUE; - } - }, - + /** - * @param {ORYX.Core.StencilSet.Property} property - * @return {Boolean} True, if property has the same namespace and id. + * editPointsRel + * + * @param {Array} points Array of absolutePoints */ - equals: function(property){ - return (this._namespace === property.namespace() && - this.id() === property.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(value) { - this._jsonProp.category = value; - }, - - 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"); + editPointsRel: function (points) { + if (points instanceof Array) { + var newPoints = []; + var x, y; + for (var i = 0; i < points.length; i++) { + x = parseFloat(points[i]) * this.deltaWidth; + i++; + y = parseFloat(points[i]) * this.deltaHeight; + newPoints.push(x); + newPoints.push(y); + } + + return newPoints; + } else { + //TODO error + } }, - + /** - * An optional link to a SVG element so that the property affects the - * graphical representation of the stencil. + * arcAbs - A + * + * @param {Number} rx + * @param {Number} ry + * @param {Number} xAxisRotation + * @param {Boolean} largeArcFlag + * @param {Boolean} sweepFlag + * @param {Number} x + * @param {Number} y */ - refToView: function(){ - return this._jsonProp.refToView; + arcAbs: function (rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) { + var pointsAbs = this.editPointsAbs([x, y]); + var pointsRel = this.editPointsRel([rx, ry]); + + this.d = this.d.concat(" A" + pointsRel[0] + " " + pointsRel[1] + + " " + xAxisRotation + " " + largeArcFlag + + " " + sweepFlag + " " + pointsAbs[0] + " " + + pointsAbs[1] + " "); }, - + /** - * If type is integer or float, min is the lower bounds of value. + * arcRel - a + * + * @param {Number} rx + * @param {Number} ry + * @param {Number} xAxisRotation + * @param {Boolean} largeArcFlag + * @param {Boolean} sweepFlag + * @param {Number} x + * @param {Number} y */ - min: function(){ - return this._jsonProp.min; + arcRel: function (rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) { + var pointsRel = this.editPointsRel([rx, ry, x, y]); + + this.d = this.d.concat(" a" + pointsRel[0] + " " + pointsRel[1] + + " " + xAxisRotation + " " + largeArcFlag + + " " + sweepFlag + " " + pointsRel[2] + " " + + pointsRel[3] + " "); }, - + /** - * If type ist integer or float, max is the upper bounds of value. + * curvetoCubicAbs - C + * + * @param {Number} x1 + * @param {Number} y1 + * @param {Number} x2 + * @param {Number} y2 + * @param {Number} x + * @param {Number} y */ - max: function(){ - return this._jsonProp.max; + curvetoCubicAbs: function (x1, y1, x2, y2, x, y) { + var pointsAbs = this.editPointsAbs([x1, y1, x2, y2, x, y]); + + this.d = this.d.concat(" C" + pointsAbs[0] + " " + pointsAbs[1] + + " " + pointsAbs[2] + " " + pointsAbs[3] + + " " + pointsAbs[4] + " " + pointsAbs[5] + " "); }, - + /** - * If type is float, this method returns if the fill-opacity property should - * be set. - * @return {Boolean} + * curvetoCubicRel - c + * + * @param {Number} x1 + * @param {Number} y1 + * @param {Number} x2 + * @param {Number} y2 + * @param {Number} x + * @param {Number} y */ - fillOpacity: function(){ - return this._jsonProp.fillOpacity; + curvetoCubicRel: function (x1, y1, x2, y2, x, y) { + var pointsRel = this.editPointsRel([x1, y1, x2, y2, x, y]); + + this.d = this.d.concat(" c" + pointsRel[0] + " " + pointsRel[1] + + " " + pointsRel[2] + " " + pointsRel[3] + + " " + pointsRel[4] + " " + pointsRel[5] + " "); }, - + /** - * If type is float, this method returns if the stroke-opacity property should - * be set. - * @return {Boolean} + * linetoHorizontalAbs - H + * + * @param {Number} x */ - strokeOpacity: function(){ - return this._jsonProp.strokeOpacity; + linetoHorizontalAbs: function (x) { + var pointsAbs = this.editPointsAbs([x, 0]); + + this.d = this.d.concat(" H" + pointsAbs[0] + " "); }, - + /** - * If type is string or richtext, length is the maximum length of the text. - * TODO how long can a string be. + * linetoHorizontalRel - h + * + * @param {Number} x */ - length: function(){ - return this._jsonProp.length ? this._jsonProp.length : Number.MAX_VALUE; - }, - - wrapLines: function(){ - return this._jsonProp.wrapLines; + linetoHorizontalRel: function (x) { + var pointsRel = this.editPointsRel([x, 0]); + + this.d = this.d.concat(" h" + pointsRel[0] + " "); }, - + /** - * If type is date, dateFormat specifies the format of the date. The format - * specification of the ext library is used: - * - * Format Output Description - * ------ ---------- -------------------------------------------------------------- - * d 10 Day of the month, 2 digits with leading zeros - * D Wed A textual representation of a day, three letters - * j 10 Day of the month without leading zeros - * l Wednesday A full textual representation of the day of the week - * S th English ordinal day of month suffix, 2 chars (use with j) - * w 3 Numeric representation of the day of the week - * z 9 The julian date, or day of the year (0-365) - * W 01 ISO-8601 2-digit week number of year, weeks starting on Monday (00-52) - * F January A full textual representation of the month - * m 01 Numeric representation of a month, with leading zeros - * M Jan Month name abbreviation, three letters - * n 1 Numeric representation of a month, without leading zeros - * t 31 Number of days in the given month - * L 0 Whether its a leap year (1 if it is a leap year, else 0) - * Y 2007 A full numeric representation of a year, 4 digits - * y 07 A two digit representation of a year - * a pm Lowercase Ante meridiem and Post meridiem - * A PM Uppercase Ante meridiem and Post meridiem - * g 3 12-hour format of an hour without leading zeros - * G 15 24-hour format of an hour without leading zeros - * h 03 12-hour format of an hour with leading zeros - * H 15 24-hour format of an hour with leading zeros - * i 05 Minutes with leading zeros - * s 01 Seconds, with leading zeros - * O -0600 Difference to Greenwich time (GMT) in hours - * T CST Timezone setting of the machine running the code - * Z -21600 Timezone offset in seconds (negative if west of UTC, positive if east) + * linetoAbs - L * - * Example: - * F j, Y, g:i a -> January 10, 2007, 3:05 pm + * @param {Number} x + * @param {Number} y */ - dateFormat: function(){ - return this._jsonProp.dateFormat; + linetoAbs: function (x, y) { + var pointsAbs = this.editPointsAbs([x, y]); + + this.d = this.d.concat(" L" + pointsAbs[0] + " " + pointsAbs[1] + " "); }, - + /** - * If type is color, this method returns if the fill property should - * be set. - * @return {Boolean} + * linetoRel - l + * + * @param {Number} x + * @param {Number} y */ - fill: function(){ - return this._jsonProp.fill; + linetoRel: function (x, y) { + var pointsRel = this.editPointsRel([x, y]); + + this.d = this.d.concat(" l" + pointsRel[0] + " " + pointsRel[1] + " "); }, - - /** - * Lightness defines the satiation of the color - * 0 is the pure color - * 1 is white - * @return {Integer} lightness - */ - lightness: function(){ - return this._jsonProp.lightness; - }, - + /** - * If type is color, this method returns if the stroke property should - * be set. - * @return {Boolean} + * movetoAbs - M + * + * @param {Number} x + * @param {Number} y */ - stroke: function(){ - return this._jsonProp.stroke; + movetoAbs: function (x, y) { + var pointsAbs = this.editPointsAbs([x, y]); + + this.d = this.d.concat(" M" + pointsAbs[0] + " " + pointsAbs[1] + " "); }, - + /** - * If type is choice, items is a hash map with all alternative values - * (PropertyItem objects) with id as keys. + * movetoRel - m + * + * @param {Number} x + * @param {Number} y */ - items: function(){ - return $H(this._items).values(); + movetoRel: function (x, y) { + var pointsRel; + if (this.d === "") { + pointsRel = this.editPointsAbs([x, y]); + } else { + pointsRel = this.editPointsRel([x, y]); + } + + this.d = this.d.concat(" m" + pointsRel[0] + " " + pointsRel[1] + " "); }, - - item: function(value){ - if (value) { - return this._items[value.toLowerCase()]; - } else { - return null; - } + + /** + * curvetoQuadraticAbs - Q + * + * @param {Number} x1 + * @param {Number} y1 + * @param {Number} x + * @param {Number} y + */ + curvetoQuadraticAbs: function (x1, y1, x, y) { + var pointsAbs = this.editPointsAbs([x1, y1, x, y]); + + this.d = this.d.concat(" Q" + pointsAbs[0] + " " + pointsAbs[1] + " " + + pointsAbs[2] + " " + pointsAbs[3] + " "); }, - - toString: function(){ - return "Property " + this.title() + " (" + this.id() + ")"; + + /** + * curvetoQuadraticRel - q + * + * @param {Number} x1 + * @param {Number} y1 + * @param {Number} x + * @param {Number} y + */ + curvetoQuadraticRel: function (x1, y1, x, y) { + var pointsRel = this.editPointsRel([x1, y1, x, y]); + + this.d = this.d.concat(" q" + pointsRel[0] + " " + pointsRel[1] + " " + + pointsRel[2] + " " + pointsRel[3] + " "); }, - - complexItems: function(){ - return $H(this._complexItems).values(); + + /** + * curvetoCubicSmoothAbs - S + * + * @param {Number} x2 + * @param {Number} y2 + * @param {Number} x + * @param {Number} y + */ + curvetoCubicSmoothAbs: function (x2, y2, x, y) { + var pointsAbs = this.editPointsAbs([x2, y2, x, y]); + + this.d = this.d.concat(" S" + pointsAbs[0] + " " + pointsAbs[1] + " " + + pointsAbs[2] + " " + pointsAbs[3] + " "); }, - - complexItem: function(id){ - if(id) { - return this._complexItems[id.toLowerCase()]; - } else { - return null; - } - + + /** + * curvetoCubicSmoothRel - s + * + * @param {Number} x2 + * @param {Number} y2 + * @param {Number} x + * @param {Number} y + */ + curvetoCubicSmoothRel: function (x2, y2, x, y) { + var pointsRel = this.editPointsRel([x2, y2, x, y]); + + this.d = this.d.concat(" s" + pointsRel[0] + " " + pointsRel[1] + " " + + pointsRel[2] + " " + pointsRel[3] + " "); }, - - complexAttributeToView: function(){ - return this._jsonProp.complexAttributeToView || ""; + + /** + * curvetoQuadraticSmoothAbs - T + * + * @param {Number} x + * @param {Number} y + */ + curvetoQuadraticSmoothAbs: function (x, y) { + var pointsAbs = this.editPointsAbs([x, y]); + + this.d = this.d.concat(" T" + pointsAbs[0] + " " + pointsAbs[1] + " "); }, - - isList: function() { - return !!this._jsonProp.isList; + + /** + * curvetoQuadraticSmoothRel - t + * + * @param {Number} x + * @param {Number} y + */ + curvetoQuadraticSmoothRel: function (x, y) { + var pointsRel = this.editPointsRel([x, y]); + + this.d = this.d.concat(" t" + pointsRel[0] + " " + pointsRel[1] + " "); + }, + + /** + * linetoVerticalAbs - V + * + * @param {Number} y + */ + linetoVerticalAbs: function (y) { + var pointsAbs = this.editPointsAbs([0, y]); + + this.d = this.d.concat(" V" + pointsAbs[1] + " "); }, - - getListItems: function() { - return this._jsonProp.list; + + /** + * linetoVerticalRel - v + * + * @param {Number} y + */ + linetoVerticalRel: function (y) { + var pointsRel = this.editPointsRel([0, y]); + + this.d = this.d.concat(" v" + pointsRel[1] + " "); }, - - /** - * If type is glossary link, the - * type of category can be defined where - * the link only can go to. - * @return {String} The glossary category id - */ - 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; - } - -}); -/* + + /** + * closePath - z or Z + */ + closePath: function () { + this.d = this.d.concat(" z"); + } + +});/* * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. * License rights for this program may be obtained from Alfresco Software, Ltd. * pursuant to a written agreement and any use of this program without such an @@ -6604,215 +2890,283 @@ ORYX.Core.StencilSet.Property = Clazz.extend({ */ /** - * Init namespace + * Init namespaces */ -if(!ORYX) {var ORYX = {};} -if(!ORYX.Core) {ORYX.Core = {};} -if(!ORYX.Core.StencilSet) {ORYX.Core.StencilSet = {};} +if (!ORYX) { + var ORYX = {}; +} +if (!ORYX.Core) { + ORYX.Core = {}; +} +if (!ORYX.Core.SVG) { + ORYX.Core.SVG = {}; +} + /** - * Class Stencil - * uses Prototpye 1.5.0 - * uses Inheritance + * MinMaxPathHandler + * + * Determine the minimum and maximum of a SVG path's absolute coordinates. + * For relative coordinates the absolute value is computed for consideration. + * The values are stored in attributes minX, minY, maxX, and maxY. + * + * @constructor */ -ORYX.Core.StencilSet.PropertyItem = Clazz.extend({ +ORYX.Core.SVG.MinMaxPathHandler = Clazz.extend({ - /** - * Constructor - */ - construct: function(jsonItem, namespace, property) { - arguments.callee.$.construct.apply(this, arguments); + construct: function () { + arguments.callee.$.construct.apply(this, arguments); - if(!jsonItem) { - throw "ORYX.Core.StencilSet.PropertyItem(construct): Parameter jsonItem is not defined."; - } - if(!namespace) { - throw "ORYX.Core.StencilSet.PropertyItem(construct): Parameter namespace is not defined."; - } - if(!property) { - throw "ORYX.Core.StencilSet.PropertyItem(construct): Parameter property is not defined."; - } - - this._jsonItem = jsonItem; - this._namespace = namespace; - this._property = property; - - //init all values - if(!jsonItem.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 = []; - } - }, + this.minX = undefined; + this.minY = undefined; + this.maxX = undefined; + this.maxY = undefined; - /** - * @param {ORYX.Core.StencilSet.PropertyItem} item - * @return {Boolean} True, if item has the same namespace and id. - */ - equals: function(item) { - return (this.property().equals(item.property()) && - this.value() === item.value()); - }, + this._lastAbsX = undefined; + this._lastAbsY = undefined; + }, - namespace: function() { - return this._namespace; - }, + /** + * Store minimal and maximal coordinates of passed points to attributes minX, maxX, minY, maxY + * + * @param {Array} points Array of absolutePoints + */ + calculateMinMax: function (points) { + if (points instanceof Array) { + var x, y; + for (var i = 0; i < points.length; i++) { + x = parseFloat(points[i]); + i++; + y = parseFloat(points[i]); + + this.minX = (this.minX !== undefined) ? Math.min(this.minX, x) : x; + this.maxX = (this.maxX !== undefined) ? Math.max(this.maxX, x) : x; + this.minY = (this.minY !== undefined) ? Math.min(this.minY, y) : y; + this.maxY = (this.maxY !== undefined) ? Math.max(this.maxY, y) : y; + + this._lastAbsX = x; + this._lastAbsY = y; + } + } else { + //TODO error + } + }, - property: function() { - return this._property; - }, + /** + * arcAbs - A + * + * @param {Number} rx + * @param {Number} ry + * @param {Number} xAxisRotation + * @param {Boolean} largeArcFlag + * @param {Boolean} sweepFlag + * @param {Number} x + * @param {Number} y + */ + arcAbs: function (rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) { + this.calculateMinMax([x, y]); + }, - value: function() { - return this._jsonItem.value; - }, - - title: function() { - return ORYX.Core.StencilSet.getTranslation(this._jsonItem, "title"); - }, + /** + * arcRel - a + * + * @param {Number} rx + * @param {Number} ry + * @param {Number} xAxisRotation + * @param {Boolean} largeArcFlag + * @param {Boolean} sweepFlag + * @param {Number} x + * @param {Number} y + */ + arcRel: function (rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) { + this.calculateMinMax([this._lastAbsX + x, this._lastAbsY + y]); + }, - refToView: function() { - return this._jsonItem.refToView; - }, - - icon: function() { - return (this._jsonItem.icon) ? this.property().stencil()._source + "icons/" + this._jsonItem.icon : ""; - }, + /** + * curvetoCubicAbs - C + * + * @param {Number} x1 + * @param {Number} y1 + * @param {Number} x2 + * @param {Number} y2 + * @param {Number} x + * @param {Number} y + */ + curvetoCubicAbs: function (x1, y1, x2, y2, x, y) { + this.calculateMinMax([x1, y1, x2, y2, x, y]); + }, - toString: function() { return "PropertyItem " + this.property() + " (" + this.value() + ")"; } -});/* - * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. - * License rights for this program may be obtained from Alfresco Software, Ltd. - * pursuant to a written agreement and any use of this program without such an - * agreement is prohibited. - */ -/* - * All code Copyright 2013 KIS Consultancy all rights reserved - */ + /** + * curvetoCubicRel - c + * + * @param {Number} x1 + * @param {Number} y1 + * @param {Number} x2 + * @param {Number} y2 + * @param {Number} x + * @param {Number} y + */ + curvetoCubicRel: function (x1, y1, x2, y2, x, y) { + this.calculateMinMax([this._lastAbsX + x1, this._lastAbsY + y1, + this._lastAbsX + x2, this._lastAbsY + y2, + this._lastAbsX + x, this._lastAbsY + y]); + }, -/** - * Init namespaces - */ -if(!ORYX) {var ORYX = {};} -if(!ORYX.Core) {ORYX.Core = {};} -if(!ORYX.Core.StencilSet) {ORYX.Core.StencilSet = {};} + /** + * linetoHorizontalAbs - H + * + * @param {Number} x + */ + linetoHorizontalAbs: function (x) { + this.calculateMinMax([x, this._lastAbsY]); + }, -/** - * Class Stencil - * uses Prototpye 1.5.0 - * uses Inheritance - */ -ORYX.Core.StencilSet.ComplexPropertyItem = Clazz.extend({ + /** + * linetoHorizontalRel - h + * + * @param {Number} x + */ + linetoHorizontalRel: function (x) { + this.calculateMinMax([this._lastAbsX + x, this._lastAbsY]); + }, - /** - * Constructor - */ - construct: function(jsonItem, namespace, property) { - arguments.callee.$.construct.apply(this, arguments); + /** + * linetoAbs - L + * + * @param {Number} x + * @param {Number} y + */ + linetoAbs: function (x, y) { + this.calculateMinMax([x, y]); + }, - if(!jsonItem) { - throw "ORYX.Core.StencilSet.ComplexPropertyItem(construct): Parameter jsonItem is not defined."; - } - if(!namespace) { - throw "ORYX.Core.StencilSet.ComplexPropertyItem(construct): Parameter namespace is not defined."; - } - if(!property) { - throw "ORYX.Core.StencilSet.ComplexPropertyItem(construct): Parameter property is not defined."; - } - - this._jsonItem = jsonItem; - this._namespace = namespace; - this._property = property; - this._items = new Hash(); - this._complexItems = new Hash(); - - //init all values - if(!jsonItem.name) { - throw "ORYX.Core.StencilSet.ComplexPropertyItem(construct): Name is not defined."; - } - - if(!jsonItem.type) { - throw "ORYX.Core.StencilSet.ComplexPropertyItem(construct): Type is not defined."; - } else { - jsonItem.type = jsonItem.type.toLowerCase(); - } - - if(jsonItem.type === ORYX.CONFIG.TYPE_CHOICE) { - if(jsonItem.items && jsonItem.items instanceof Array) { - jsonItem.items.each((function(item) { - this._items[item.value] = new ORYX.Core.StencilSet.PropertyItem(item, namespace, this); - }).bind(this)); - } else { - throw "ORYX.Core.StencilSet.Property(construct): No property items defined." - } - } else if(jsonItem.type === ORYX.CONFIG.TYPE_COMPLEX) { - if(jsonItem.complexItems && jsonItem.complexItems instanceof Array) { - jsonItem.complexItems.each((function(complexItem) { - this._complexItems[complexItem.id] = new ORYX.Core.StencilSet.ComplexPropertyItem(complexItem, namespace, this); - }).bind(this)); - } else { - throw "ORYX.Core.StencilSet.Property(construct): No property items defined." - } - } - }, + /** + * linetoRel - l + * + * @param {Number} x + * @param {Number} y + */ + linetoRel: function (x, y) { + this.calculateMinMax([this._lastAbsX + x, this._lastAbsY + y]); + }, - /** - * @param {ORYX.Core.StencilSet.PropertyItem} item - * @return {Boolean} True, if item has the same namespace and id. - */ - equals: function(item) { - return (this.property().equals(item.property()) && - this.name() === item.name()); - }, + /** + * movetoAbs - M + * + * @param {Number} x + * @param {Number} y + */ + movetoAbs: function (x, y) { + this.calculateMinMax([x, y]); + }, - namespace: function() { - return this._namespace; - }, + /** + * movetoRel - m + * + * @param {Number} x + * @param {Number} y + */ + movetoRel: function (x, y) { + if (this._lastAbsX && this._lastAbsY) { + this.calculateMinMax([this._lastAbsX + x, this._lastAbsY + y]); + } else { + this.calculateMinMax([x, y]); + } + }, - property: function() { - return this._property; - }, + /** + * curvetoQuadraticAbs - Q + * + * @param {Number} x1 + * @param {Number} y1 + * @param {Number} x + * @param {Number} y + */ + curvetoQuadraticAbs: function (x1, y1, x, y) { + this.calculateMinMax([x1, y1, x, y]); + }, + + /** + * curvetoQuadraticRel - q + * + * @param {Number} x1 + * @param {Number} y1 + * @param {Number} x + * @param {Number} y + */ + curvetoQuadraticRel: function (x1, y1, x, y) { + this.calculateMinMax([this._lastAbsX + x1, this._lastAbsY + y1, this._lastAbsX + x, this._lastAbsY + y]); + }, + + /** + * curvetoCubicSmoothAbs - S + * + * @param {Number} x2 + * @param {Number} y2 + * @param {Number} x + * @param {Number} y + */ + curvetoCubicSmoothAbs: function (x2, y2, x, y) { + this.calculateMinMax([x2, y2, x, y]); + }, + + /** + * curvetoCubicSmoothRel - s + * + * @param {Number} x2 + * @param {Number} y2 + * @param {Number} x + * @param {Number} y + */ + curvetoCubicSmoothRel: function (x2, y2, x, y) { + this.calculateMinMax([this._lastAbsX + x2, this._lastAbsY + y2, this._lastAbsX + x, this._lastAbsY + y]); + }, + + /** + * curvetoQuadraticSmoothAbs - T + * + * @param {Number} x + * @param {Number} y + */ + curvetoQuadraticSmoothAbs: function (x, y) { + this.calculateMinMax([x, y]); + }, + + /** + * curvetoQuadraticSmoothRel - t + * + * @param {Number} x + * @param {Number} y + */ + curvetoQuadraticSmoothRel: function (x, y) { + this.calculateMinMax([this._lastAbsX + x, this._lastAbsY + y]); + }, + + /** + * linetoVerticalAbs - V + * + * @param {Number} y + */ + linetoVerticalAbs: function (y) { + this.calculateMinMax([this._lastAbsX, y]); + }, + + /** + * linetoVerticalRel - v + * + * @param {Number} y + */ + linetoVerticalRel: function (y) { + this.calculateMinMax([this._lastAbsX, this._lastAbsY + y]); + }, + + /** + * closePath - z or Z + */ + closePath: function () { + return;// do nothing + } - 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; - } });/* * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. * License rights for this program may be obtained from Alfresco Software, Ltd. @@ -6826,1308 +3180,276 @@ ORYX.Core.StencilSet.ComplexPropertyItem = Clazz.extend({ /** * Init namespaces */ -if(!ORYX) {var ORYX = {};} -if(!ORYX.Core) {ORYX.Core = {};} -if(!ORYX.Core.StencilSet) {ORYX.Core.StencilSet = {};} +if (!ORYX) { + var ORYX = {}; +} +if (!ORYX.Core) { + ORYX.Core = {}; +} +if (!ORYX.Core.SVG) { + ORYX.Core.SVG = {}; +} + /** - * Class Rules uses Prototpye 1.5.0 uses Inheritance - * - * This class implements the API to check the stencil sets' rules. + * PathHandler + * + * Determine absolute points of a SVG path. The coordinates are stored + * sequentially in the attribute points (x-coordinates at even indices, + * y-coordinates at odd indices). + * + * @constructor */ -ORYX.Core.StencilSet.Rules = { +ORYX.Core.SVG.PointsPathHandler = Clazz.extend({ - /** - * Constructor - */ - 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(); - }, - - /** - * Call this method to initialize the rules for a stencil set and all of its - * active extensions. - * - * @param {Object} - * stencilSet - */ - initializeRules: function(stencilSet) { - - var existingSS = this._stencilSets.find(function(ss) { - return (ss.namespace() == stencilSet.namespace()); - }); - if (existingSS) { - // reinitialize all rules - var stencilsets = this._stencilSets.clone(); - stencilsets = stencilsets.without(existingSS); - stencilsets.push(stencilSet); - - 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(); - - stencilsets.each(function(ss){ - this.initializeRules(ss); - }.bind(this)); - return; - } - else { - this._stencilSets.push(stencilSet); - - var jsonRules = new Hash(stencilSet.jsonRules()); - var namespace = stencilSet.namespace(); - var stencils = stencilSet.stencils(); - - stencilSet.extensions().values().each(function(extension) { - if(extension.rules) { - if(extension.rules.connectionRules) - jsonRules.connectionRules = jsonRules.connectionRules.concat(extension.rules.connectionRules); - if(extension.rules.cardinalityRules) - jsonRules.cardinalityRules = jsonRules.cardinalityRules.concat(extension.rules.cardinalityRules); - if(extension.rules.containmentRules) - jsonRules.containmentRules = jsonRules.containmentRules.concat(extension.rules.containmentRules); - if(extension.rules.morphingRules) - jsonRules.morphingRules = jsonRules.morphingRules.concat(extension.rules.morphingRules); - } - if(extension.stencils) - stencils = stencils.concat(extension.stencils); - }); - - this._stencils = this._stencils.concat(stencilSet.stencils()); - - // init connection rules - var cr = this._connectionRules; - if (jsonRules.connectionRules) { - jsonRules.connectionRules.each((function(rules){ - if (this._isRoleOfOtherNamespace(rules.role)) { - if (!cr[rules.role]) { - cr[rules.role] = new Hash(); - } - } - else { - if (!cr[namespace + rules.role]) - cr[namespace + rules.role] = new Hash(); - } - - rules.connects.each((function(connect){ - var toRoles = []; - if (connect.to) { - if (!(connect.to instanceof Array)) { - connect.to = [connect.to]; - } - connect.to.each((function(to){ - if (this._isRoleOfOtherNamespace(to)) { - toRoles.push(to); - } - else { - toRoles.push(namespace + to); - } - }).bind(this)); - } - - var role, from; - if (this._isRoleOfOtherNamespace(rules.role)) - role = rules.role; - else - role = namespace + rules.role; - - if (this._isRoleOfOtherNamespace(connect.from)) - from = connect.from; - else - from = namespace + connect.from; - - if (!cr[role][from]) - cr[role][from] = toRoles; - else - cr[role][from] = cr[role][from].concat(toRoles); - - }).bind(this)); - }).bind(this)); - } - - // init cardinality rules - var cardr = this._cardinalityRules; - if (jsonRules.cardinalityRules) { - jsonRules.cardinalityRules.each((function(rules){ - var cardrKey; - if (this._isRoleOfOtherNamespace(rules.role)) { - cardrKey = rules.role; - } - else { - cardrKey = namespace + rules.role; - } - - if (!cardr[cardrKey]) { - cardr[cardrKey] = {}; - for (i in rules) { - cardr[cardrKey][i] = rules[i]; - } - } - - var oe = new Hash(); - if (rules.outgoingEdges) { - rules.outgoingEdges.each((function(rule){ - if (this._isRoleOfOtherNamespace(rule.role)) { - oe[rule.role] = rule; - } - else { - oe[namespace + rule.role] = rule; - } - }).bind(this)); - } - cardr[cardrKey].outgoingEdges = oe; - var ie = new Hash(); - if (rules.incomingEdges) { - rules.incomingEdges.each((function(rule){ - if (this._isRoleOfOtherNamespace(rule.role)) { - ie[rule.role] = rule; - } - else { - ie[namespace + rule.role] = rule; - } - }).bind(this)); - } - cardr[cardrKey].incomingEdges = ie; - }).bind(this)); - } - - // init containment rules - var conr = this._containmentRules; - if (jsonRules.containmentRules) { - jsonRules.containmentRules.each((function(rules){ - var conrKey; - if (this._isRoleOfOtherNamespace(rules.role)) { - conrKey = rules.role; - } - else { - this._containerStencils.push(namespace + rules.role); - conrKey = namespace + rules.role; - } - if (!conr[conrKey]) { - conr[conrKey] = []; - } - (rules.contains||[]).each((function(containRole){ - if (this._isRoleOfOtherNamespace(containRole)) { - conr[conrKey].push(containRole); - } - else { - conr[conrKey].push(namespace + containRole); - } - }).bind(this)); - }).bind(this)); - } - - // init morphing rules - var morphr = this._morphingRules; - if (jsonRules.morphingRules) { - jsonRules.morphingRules.each((function(rules){ - var morphrKey; - if (this._isRoleOfOtherNamespace(rules.role)) { - morphrKey = rules.role; - } - else { - morphrKey = namespace + rules.role; - } - if (!morphr[morphrKey]) { - morphr[morphrKey] = []; - } - if(!rules.preserveBounds) { - rules.preserveBounds = false; - } - rules.baseMorphs.each((function(baseMorphStencilId){ - var morphStencil = this._getStencilById(namespace + baseMorphStencilId); - if(morphStencil) { - morphr[morphrKey].push(morphStencil); - } - }).bind(this)); - }).bind(this)); - } - - // init layouting rules - var layoutRules = this._layoutRules; - if (jsonRules.layoutRules) { - - var getDirections = function(o){ - return { - "edgeRole":o.edgeRole||undefined, - "t": o["t"]||1, - "r": o["r"]||1, - "b": o["b"]||1, - "l": o["l"]||1 - } - } - - jsonRules.layoutRules.each(function(rules){ - var layoutKey; - if (this._isRoleOfOtherNamespace(rules.role)) { - layoutKey = rules.role; - } - else { - layoutKey = namespace + rules.role; - } - if (!layoutRules[layoutKey]) { - layoutRules[layoutKey] = {}; - } - if (rules["in"]){ - layoutRules[layoutKey]["in"] = getDirections(rules["in"]); - } - if (rules["ins"]){ - layoutRules[layoutKey]["ins"] = (rules["ins"]||[]).map(function(e){ return getDirections(e) }) - } - if (rules["out"]) { - layoutRules[layoutKey]["out"] = getDirections(rules["out"]); - } - if (rules["outs"]){ - layoutRules[layoutKey]["outs"] = (rules["outs"]||[]).map(function(e){ return getDirections(e) }) - } - }.bind(this)); - } - } - }, - - _getStencilById: function(id) { - return this._stencils.find(function(stencil) { - return stencil.id()==id; - }); - }, - - _cacheConnect: function(args) { - result = this._canConnect(args); - - if (args.sourceStencil && args.targetStencil) { - var source = this._cachedConnectSET[args.sourceStencil.id()]; - - if(!source) { - source = new Hash(); - this._cachedConnectSET[args.sourceStencil.id()] = source; - } - - var edge = source[args.edgeStencil.id()]; - - if(!edge) { - edge = new Hash(); - source[args.edgeStencil.id()] = edge; - } - - edge[args.targetStencil.id()] = result; - - } else if (args.sourceStencil) { - var source = this._cachedConnectSE[args.sourceStencil.id()]; - - if(!source) { - source = new Hash(); - this._cachedConnectSE[args.sourceStencil.id()] = source; - } - - source[args.edgeStencil.id()] = result; + construct: function () { + arguments.callee.$.construct.apply(this, arguments); - } else { - var target = this._cachedConnectTE[args.targetStencil.id()]; - - if(!target) { - target = new Hash(); - this._cachedConnectTE[args.targetStencil.id()] = target; - } - - target[args.edgeStencil.id()] = result; - } - - return result; - }, - - _cacheCard: function(args) { - - if(args.sourceStencil) { - var source = this._cachedCardSE[args.sourceStencil.id()] - - if(!source) { - source = new Hash(); - this._cachedCardSE[args.sourceStencil.id()] = source; - } - - var max = this._getMaximumNumberOfOutgoingEdge(args); - if(max == undefined) - max = -1; - - source[args.edgeStencil.id()] = max; - } - - if(args.targetStencil) { - var target = this._cachedCardTE[args.targetStencil.id()] - - if(!target) { - target = new Hash(); - this._cachedCardTE[args.targetStencil.id()] = target; - } - - var max = this._getMaximumNumberOfIncomingEdge(args); - if(max == undefined) - max = -1; - - target[args.edgeStencil.id()] = max; - } - }, - - _cacheContain: function(args) { - - var result = [this._canContain(args), - this._getMaximumOccurrence(args.containingStencil, args.containedStencil)] - - if(result[1] == undefined) - result[1] = -1; - - var children = this._cachedContainPC[args.containingStencil.id()]; - - if(!children) { - children = new Hash(); - this._cachedContainPC[args.containingStencil.id()] = children; - } - - children[args.containedStencil.id()] = result; - - return result; - }, - - /** - * Returns all stencils belonging to a morph group. (calculation result is - * cached) - */ - _cacheMorph: function(role) { - - var morphs = this._cachedMorphRS[role]; - - if(!morphs) { - morphs = []; - - if(this._morphingRules.keys().include(role)) { - morphs = this._stencils.select(function(stencil) { - return stencil.roles().include(role); - }); - } - - this._cachedMorphRS[role] = morphs; - } - return morphs; - }, - - /** Begin connection rules' methods */ - - /** - * - * @param {Object} - * args sourceStencil: ORYX.Core.StencilSet.Stencil | undefined - * sourceShape: ORYX.Core.Shape | undefined - * - * At least sourceStencil or sourceShape has to be specified - * - * @return {Array} Array of stencils of edges that can be outgoing edges of - * the source. - */ - outgoingEdgeStencils: function(args) { - // check arguments - if(!args.sourceShape && !args.sourceStencil) { - return []; - } - - // init arguments - if(args.sourceShape) { - args.sourceStencil = args.sourceShape.getStencil(); - } - - var _edges = []; - - // test each edge, if it can connect to source - this._stencils.each((function(stencil) { - if(stencil.type() === "edge") { - var newArgs = Object.clone(args); - newArgs.edgeStencil = stencil; - if(this.canConnect(newArgs)) { - _edges.push(stencil); - } - } - }).bind(this)); + this.points = []; - return _edges; - }, + this._lastAbsX = undefined; + this._lastAbsY = undefined; + }, - /** - * - * @param {Object} - * args targetStencil: ORYX.Core.StencilSet.Stencil | undefined - * targetShape: ORYX.Core.Shape | undefined - * - * At least targetStencil or targetShape has to be specified - * - * @return {Array} Array of stencils of edges that can be incoming edges of - * the target. - */ - incomingEdgeStencils: function(args) { - // check arguments - if(!args.targetShape && !args.targetStencil) { - return []; - } - - // init arguments - if(args.targetShape) { - args.targetStencil = args.targetShape.getStencil(); - } - - var _edges = []; - - // test each edge, if it can connect to source - this._stencils.each((function(stencil) { - if(stencil.type() === "edge") { - var newArgs = Object.clone(args); - newArgs.edgeStencil = stencil; - if(this.canConnect(newArgs)) { - _edges.push(stencil); - } - } - }).bind(this)); + /** + * addPoints + * + * @param {Array} points Array of absolutePoints + */ + addPoints: function (points) { + if (points instanceof Array) { + var x, y; + for (var i = 0; i < points.length; i++) { + x = parseFloat(points[i]); + i++; + y = parseFloat(points[i]); + + this.points.push(x); + this.points.push(y); + //this.points.push({x:x, y:y}); + + this._lastAbsX = x; + this._lastAbsY = y; + } + } else { + //TODO error + } + }, - return _edges; - }, - - /** - * - * @param {Object} - * args edgeStencil: ORYX.Core.StencilSet.Stencil | undefined - * edgeShape: ORYX.Core.Edge | undefined targetStencil: - * ORYX.Core.StencilSet.Stencil | undefined targetShape: - * ORYX.Core.Node | undefined - * - * At least edgeStencil or edgeShape has to be specified!!! - * - * @return {Array} Returns an array of stencils that can be source of the - * specified edge. - */ - sourceStencils: function(args) { - // check arguments - if(!args || - !args.edgeShape && !args.edgeStencil) { - return []; - } - - // init arguments - if(args.targetShape) { - args.targetStencil = args.targetShape.getStencil(); - } - - if(args.edgeShape) { - args.edgeStencil = args.edgeShape.getStencil(); - } - - var _sources = []; - - // check each stencil, if it can be a source - this._stencils.each((function(stencil) { - var newArgs = Object.clone(args); - newArgs.sourceStencil = stencil; - if(this.canConnect(newArgs)) { - _sources.push(stencil); - } - }).bind(this)); + /** + * arcAbs - A + * + * @param {Number} rx + * @param {Number} ry + * @param {Number} xAxisRotation + * @param {Boolean} largeArcFlag + * @param {Boolean} sweepFlag + * @param {Number} x + * @param {Number} y + */ + arcAbs: function (rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) { + this.addPoints([x, y]); + }, - return _sources; - }, - - /** - * - * @param {Object} - * args edgeStencil: ORYX.Core.StencilSet.Stencil | undefined - * edgeShape: ORYX.Core.Edge | undefined sourceStencil: - * ORYX.Core.StencilSet.Stencil | undefined sourceShape: - * ORYX.Core.Node | undefined - * - * At least edgeStencil or edgeShape has to be specified!!! - * - * @return {Array} Returns an array of stencils that can be target of the - * specified edge. - */ - targetStencils: function(args) { - // check arguments - if(!args || - !args.edgeShape && !args.edgeStencil) { - return []; - } - - // init arguments - if(args.sourceShape) { - args.sourceStencil = args.sourceShape.getStencil(); - } - - if(args.edgeShape) { - args.edgeStencil = args.edgeShape.getStencil(); - } - - var _targets = []; - - // check stencil, if it can be a target - this._stencils.each((function(stencil) { - var newArgs = Object.clone(args); - newArgs.targetStencil = stencil; - if(this.canConnect(newArgs)) { - _targets.push(stencil); - } - }).bind(this)); + /** + * arcRel - a + * + * @param {Number} rx + * @param {Number} ry + * @param {Number} xAxisRotation + * @param {Boolean} largeArcFlag + * @param {Boolean} sweepFlag + * @param {Number} x + * @param {Number} y + */ + arcRel: function (rx, ry, xAxisRotation, largeArcFlag, sweepFlag, x, y) { + this.addPoints([this._lastAbsX + x, this._lastAbsY + y]); + }, - return _targets; - }, + /** + * curvetoCubicAbs - C + * + * @param {Number} x1 + * @param {Number} y1 + * @param {Number} x2 + * @param {Number} y2 + * @param {Number} x + * @param {Number} y + */ + curvetoCubicAbs: function (x1, y1, x2, y2, x, y) { + this.addPoints([x, y]); + }, - /** - * - * @param {Object} - * args edgeStencil: ORYX.Core.StencilSet.Stencil edgeShape: - * ORYX.Core.Edge |undefined sourceStencil: - * ORYX.Core.StencilSet.Stencil | undefined sourceShape: - * ORYX.Core.Node |undefined targetStencil: - * ORYX.Core.StencilSet.Stencil | undefined targetShape: - * ORYX.Core.Node |undefined - * - * At least source or target has to be specified!!! - * - * @return {Boolean} Returns, if the edge can connect source and target. - */ - canConnect: function(args) { - // check arguments - if(!args || - (!args.sourceShape && !args.sourceStencil && - !args.targetShape && !args.targetStencil) || - !args.edgeShape && !args.edgeStencil) { - return false; - } - - // init arguments - if(args.sourceShape) { - args.sourceStencil = args.sourceShape.getStencil(); - } - if(args.targetShape) { - args.targetStencil = args.targetShape.getStencil(); - } - if(args.edgeShape) { - args.edgeStencil = args.edgeShape.getStencil(); - } - - var result; - - if(args.sourceStencil && args.targetStencil) { - var source = this._cachedConnectSET[args.sourceStencil.id()]; - - if(!source) - result = this._cacheConnect(args); - else { - var edge = source[args.edgeStencil.id()]; - - if(!edge) - result = this._cacheConnect(args); - else { - var target = edge[args.targetStencil.id()]; - - if(target == undefined) - result = this._cacheConnect(args); - else - result = target; - } - } - } else if (args.sourceStencil) { - var source = this._cachedConnectSE[args.sourceStencil.id()]; - - if(!source) - result = this._cacheConnect(args); - else { - var edge = source[args.edgeStencil.id()]; - - if(edge == undefined) - result = this._cacheConnect(args); - else - result = edge; - } - } else { // args.targetStencil - var target = this._cachedConnectTE[args.targetStencil.id()]; - - if(!target) - result = this._cacheConnect(args); - else { - var edge = target[args.edgeStencil.id()]; - - if(edge == undefined) - result = this._cacheConnect(args); - else - result = edge; - } - } - - // check cardinality - if (result) { - if(args.sourceShape) { - var source = this._cachedCardSE[args.sourceStencil.id()]; - - if(!source) { - this._cacheCard(args); - source = this._cachedCardSE[args.sourceStencil.id()]; - } - - var max = source[args.edgeStencil.id()]; - - if(max == undefined) { - this._cacheCard(args); - } - - max = source[args.edgeStencil.id()]; - - if(max != -1) { - result = args.sourceShape.getOutgoingShapes().all(function(cs) { - if((cs.getStencil().id() === args.edgeStencil.id()) && - ((args.edgeShape) ? cs !== args.edgeShape : true)) { - max--; - return (max > 0) ? true : false; - } else { - return true; - } - }); - } - } - - if (args.targetShape) { - var target = this._cachedCardTE[args.targetStencil.id()]; - - if(!target) { - this._cacheCard(args); - target = this._cachedCardTE[args.targetStencil.id()]; - } - - var max = target[args.edgeStencil.id()]; - - if(max == undefined) { - this._cacheCard(args); - } - - max = target[args.edgeStencil.id()]; - - if(max != -1) { - result = args.targetShape.getIncomingShapes().all(function(cs){ - if ((cs.getStencil().id() === args.edgeStencil.id()) && - ((args.edgeShape) ? cs !== args.edgeShape : true)) { - max--; - return (max > 0) ? true : false; - } - else { - return true; - } - }); - } - } - } - - return result; - }, - - /** - * - * @param {Object} - * args edgeStencil: ORYX.Core.StencilSet.Stencil edgeShape: - * ORYX.Core.Edge |undefined sourceStencil: - * ORYX.Core.StencilSet.Stencil | undefined sourceShape: - * ORYX.Core.Node |undefined targetStencil: - * ORYX.Core.StencilSet.Stencil | undefined targetShape: - * ORYX.Core.Node |undefined - * - * At least source or target has to be specified!!! - * - * @return {Boolean} Returns, if the edge can connect source and target. - */ - _canConnect: function(args) { - // check arguments - if(!args || - (!args.sourceShape && !args.sourceStencil && - !args.targetShape && !args.targetStencil) || - !args.edgeShape && !args.edgeStencil) { - return false; - } - - // init arguments - if(args.sourceShape) { - args.sourceStencil = args.sourceShape.getStencil(); - } - if(args.targetShape) { - args.targetStencil = args.targetShape.getStencil(); - } - if(args.edgeShape) { - args.edgeStencil = args.edgeShape.getStencil(); - } + /** + * curvetoCubicRel - c + * + * @param {Number} x1 + * @param {Number} y1 + * @param {Number} x2 + * @param {Number} y2 + * @param {Number} x + * @param {Number} y + */ + curvetoCubicRel: function (x1, y1, x2, y2, x, y) { + this.addPoints([this._lastAbsX + x, this._lastAbsY + y]); + }, - // 1. check connection rules - var resultCR; - - // get all connection rules for this edge - var edgeRules = this._getConnectionRulesOfEdgeStencil(args.edgeStencil); + /** + * linetoHorizontalAbs - H + * + * @param {Number} x + */ + linetoHorizontalAbs: function (x) { + this.addPoints([x, this._lastAbsY]); + }, - // check connection rules, if the source can be connected to the target - // with the specified edge. - if(edgeRules.keys().length === 0) { - resultCR = false; - } else { - if(args.sourceStencil) { - resultCR = args.sourceStencil.roles().any(function(sourceRole) { - var targetRoles = edgeRules[sourceRole]; - - if(!targetRoles) {return false;} - - if(args.targetStencil) { - return (targetRoles.any(function(targetRole) { - return args.targetStencil.roles().member(targetRole); - })); - } else { - return true; - } - }); - } else { // !args.sourceStencil -> there is args.targetStencil - resultCR = edgeRules.values().any(function(targetRoles) { - return args.targetStencil.roles().any(function(targetRole) { - return targetRoles.member(targetRole); - }); - }); - } - } - - return resultCR; - }, + /** + * linetoHorizontalRel - h + * + * @param {Number} x + */ + linetoHorizontalRel: function (x) { + this.addPoints([this._lastAbsX + x, this._lastAbsY]); + }, - /** End connection rules' methods */ + /** + * linetoAbs - L + * + * @param {Number} x + * @param {Number} y + */ + linetoAbs: function (x, y) { + this.addPoints([x, y]); + }, + /** + * linetoRel - l + * + * @param {Number} x + * @param {Number} y + */ + linetoRel: function (x, y) { + this.addPoints([this._lastAbsX + x, this._lastAbsY + y]); + }, - /** Begin containment rules' methods */ + /** + * movetoAbs - M + * + * @param {Number} x + * @param {Number} y + */ + movetoAbs: function (x, y) { + this.addPoints([x, y]); + }, - isContainer: function(shape) { - return this._containerStencils.member(shape.getStencil().id()); - }, + /** + * movetoRel - m + * + * @param {Number} x + * @param {Number} y + */ + movetoRel: function (x, y) { + if (this._lastAbsX && this._lastAbsY) { + this.addPoints([this._lastAbsX + x, this._lastAbsY + y]); + } else { + this.addPoints([x, y]); + } + }, - /** - * - * @param {Object} - * args containingStencil: ORYX.Core.StencilSet.Stencil - * containingShape: ORYX.Core.AbstractShape containedStencil: - * ORYX.Core.StencilSet.Stencil containedShape: ORYX.Core.Shape - */ - canContain: function(args) { - if(!args || - !args.containingStencil && !args.containingShape || - !args.containedStencil && !args.containedShape) { - return false; - } - - // init arguments - if(args.containedShape) { - args.containedStencil = args.containedShape.getStencil(); - } - - if(args.containingShape) { - args.containingStencil = args.containingShape.getStencil(); - } - - //if(args.containingStencil.type() == 'edge' || args.containedStencil.type() == 'edge') - // return false; - if(args.containedStencil.type() == 'edge') - return false; - - var childValues; - - var parent = this._cachedContainPC[args.containingStencil.id()]; - - if(!parent) - childValues = this._cacheContain(args); - else { - childValues = parent[args.containedStencil.id()]; - - if(!childValues) - childValues = this._cacheContain(args); - } + /** + * curvetoQuadraticAbs - Q + * + * @param {Number} x1 + * @param {Number} y1 + * @param {Number} x + * @param {Number} y + */ + curvetoQuadraticAbs: function (x1, y1, x, y) { + this.addPoints([x, y]); + }, - if(!childValues[0]) - return false; - else if (childValues[1] == -1) - return true; - else { - if(args.containingShape) { - var max = childValues[1]; - return args.containingShape.getChildShapes(false).all(function(as) { - if(as.getStencil().id() === args.containedStencil.id()) { - max--; - return (max > 0) ? true : false; - } else { - return true; - } - }); - } else { - return true; - } - } - }, - - /** - * - * @param {Object} - * args containingStencil: ORYX.Core.StencilSet.Stencil - * containingShape: ORYX.Core.AbstractShape containedStencil: - * ORYX.Core.StencilSet.Stencil containedShape: ORYX.Core.Shape - */ - _canContain: function(args) { - if(!args || - !args.containingStencil && !args.containingShape || - !args.containedStencil && !args.containedShape) { - return false; - } - - // init arguments - if(args.containedShape) { - args.containedStencil = args.containedShape.getStencil(); - } - - if(args.containingShape) { - args.containingStencil = args.containingShape.getStencil(); - } - -// if(args.containingShape) { -// if(args.containingShape instanceof ORYX.Core.Edge) { -// // edges cannot contain other shapes -// return false; -// } -// } + /** + * curvetoQuadraticRel - q + * + * @param {Number} x1 + * @param {Number} y1 + * @param {Number} x + * @param {Number} y + */ + curvetoQuadraticRel: function (x1, y1, x, y) { + this.addPoints([this._lastAbsX + x, this._lastAbsY + y]); + }, - - var result; - - // check containment rules - result = args.containingStencil.roles().any((function(role) { - var roles = this._containmentRules[role]; - if(roles) { - return roles.any(function(role) { - return args.containedStencil.roles().member(role); - }); - } else { - return false; - } - }).bind(this)); - - return result; - }, - - /** End containment rules' methods */ - - - /** Begin morphing rules' methods */ - - /** - * - * @param {Object} - * args - * stencil: ORYX.Core.StencilSet.Stencil | undefined - * shape: ORYX.Core.Shape | undefined - * - * At least stencil or shape has to be specified - * - * @return {Array} Array of stencils that the passed stencil/shape can be - * transformed to (including the current stencil itself) - */ - morphStencils: function(args) { - // check arguments - if(!args.stencil && !args.shape) { - return []; - } - - // init arguments - if(args.shape) { - args.stencil = args.shape.getStencil(); - } - - var _morphStencils = []; - args.stencil.roles().each(function(role) { - this._cacheMorph(role).each(function(stencil) { - _morphStencils.push(stencil); - }) - }.bind(this)); + /** + * curvetoCubicSmoothAbs - S + * + * @param {Number} x2 + * @param {Number} y2 + * @param {Number} x + * @param {Number} y + */ + curvetoCubicSmoothAbs: function (x2, y2, x, y) { + this.addPoints([x, y]); + }, + /** + * curvetoCubicSmoothRel - s + * + * @param {Number} x2 + * @param {Number} y2 + * @param {Number} x + * @param {Number} y + */ + curvetoCubicSmoothRel: function (x2, y2, x, y) { + this.addPoints([this._lastAbsX + x, this._lastAbsY + y]); + }, - var baseMorphs = this.baseMorphs(); - // BaseMorphs should be in the front of the array - _morphStencils = _morphStencils.uniq().sort(function(a,b){ return baseMorphs.include(a)&&!baseMorphs.include(b) ? -1 : (baseMorphs.include(b)&&!baseMorphs.include(a) ? 1 : 0)}) - return _morphStencils; - }, - - /** - * @return {Array} An array of all base morph stencils - */ - baseMorphs: function() { - var _baseMorphs = []; - this._morphingRules.each(function(pair) { - pair.value.each(function(baseMorph) { - _baseMorphs.push(baseMorph); - }); - }); - return _baseMorphs; - }, - - /** - * Returns true if there are morphing rules defines - * @return {boolean} - */ - containsMorphingRules: function(){ - return this._stencilSets.any(function(ss){ return !!ss.jsonRules().morphingRules}); - }, - - /** - * - * @param {Object} - * args - * sourceStencil: - * ORYX.Core.StencilSet.Stencil | undefined - * sourceShape: - * ORYX.Core.Node |undefined - * targetStencil: - * ORYX.Core.StencilSet.Stencil | undefined - * targetShape: - * ORYX.Core.Node |undefined - * - * - * @return {Stencil} Returns, the stencil for the connecting edge - * or null if connection is not possible - */ - connectMorph: function(args) { - // check arguments - if(!args || - (!args.sourceShape && !args.sourceStencil && - !args.targetShape && !args.targetStencil)) { - return false; - } - - // init arguments - if(args.sourceShape) { - args.sourceStencil = args.sourceShape.getStencil(); - } - if(args.targetShape) { - args.targetStencil = args.targetShape.getStencil(); - } - - var incoming = this.incomingEdgeStencils(args); - var outgoing = this.outgoingEdgeStencils(args); - - var edgeStencils = incoming.select(function(e) { return outgoing.member(e); }); // intersection of sets - var baseEdgeStencils = this.baseMorphs().select(function(e) { return edgeStencils.member(e); }); // again: intersection of sets - - if(baseEdgeStencils.size()>0) - return baseEdgeStencils[0]; // return any of the possible base morphs - else if(edgeStencils.size()>0) - return edgeStencils[0]; // return any of the possible stencils - - return null; //connection not possible - }, - - /** - * Return true if the stencil should be located in the shape menu - * @param {ORYX.Core.StencilSet.Stencil} morph - * @return {Boolean} Returns true if the morphs in the morph group of the - * specified morph shall be displayed in the shape menu - */ - showInShapeMenu: function(stencil) { - return this._stencilSets.any(function(ss){ - return ss.jsonRules().morphingRules - .any(function(r){ - return stencil.roles().include(ss.namespace() + r.role) - && r.showInShapeMenu !== false; - }) - }); - }, - - preserveBounds: function(stencil) { - return this._stencilSets.any(function(ss) { - return ss.jsonRules().morphingRules.any(function(r) { - - - return stencil.roles().include(ss.namespace() + r.role) - && r.preserveBounds; - }) - }) - }, - - /** End morphing rules' methods */ + /** + * curvetoQuadraticSmoothAbs - T + * + * @param {Number} x + * @param {Number} y + */ + curvetoQuadraticSmoothAbs: function (x, y) { + this.addPoints([x, y]); + }, + /** + * curvetoQuadraticSmoothRel - t + * + * @param {Number} x + * @param {Number} y + */ + curvetoQuadraticSmoothRel: function (x, y) { + this.addPoints([this._lastAbsX + x, this._lastAbsY + y]); + }, - /** Begin layouting rules' methods */ - - /** - * Returns a set on "in" and "out" layouting rules for a given shape - * @param {Object} shape - * @param {Object} edgeShape (Optional) - * @return {Object} "in" and "out" with a default value of {"t":1, "r":1, "b":1, "r":1} if not specified in the json - */ - getLayoutingRules : function(shape, edgeShape){ - - if (!shape||!(shape instanceof ORYX.Core.Shape)){ return } - - var layout = {"in":{},"out":{}}; - - var parseValues = function(o, v){ - if (o && o[v]){ - ["t","r","b","l"].each(function(d){ - layout[v][d]=Math.max(o[v][d],layout[v][d]||0); - }); - } - if (o && o[v+"s"] instanceof Array){ - ["t","r","b","l"].each(function(d){ - var defaultRule = o[v+"s"].find(function(e){ return !e.edgeRole }); - var edgeRule; - if (edgeShape instanceof ORYX.Core.Edge) { - edgeRule = o[v + "s"].find(function(e){return this._hasRole(edgeShape, e.edgeRole) }.bind(this)); - } - layout[v][d]=Math.max(edgeRule?edgeRule[d]:defaultRule[d],layout[v][d]||0); - }.bind(this)); - } - }.bind(this) - - // For each role - shape.getStencil().roles().each(function(role) { - // check if there are layout information - if (this._layoutRules[role]){ - // if so, parse those information to the 'layout' variable - parseValues(this._layoutRules[role], "in"); - parseValues(this._layoutRules[role], "out"); - } - }.bind(this)); - - // Make sure, that every attribute has an value, - // otherwise set 1 - ["in","out"].each(function(v){ - ["t","r","b","l"].each(function(d){ - layout[v][d]=layout[v][d]!==undefined?layout[v][d]:1; - }); - }) - - return layout; - }, - - /** End layouting rules' methods */ - - /** Helper methods */ - - /** - * Checks wether a shape contains the given role or the role is equal the stencil id - * @param {ORYX.Core.Shape} shape - * @param {String} role - */ - _hasRole: function(shape, role){ - if (!(shape instanceof ORYX.Core.Shape)||!role){ return } - var isRole = shape.getStencil().roles().any(function(r){ return r == role}); - - return isRole || shape.getStencil().id() == (shape.getStencil().namespace()+role); - }, + /** + * linetoVerticalAbs - V + * + * @param {Number} y + */ + linetoVerticalAbs: function (y) { + this.addPoints([this._lastAbsX, y]); + }, - /** - * - * @param {String} - * role - * - * @return {Array} Returns an array of stencils that can act as role. - */ - _stencilsWithRole: function(role) { - return this._stencils.findAll(function(stencil) { - return (stencil.roles().member(role)) ? true : false; - }); - }, - - /** - * - * @param {String} - * role - * - * @return {Array} Returns an array of stencils that can act as role and - * have the type 'edge'. - */ - _edgesWithRole: function(role) { - return this._stencils.findAll(function(stencil) { - return (stencil.roles().member(role) && stencil.type() === "edge") ? true : false; - }); - }, - - /** - * - * @param {String} - * role - * - * @return {Array} Returns an array of stencils that can act as role and - * have the type 'node'. - */ - _nodesWithRole: function(role) { - return this._stencils.findAll(function(stencil) { - return (stencil.roles().member(role) && stencil.type() === "node") ? true : false; - }); - }, - - /** - * - * @param {ORYX.Core.StencilSet.Stencil} - * parent - * @param {ORYX.Core.StencilSet.Stencil} - * child - * - * @returns {Boolean} Returns the maximum occurrence of shapes of the - * stencil's type inside the parent. - */ - _getMaximumOccurrence: function(parent, child) { - var max; - child.roles().each((function(role) { - var cardRule = this._cardinalityRules[role]; - if(cardRule && cardRule.maximumOccurrence) { - if(max) { - max = Math.min(max, cardRule.maximumOccurrence); - } else { - max = cardRule.maximumOccurrence; - } - } - }).bind(this)); - - return max; - }, - - - /** - * - * @param {Object} - * args sourceStencil: ORYX.Core.Node edgeStencil: - * ORYX.Core.StencilSet.Stencil - * - * @return {Boolean} Returns, the maximum number of outgoing edges of the - * type specified by edgeStencil of the sourceShape. - */ - _getMaximumNumberOfOutgoingEdge: function(args) { - if(!args || - !args.sourceStencil || - !args.edgeStencil) { - return false; - } - - var max; - args.sourceStencil.roles().each((function(role) { - var cardRule = this._cardinalityRules[role]; - - if(cardRule && cardRule.outgoingEdges) { - args.edgeStencil.roles().each(function(edgeRole) { - var oe = cardRule.outgoingEdges[edgeRole]; - - if(oe && oe.maximum) { - if(max) { - max = Math.min(max, oe.maximum); - } else { - max = oe.maximum; - } - } - }); - } - }).bind(this)); - - return max; - }, - - /** - * - * @param {Object} - * args targetStencil: ORYX.Core.StencilSet.Stencil edgeStencil: - * ORYX.Core.StencilSet.Stencil - * - * @return {Boolean} Returns the maximum number of incoming edges of the - * type specified by edgeStencil of the targetShape. - */ - _getMaximumNumberOfIncomingEdge: function(args) { - if(!args || - !args.targetStencil || - !args.edgeStencil) { - return false; - } - - var max; - args.targetStencil.roles().each((function(role) { - var cardRule = this._cardinalityRules[role]; - if(cardRule && cardRule.incomingEdges) { - args.edgeStencil.roles().each(function(edgeRole) { - var ie = cardRule.incomingEdges[edgeRole]; - if(ie && ie.maximum) { - if(max) { - max = Math.min(max, ie.maximum); - } else { - max = ie.maximum; - } - } - }); - } - }).bind(this)); + /** + * linetoVerticalRel - v + * + * @param {Number} y + */ + linetoVerticalRel: function (y) { + this.addPoints([this._lastAbsX, this._lastAbsY + y]); + }, - return max; - }, - - /** - * - * @param {ORYX.Core.StencilSet.Stencil} - * edgeStencil - * - * @return {Hash} Returns a hash map of all connection rules for - * edgeStencil. - */ - _getConnectionRulesOfEdgeStencil: function(edgeStencil) { - var edgeRules = new Hash(); - edgeStencil.roles().each((function(role) { - if(this._connectionRules[role]) { - this._connectionRules[role].each(function(cr) { - if(edgeRules[cr.key]) { - edgeRules[cr.key] = edgeRules[cr.key].concat(cr.value); - } else { - edgeRules[cr.key] = cr.value; - } - }); - } - }).bind(this)); - - return edgeRules; - }, - - _isRoleOfOtherNamespace: function(role) { - return (role.indexOf("#") > 0); - }, + /** + * closePath - z or Z + */ + closePath: function () { + return;// do nothing + } - toString: function() { return "Rules"; } -} -ORYX.Core.StencilSet.Rules = Clazz.extend(ORYX.Core.StencilSet.Rules); -/* +});/* * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. * License rights for this program may be obtained from Alfresco Software, Ltd. * pursuant to a written agreement and any use of this program without such an @@ -8138,7 +3460,22 @@ ORYX.Core.StencilSet.Rules = Clazz.extend(ORYX.Core.StencilSet.Rules); */ /** - * Init namespace + * + * Config variables + */ +NAMESPACE_ORYX = "http://www.b3mn.org/oryx"; +NAMESPACE_SVG = "http://www.w3.org/2000/svg/"; + +/** + * @classDescription This class wraps the manipulation of a SVG marker. + * @namespace ORYX.Core.SVG + * uses Inheritance (Clazz) + * uses Prototype 1.5.0 + * + */ + +/** + * Init package */ if (!ORYX) { var ORYX = {}; @@ -8146,429 +3483,174 @@ if (!ORYX) { if (!ORYX.Core) { ORYX.Core = {}; } -if (!ORYX.Core.StencilSet) { - ORYX.Core.StencilSet = {}; +if (!ORYX.Core.SVG) { + ORYX.Core.SVG = {}; } -/** - * This class represents a stencil set. It offers methods for accessing - * the attributes of the stencil set description JSON file and the stencil set's - * stencils. - */ -ORYX.Core.StencilSet.StencilSet = Clazz.extend({ +ORYX.Core.SVG.SVGMarker = Clazz.extend({ /** * Constructor - * @param source {URL} A reference to the stencil set specification. - * + * @param markerElement {SVGMarkerElement} */ - construct: function(source, modelMetaData, editorId){ + construct: function (markerElement) { arguments.callee.$.construct.apply(this, arguments); - - if (!source) { - throw "ORYX.Core.StencilSet.StencilSet(construct): Parameter 'source' is not defined."; - } - - if (source.endsWith("/")) { - source = source.substr(0, source.length - 1); - } - - this._extensions = new Hash(); - - this._source = source; - this._baseUrl = source.substring(0, source.lastIndexOf("/") + 1); - - this._jsonObject = {}; - - this._stencils = new Hash(); - this._availableStencils = new Hash(); - - if(ORYX.CONFIG.BACKEND_SWITCH) { - this._baseUrl = "editor/stencilsets/bpmn2.0/"; - this._source = "stencilsets/bpmn2.0/bpmn2.0.json"; - - new Ajax.Request(ACTIVITI.CONFIG.contextRoot + '/editor/stencilset?version=' + Date.now(), { - asynchronous: false, - method: 'get', - onSuccess: this._init.bind(this), - onFailure: this._cancelInit.bind(this) - }); - - } else { - new Ajax.Request(source, { - asynchronous: false, - method: 'get', - onSuccess: this._init.bind(this), - onFailure: this._cancelInit.bind(this) - }); - } - - if (this.errornous) - throw "Loading stencil set " + source + " failed."; - }, - - /** - * Finds a root stencil in this stencil set. There may be many of these. If - * there are, the first one found will be used. In Firefox, this is the - * topmost definition in the stencil set description file. - */ - findRootStencilName: function(){ - - // find any stencil that may be root. - var rootStencil = this._stencils.values().find(function(stencil){ - return stencil._jsonStencil.mayBeRoot - }); - - // if there is none, just guess the first. - if (!rootStencil) { - ORYX.Log.warn("Did not find any stencil that may be root. Taking a guess."); - rootStencil = this._stencils.values()[0]; - } - // return its id. - return rootStencil.id(); + this.id = undefined; + this.element = markerElement; + 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(); //initialisation of all the properties declared above. }, - + /** - * @param {ORYX.Core.StencilSet.StencilSet} stencilSet - * @return {Boolean} True, if stencil set has the same namespace. + * Initializes the values that are defined in the constructor. */ - equals: function(stencilSet){ - return (this.namespace() === stencilSet.namespace()); - }, - - /** - * - * @param {Oryx.Core.StencilSet.Stencil} rootStencil If rootStencil is defined, it only returns stencils - * that could be (in)direct child of that stencil. - */ - stencils: function(rootStencil, rules, sortByGroup){ - if(rootStencil && rules) { - var stencils = this._availableStencils.values(); - var containers = [rootStencil]; - var checkedContainers = []; - - var result = []; - - while (containers.size() > 0) { - var container = containers.pop(); - checkedContainers.push(container); - var children = stencils.findAll(function(stencil){ - var args = { - containingStencil: container, - containedStencil: stencil - }; - return rules.canContain(args); - }); - for(var i = 0; i < children.size(); i++) { - if (!checkedContainers.member(children[i])) { - containers.push(children[i]); - } - } - result = result.concat(children).uniq(); - } - - // Sort the result to the origin order - result = result.sortBy(function(stencil) { - return stencils.indexOf(stencil); - }); - - - if(sortByGroup) { - result = result.sortBy(function(stencil) { - return stencil.groups().first(); - }); - } - - var edges = stencils.findAll(function(stencil) { - return stencil.type() == "edge"; - }); - result = result.concat(edges); - - return result; - - } else { - if(sortByGroup) { - return this._availableStencils.values().sortBy(function(stencil) { - return stencil.groups().first(); - }); - } else { - return this._availableStencils.values(); - } - } - }, - - nodes: function(){ - return this._availableStencils.values().findAll(function(stencil){ - return (stencil.type() === 'node') - }); - }, - - edges: function(){ - return this._availableStencils.values().findAll(function(stencil){ - return (stencil.type() === 'edge') - }); - }, - - stencil: function(id){ - return this._stencils[id]; - }, - - 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(url) { - - new Ajax.Request(url, { - method: 'GET', - asynchronous: false, - onSuccess: (function(transport) { - this.addExtensionDirectly(transport.responseText); - }).bind(this), - onFailure: (function(transport) { - ORYX.Log.debug("Loading stencil set extension file failed. The request returned an error." + transport); - }).bind(this), - onException: (function(transport) { - ORYX.Log.debug("Loading stencil set extension file failed. The request returned an error." + transport); - }).bind(this) - - }); - }, - - addExtensionDirectly: function(str){ - - try { - eval("var jsonExtension = " + str); - - if(!(jsonExtension["extends"].endsWith("#"))) - jsonExtension["extends"] += "#"; - - if(jsonExtension["extends"] == this.namespace()) { - this._extensions[jsonExtension.namespace] = jsonExtension; - - var defaultPosition = this._stencils.keys().size(); - //load new stencils - if(jsonExtension.stencils) { - $A(jsonExtension.stencils).each(function(stencil) { - defaultPosition++; - var oStencil = new ORYX.Core.StencilSet.Stencil(stencil, this.namespace(), this._baseUrl, this, undefined, defaultPosition); - this._stencils[oStencil.id()] = oStencil; - this._availableStencils[oStencil.id()] = oStencil; - }.bind(this)); - } - - //load additional properties - 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)); - } - - //remove stencil properties - 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)); - } - - //remove stencils - 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(namespace) { - var jsonExtension = this._extensions[namespace]; - if(jsonExtension) { - - //unload extension's stencils - if(jsonExtension.stencils) { - $A(jsonExtension.stencils).each(function(stencil) { - var oStencil = new ORYX.Core.StencilSet.Stencil(stencil, this.namespace(), this._baseUrl, this); - delete this._stencils[oStencil.id()]; // maybe not ?? - delete this._availableStencils[oStencil.id()]; - }.bind(this)); - } - - //unload extension's properties - 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.removeProperty(property.id); - }); - - return true; - } - else - return false; - }) - }) - }.bind(this)); - } - - //restore removed stencil properties - if(jsonExtension.removeproperties) { - jsonExtension.removeproperties.each(function(remprop) { - var stencil = this.stencil(jsonExtension["extends"] + remprop.stencil); - if(stencil) { - var stencilJson = $A(this._jsonObject.stencils).find(function(s) { return s.id == stencil.id() }); - remprop.properties.each(function(propId) { - var propertyJson = $A(stencilJson.properties).find(function(p) { return p.id == propId }); - stencil.addProperty(propertyJson, this.namespace()); - }.bind(this)); - } - }.bind(this)); - } - - //restore removed stencils - if(jsonExtension.removestencils) { - $A(jsonExtension.removestencils).each(function(remstencil) { - var sId = jsonExtension["extends"] + remstencil; - this._availableStencils[sId] = this._stencils[sId]; - }.bind(this)); - } - } - delete this._extensions[namespace]; - }, - - __handleStencilset: function(response){ - - try { - // using eval instead of prototype's parsing, - // since there are functions in this JSON. - eval("this._jsonObject =" + response.responseText); - } - catch (e) { - throw "Stenciset corrupt: " + e; + _init: function () { + //check if this.element is a SVGMarkerElement + if (!(this.element == "[object SVGMarkerElement]")) { + throw "SVGMarker: Argument is not an instance of SVGMarkerElement."; } - - // assert it was parsed. - if (!this._jsonObject) { - throw "Error evaluating stencilset. It may be corrupt."; + + this.id = this.element.getAttributeNS(null, "id"); + + //init svg marker attributes + var refXValue = this.element.getAttributeNS(null, "refX"); + if (refXValue) { + this.refX = parseFloat(refXValue); + } else { + this.refX = 0; } - - with (this._jsonObject) { - - // assert there is a namespace. - if (!namespace || namespace === "") - throw "Namespace definition missing in stencilset."; - - if (!(stencils instanceof Array)) - throw "Stencilset corrupt."; - - // assert namespace ends with '#'. - if (!namespace.endsWith("#")) - namespace = namespace + "#"; - - // assert title and description are strings. - if (!title) - title = ""; - if (!description) - description = ""; + var refYValue = this.element.getAttributeNS(null, "refY"); + if (refYValue) { + this.refY = parseFloat(refYValue); + } else { + this.refY = 0; + } + var markerWidthValue = this.element.getAttributeNS(null, "markerWidth"); + if (markerWidthValue) { + this.markerWidth = parseFloat(markerWidthValue); + } else { + this.markerWidth = 3; + } + var markerHeightValue = this.element.getAttributeNS(null, "markerHeight"); + if (markerHeightValue) { + this.markerHeight = parseFloat(markerHeightValue); + } else { + this.markerHeight = 3; + } + + this.oldRefX = this.refX; + this.oldRefY = this.refY; + this.oldMarkerWidth = this.markerWidth; + this.oldMarkerHeight = this.markerHeight; + + //init oryx attributes + var optionalAttr = this.element.getAttributeNS(NAMESPACE_ORYX, "optional"); + if (optionalAttr) { + optionalAttr = optionalAttr.strip(); + this.optional = (optionalAttr.toLowerCase() === "yes"); + } else { + this.optional = false; + } + + var enabledAttr = this.element.getAttributeNS(NAMESPACE_ORYX, "enabled"); + if (enabledAttr) { + enabledAttr = enabledAttr.strip(); + this.enabled = !(enabledAttr.toLowerCase() === "no"); + } else { + this.enabled = true; + } + + var minLengthAttr = this.element.getAttributeNS(NAMESPACE_ORYX, "minimumLength"); + if (minLengthAttr) { + this.minimumLength = parseFloat(minLengthAttr); } + + var resizeAttr = this.element.getAttributeNS(NAMESPACE_ORYX, "resize"); + if (resizeAttr) { + resizeAttr = resizeAttr.strip(); + this.resize = (resizeAttr.toLowerCase() === "yes"); + } else { + this.resize = false; + } + + //init SVGShape objects + //this.svgShapes = this._getSVGShapes(this.element); }, - + /** - * This method is called when the HTTP request to get the requested stencil - * set succeeds. The response is supposed to be a JSON representation - * according to the stencil set specification. - * @param {Object} response The JSON representation according to the - * stencil set specification. + * */ - _init: function(response){ - - // init and check consistency. - this.__handleStencilset(response); - - var pps = new Hash(); - - // init property packages - if(this._jsonObject.propertyPackages) { - $A(this._jsonObject.propertyPackages).each((function(pp) { - pps[pp.name] = pp.properties; - }).bind(this)); - } - - var defaultPosition = 0; - - // init each stencil - $A(this._jsonObject.stencils).each((function(stencil){ - defaultPosition++; - - // instantiate normally. - var oStencil = new ORYX.Core.StencilSet.Stencil(stencil, this.namespace(), this._baseUrl, this, pps, defaultPosition); - this._stencils[oStencil.id()] = oStencil; - this._availableStencils[oStencil.id()] = oStencil; - - }).bind(this)); + _getSVGShapes: function (svgElement) { + if (svgElement.hasChildNodes) { + var svgShapes = []; + var me = this; + $A(svgElement.childNodes).each(function (svgChild) { + try { + var svgShape = new ORYX.Core.SVG.SVGShape(svgChild); + svgShapes.push(svgShape); + } catch (e) { + svgShapes = svgShapes.concat(me._getSVGShapes(svgChild)); + } + }); + return svgShapes; + } }, - - _cancelInit: function(response){ - this.errornous = true; + + /** + * Writes the changed values into the SVG marker. + */ + update: function () { + //TODO mache marker resizebar!!! aber erst wenn der rest der connectingshape funzt! + +// //update marker attributes +// if(this.refX != this.oldRefX) { +// this.element.setAttributeNS(null, "refX", this.refX); +// } +// if(this.refY != this.oldRefY) { +// this.element.setAttributeNS(null, "refY", this.refY); +// } +// if(this.markerWidth != this.oldMarkerWidth) { +// this.element.setAttributeNS(null, "markerWidth", this.markerWidth); +// } +// if(this.markerHeight != this.oldMarkerHeight) { +// this.element.setAttributeNS(null, "markerHeight", this.markerHeight); +// } +// +// //update SVGShape objects +// var widthDelta = this.markerWidth / this.oldMarkerWidth; +// var heightDelta = this.markerHeight / this.oldMarkerHeight; +// if(widthDelta != 1 && heightDelta != 1) { +// this.svgShapes.each(function(svgShape) { +// +// }); +// } + + //update old values to prepare the next update + this.oldRefX = this.refX; + this.oldRefY = this.refY; + this.oldMarkerWidth = this.markerWidth; + this.oldMarkerHeight = this.markerHeight; }, - - toString: function(){ - return "StencilSet " + this.title() + " (" + this.namespace() + ")"; + + toString: function () { + return (this.element) ? "SVGMarker " + this.element.id : "SVGMarker " + this.element; } -}); -/* +});/* * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. * License rights for this program may be obtained from Alfresco Software, Ltd. * pursuant to a written agreement and any use of this program without such an @@ -8579,211 +3661,565 @@ ORYX.Core.StencilSet.StencilSet = Clazz.extend({ */ /** - * Init namespace + * + * Config variables */ -if(!ORYX) {var ORYX = {};} -if(!ORYX.Core) {ORYX.Core = {};} -if(!ORYX.Core.StencilSet) {ORYX.Core.StencilSet = {};} +NAMESPACE_ORYX = "http://www.b3mn.org/oryx"; +NAMESPACE_SVG = "http://www.w3.org/2000/svg/"; /** - * Class StencilSets - * uses Prototpye 1.5.0 - * uses Inheritance + * @classDescription This class wraps the manipulation of a SVG basic shape or a path. + * @namespace ORYX.Core.SVG + * uses Inheritance (Clazz) + * uses Prototype 1.5.0 + * uses PathParser by Kevin Lindsey (http://kevlindev.com/) + * uses MinMaxPathHandler + * uses EditPathHandler * - * Singleton */ -//storage for loaded stencil sets by namespace -ORYX.Core.StencilSet._stencilSetsByNamespace = new Hash(); -//storage for stencil sets by url -ORYX.Core.StencilSet._stencilSetsByUrl = new Hash(); +//init package +if (!ORYX) { + var ORYX = {}; +} +if (!ORYX.Core) { + ORYX.Core = {}; +} +if (!ORYX.Core.SVG) { + ORYX.Core.SVG = {}; +} -//storage for stencil set namespaces by editor instances -ORYX.Core.StencilSet._StencilSetNSByEditorInstance = new Hash(); +ORYX.Core.SVG.SVGShape = Clazz.extend({ -//storage for rules by editor instances -ORYX.Core.StencilSet._rulesByEditorInstance = new Hash(); + /** + * Constructor + * @param svgElem {SVGElement} An SVGElement that is a basic shape or a path. + */ + construct: function (svgElem) { + arguments.callee.$.construct.apply(this, arguments); -/** - * - * @param {String} editorId - * - * @return {Hash} Returns a hash map with all stencil sets that are loaded by - * the editor with the editorId. - */ -ORYX.Core.StencilSet.stencilSets = function(editorId) { - var stencilSetNSs = ORYX.Core.StencilSet._StencilSetNSByEditorInstance[editorId]; - var stencilSets = new Hash(); - if(stencilSetNSs) { - stencilSetNSs.each(function(stencilSetNS) { - var stencilSet = ORYX.Core.StencilSet.stencilSet(stencilSetNS) - stencilSets[stencilSet.namespace()] = stencilSet; - }); - } - return stencilSets; -}; + this.type; + this.element = svgElem; + 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.anchors = []; + this.anchorLeft = false; + this.anchorRight = false; + this.anchorTop = false; + this.anchorBottom = false; -/** - * - * @param {String} namespace - * - * @return {ORYX.Core.StencilSet.StencilSet} Returns the stencil set with the specified - * namespace. - * - * The method can handle namespace strings like - * http://www.example.org/stencilset - * http://www.example.org/stencilset# - * http://www.example.org/stencilset#ANode - */ -ORYX.Core.StencilSet.stencilSet = function(namespace) { - ORYX.Log.trace("Getting stencil set %0", namespace); - var splitted = namespace.split("#", 1); - if(splitted.length === 1) { - ORYX.Log.trace("Getting stencil set %0", splitted[0]); - return ORYX.Core.StencilSet._stencilSetsByNamespace[splitted[0] + "#"]; - } else { - return undefined; - } -}; + //attributes of path elements of edge objects + this.allowDockers = true; + this.resizeMarkerMid = false; -/** - * - * @param {String} id - * - * @return {ORYX.Core.StencilSet.Stencil} Returns the stencil specified by the id. - * - * The id must be unique and contains the namespace of the stencil's stencil set. - * e.g. http://www.example.org/stencilset#ANode - */ -ORYX.Core.StencilSet.stencil = function(id) { - ORYX.Log.trace("Getting stencil for %0", id); - var ss = ORYX.Core.StencilSet.stencilSet(id); - if(ss) { - return ss.stencil(id); - } else { - - ORYX.Log.trace("Cannot fild stencil for %0", id); - return undefined; - } -}; + this.editPathParser; + this.editPathHandler; -/** - * - * @param {String} editorId - * - * @return {ORYX.Core.StencilSet.Rules} Returns the rules object for the editor - * specified by its editor id. - */ -ORYX.Core.StencilSet.rules = function(editorId) { - if(!ORYX.Core.StencilSet._rulesByEditorInstance[editorId]) { - ORYX.Core.StencilSet._rulesByEditorInstance[editorId] = new ORYX.Core.StencilSet.Rules(); - } - return ORYX.Core.StencilSet._rulesByEditorInstance[editorId]; -}; + this.init(); //initialisation of all the properties declared above. + }, -/** - * - * @param {String} url - * @param {String} editorId - * - * Loads a stencil set from url, if it is not already loaded. - * It also stores which editor instance loads the stencil set and - * initializes the Rules object for the editor instance. - */ -ORYX.Core.StencilSet.loadStencilSet = function(url, modelMetaData, editorId) { - - // Alfresco: disable cache, because stencil sets are now flexible - - //var stencilSet = ORYX.Core.StencilSet._stencilSetsByUrl[url]; - - //if(!stencilSet) { - //load stencil set - stencilSet = new ORYX.Core.StencilSet.StencilSet(url, modelMetaData, editorId); - - //store stencil set - ORYX.Core.StencilSet._stencilSetsByNamespace[stencilSet.namespace()] = stencilSet; - - //store stencil set by url - ORYX.Core.StencilSet._stencilSetsByUrl[url] = stencilSet; - //} - - var namespace = stencilSet.namespace(); - - //store which editorInstance loads the stencil set - if(ORYX.Core.StencilSet._StencilSetNSByEditorInstance[editorId]) { - ORYX.Core.StencilSet._StencilSetNSByEditorInstance[editorId].push(namespace); - } else { - ORYX.Core.StencilSet._StencilSetNSByEditorInstance[editorId] = [namespace]; - } - - //store the rules for the editor instance - if(ORYX.Core.StencilSet._rulesByEditorInstance[editorId]) { - ORYX.Core.StencilSet._rulesByEditorInstance[editorId].initializeRules(stencilSet); - } else { - var rules = new ORYX.Core.StencilSet.Rules(); - rules.initializeRules(stencilSet); - ORYX.Core.StencilSet._rulesByEditorInstance[editorId] = rules; - } -}; + /** + * Initializes the values that are defined in the constructor. + */ + init: function () { -/** - * Returns the translation of an attribute in jsonObject specified by its name - * according to navigator.language - */ -ORYX.Core.StencilSet.getTranslation = function(jsonObject, name) { - var lang = ORYX.I18N.Language.toLowerCase(); - - var result = jsonObject[name + "_" + lang]; - - if(result) - return result; - - result = jsonObject[name + "_" + lang.substr(0, 2)]; - - if(result) - return result; - - return jsonObject[name]; -}; -/* - * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. - * License rights for this program may be obtained from Alfresco Software, Ltd. - * pursuant to a written agreement and any use of this program without such an - * agreement is prohibited. - */ -/* - * All code Copyright 2013 KIS Consultancy all rights reserved - */ + /**initialize position and size*/ + if (ORYX.Editor.checkClassType(this.element, SVGRectElement) || ORYX.Editor.checkClassType(this.element, SVGImageElement)) { + this.type = "Rect"; -/** - * Init namespaces - */ -if(!ORYX) {var ORYX = {};} -if(!ORYX.Core) {ORYX.Core = {};} + var xAttr = this.element.getAttributeNS(null, "x"); + if (xAttr) { + this.oldX = parseFloat(xAttr); + } else { + throw "Missing attribute in element " + this.element; + } + var yAttr = this.element.getAttributeNS(null, "y"); + if (yAttr) { + this.oldY = parseFloat(yAttr); + } else { + throw "Missing attribute in element " + this.element; + } + var widthAttr = this.element.getAttributeNS(null, "width"); + if (widthAttr) { + this.oldWidth = parseFloat(widthAttr); + } else { + throw "Missing attribute in element " + this.element; + } + var heightAttr = this.element.getAttributeNS(null, "height"); + if (heightAttr) { + this.oldHeight = parseFloat(heightAttr); + } else { + throw "Missing attribute in element " + this.element; + } + } else if (ORYX.Editor.checkClassType(this.element, SVGCircleElement)) { + this.type = "Circle"; -/** - * @classDescription With Bounds you can set and get position and size of UIObjects. - */ -ORYX.Core.Command = Clazz.extend({ + var cx = undefined; + var cy = undefined; + //var r = undefined; - /** - * Constructor - */ - construct: function() { + var cxAttr = this.element.getAttributeNS(null, "cx"); + if (cxAttr) { + cx = parseFloat(cxAttr); + } else { + throw "Missing attribute in element " + this.element; + } + var cyAttr = this.element.getAttributeNS(null, "cy"); + if (cyAttr) { + cy = parseFloat(cyAttr); + } else { + throw "Missing attribute in element " + this.element; + } + var rAttr = this.element.getAttributeNS(null, "r"); + if (rAttr) { + //r = parseFloat(rAttr); + this.radiusX = parseFloat(rAttr); + } else { + throw "Missing attribute in element " + this.element; + } + this.oldX = cx - this.radiusX; + this.oldY = cy - this.radiusX; + this.oldWidth = 2 * this.radiusX; + this.oldHeight = 2 * this.radiusX; + + } else if (ORYX.Editor.checkClassType(this.element, SVGEllipseElement)) { + this.type = "Ellipse"; + + var cx = undefined; + var cy = undefined; + //var rx = undefined; + //var ry = undefined; + var cxAttr = this.element.getAttributeNS(null, "cx"); + if (cxAttr) { + cx = parseFloat(cxAttr); + } else { + throw "Missing attribute in element " + this.element; + } + var cyAttr = this.element.getAttributeNS(null, "cy"); + if (cyAttr) { + cy = parseFloat(cyAttr); + } else { + throw "Missing attribute in element " + this.element; + } + var rxAttr = this.element.getAttributeNS(null, "rx"); + if (rxAttr) { + this.radiusX = parseFloat(rxAttr); + } else { + throw "Missing attribute in element " + this.element; + } + var ryAttr = this.element.getAttributeNS(null, "ry"); + if (ryAttr) { + this.radiusY = parseFloat(ryAttr); + } else { + throw "Missing attribute in element " + this.element; + } + this.oldX = cx - this.radiusX; + this.oldY = cy - this.radiusY; + this.oldWidth = 2 * this.radiusX; + this.oldHeight = 2 * this.radiusY; + + } else if (ORYX.Editor.checkClassType(this.element, SVGLineElement)) { + this.type = "Line"; + + var x1 = undefined; + var y1 = undefined; + var x2 = undefined; + var y2 = undefined; + var x1Attr = this.element.getAttributeNS(null, "x1"); + if (x1Attr) { + x1 = parseFloat(x1Attr); + } else { + throw "Missing attribute in element " + this.element; + } + var y1Attr = this.element.getAttributeNS(null, "y1"); + if (y1Attr) { + y1 = parseFloat(y1Attr); + } else { + throw "Missing attribute in element " + this.element; + } + var x2Attr = this.element.getAttributeNS(null, "x2"); + if (x2Attr) { + x2 = parseFloat(x2Attr); + } else { + throw "Missing attribute in element " + this.element; + } + var y2Attr = this.element.getAttributeNS(null, "y2"); + if (y2Attr) { + y2 = parseFloat(y2Attr); + } else { + throw "Missing attribute in element " + this.element; + } + this.oldX = Math.min(x1, x2); + this.oldY = Math.min(y1, y2); + this.oldWidth = Math.abs(x1 - x2); + this.oldHeight = Math.abs(y1 - y2); + + } else if (ORYX.Editor.checkClassType(this.element, SVGPolylineElement) || ORYX.Editor.checkClassType(this.element, SVGPolygonElement)) { + this.type = "Polyline"; + + var pointsArray = []; + if (this.element.points && this.element.points.numberOfItems) { + for (var i = 0, size = this.element.points.numberOfItems; i < size; i++) { + pointsArray.push(this.element.points.getItem(i).x) + pointsArray.push(this.element.points.getItem(i).y) + } + } else { + var points = this.element.getAttributeNS(null, "points"); + if (points) { + points = points.replace(/,/g, " "); + pointsArray = points.split(" "); + pointsArray = pointsArray.without(""); + } else { + throw "Missing attribute in element " + this.element; + } + } - }, - - execute: function(){ - throw "Command.execute() has to be implemented!" - }, - - rollback: function(){ - throw "Command.rollback() has to be implemented!" - } - - - });/* + + if (pointsArray && pointsArray.length && pointsArray.length > 1) { + var minX = parseFloat(pointsArray[0]); + var minY = parseFloat(pointsArray[1]); + var maxX = parseFloat(pointsArray[0]); + var maxY = parseFloat(pointsArray[1]); + + for (var i = 0; i < pointsArray.length; i++) { + minX = Math.min(minX, parseFloat(pointsArray[i])); + maxX = Math.max(maxX, parseFloat(pointsArray[i])); + i++; + minY = Math.min(minY, parseFloat(pointsArray[i])); + maxY = Math.max(maxY, parseFloat(pointsArray[i])); + } + + this.oldX = minX; + this.oldY = minY; + this.oldWidth = maxX - minX; + this.oldHeight = maxY - minY; + } 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 parser = new PathParser(); + var handler = new ORYX.Core.SVG.MinMaxPathHandler(); + parser.setHandler(handler); + parser.parsePath(this.element); + + this.oldX = handler.minX; + this.oldY = handler.minY; + this.oldWidth = handler.maxX - handler.minX; + this.oldHeight = handler.maxY - handler.minY; + + delete parser; + delete handler; + } else { + throw "Element is not a shape."; + } + + /** initialize attributes of oryx namespace */ + //resize + var resizeAttr = this.element.getAttributeNS(NAMESPACE_ORYX, "resize"); + if (resizeAttr) { + resizeAttr = resizeAttr.toLowerCase(); + if (resizeAttr.match(/horizontal/)) { + this.isHorizontallyResizable = true; + } else { + this.isHorizontallyResizable = false; + } + if (resizeAttr.match(/vertical/)) { + this.isVerticallyResizable = true; + } else { + this.isVerticallyResizable = false; + } + } else { + this.isHorizontallyResizable = false; + this.isVerticallyResizable = false; + } + + //anchors + var anchorAttr = this.element.getAttributeNS(NAMESPACE_ORYX, "anchors"); + if (anchorAttr) { + anchorAttr = anchorAttr.replace("/,/g", " "); + var anchors = anchorAttr.split(" ").without(""); + + for (var i = 0; i < anchors.length; i++) { + switch (anchors[i].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; + } + } + } + + //allowDockers and resizeMarkerMid + if (ORYX.Editor.checkClassType(this.element, SVGPathElement)) { + var allowDockersAttr = this.element.getAttributeNS(NAMESPACE_ORYX, "allowDockers"); + if (allowDockersAttr) { + if (allowDockersAttr.toLowerCase() === "no") { + this.allowDockers = false; + } else { + this.allowDockers = true; + } + } + + var resizeMarkerMidAttr = this.element.getAttributeNS(NAMESPACE_ORYX, "resizeMarker-mid"); + if (resizeMarkerMidAttr) { + if (resizeMarkerMidAttr.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; + }, + + /** + * Writes the changed values into the SVG element. + */ + 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": + //calculate the radius + //var r; +// if(this.width/this.oldWidth <= this.height/this.oldHeight) { +// this.radiusX = ((this.width > this.height) ? this.width : this.height)/2.0; +// } else { + this.radiusX = ((this.width < this.height) ? this.width : this.height) / 2.0; + //} + + this.element.setAttributeNS(null, "cx", this.x + this.width / 2.0); + this.element.setAttributeNS(null, "cy", this.y + this.height / 2.0); + 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 points = this.element.getAttributeNS(null, "points"); + if (points) { + points = points.replace(/,/g, " ").split(" ").without(""); + + if (points && points.length && points.length > 1) { + + //TODO what if oldWidth == 0? + var widthDelta = (this.oldWidth === 0) ? 0 : this.width / this.oldWidth; + var heightDelta = (this.oldHeight === 0) ? 0 : this.height / this.oldHeight; + + var updatedPoints = ""; + for (var i = 0; i < points.length; i++) { + var x = (parseFloat(points[i]) - this.oldX) * widthDelta + this.x; + i++; + var y = (parseFloat(points[i]) - this.oldY) * heightDelta + this.y; + updatedPoints += x + " " + y + " "; + } + this.element.setAttributeNS(null, "points", updatedPoints); + } else { + //TODO error + } + } else { + //TODO error + } + break; + case "Path": + //calculate scaling delta + //TODO what if oldWidth == 0? + var widthDelta = (this.oldWidth === 0) ? 0 : this.width / this.oldWidth; + var heightDelta = (this.oldHeight === 0) ? 0 : this.height / this.oldHeight; + + //use path parser to edit each point of the path + this.editPathHandler.init(this.x, this.y, this.oldX, this.oldY, widthDelta, heightDelta); + this.editPathParser.parsePath(this.element); + + //change d attribute of path + 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; + } + + // Remove cached variables + delete this.visible; + delete this.handler; + }, + + isPointIncluded: function (pointX, pointY) { + + // Check if there are the right arguments and if the node is visible + if (!pointX || !pointY || !this.isVisible()) { + return false; + } + + switch (this.type) { + case "Rect": + return (pointX >= this.x && pointX <= this.x + this.width && + pointY >= this.y && pointY <= this.y + this.height); + break; + case "Circle": + //calculate the radius +// var r; +// if(this.width/this.oldWidth <= this.height/this.oldHeight) { +// r = ((this.width > this.height) ? this.width : this.height)/2.0; +// } else { +// r = ((this.width < this.height) ? this.width : this.height)/2.0; +// } + return ORYX.Core.Math.isPointInEllipse(pointX, pointY, this.x + this.width / 2.0, this.y + this.height / 2.0, this.radiusX, this.radiusX); + break; + case "Ellipse": + return ORYX.Core.Math.isPointInEllipse(pointX, pointY, this.x + this.radiusX, this.y + this.radiusY, this.radiusX, this.radiusY); + break; + case "Line": + return ORYX.Core.Math.isPointInLine(pointX, pointY, this.x, this.y, this.x + this.width, this.y + this.height); + break; + case "Polyline": + var points = this.element.getAttributeNS(null, "points"); + + if (points) { + points = points.replace(/,/g, " ").split(" ").without(""); + + points = points.collect(function (n) { + return parseFloat(n); + }); + + return ORYX.Core.Math.isPointInPolygone(pointX, pointY, points); + } else { + return false; + } + break; + case "Path": + + // Cache Path handler + if (!this.handler) { + var parser = new PathParser(); + this.handler = new ORYX.Core.SVG.PointsPathHandler(); + parser.setHandler(this.handler); + parser.parsePath(this.element); + } + + return ORYX.Core.Math.isPointInPolygone(pointX, pointY, this.handler.points); + + break; + default: + return false; + } + }, + + /** + * Returns true if the element is visible + * @param {SVGElement} elem + * @return boolean + */ + isVisible: function (elem) { + + if (this.visible !== undefined) { + return this.visible; + } + + if (!elem) { + elem = this.element; + } + + var hasOwnerSVG = false; + try { + hasOwnerSVG = !!elem.ownerSVGElement; + } catch (e) { + } + + // Is SVG context + if (hasOwnerSVG) { + // IF G-Element + if (ORYX.Editor.checkClassType(elem, SVGGElement)) { + if (elem.className && elem.className.baseVal == "me") { + this.visible = true; + return this.visible; + } + } + + // Check if fill or stroke is set + var fill = elem.getAttributeNS(null, "fill"); + var stroke = elem.getAttributeNS(null, "stroke"); + if (fill && fill == "none" && stroke && stroke == "none") { + this.visible = false; + } else { + // Check if displayed + var attr = elem.getAttributeNS(null, "display"); + if (!attr) + this.visible = this.isVisible(elem.parentNode); + else if (attr == "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; + } +});/* * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. * License rights for this program may be obtained from Alfresco Software, Ltd. * pursuant to a written agreement and any use of this program without such an @@ -8796,3809 +4232,1149 @@ ORYX.Core.Command = Clazz.extend({ /** * Init namespaces */ -if(!ORYX) {var ORYX = {};} -if(!ORYX.Core) {ORYX.Core = {};} - +if (!ORYX) { + var ORYX = {}; +} +if (!ORYX.Core) { + ORYX.Core = {}; +} +if (!ORYX.Core.SVG) { + ORYX.Core.SVG = {}; +} /** - * @classDescription With Bounds you can set and get position and size of UIObjects. + * @classDescription Class for adding text to a shape. + * */ -ORYX.Core.Bounds = { +ORYX.Core.SVG.Label = Clazz.extend({ - /** - * Constructor - */ - construct: function() { - this._changedCallbacks = []; //register a callback with changedCallacks.push(this.method.bind(this)); - this.a = {}; - this.b = {}; - this.set.apply(this, arguments); - this.suspendChange = false; - this.changedWhileSuspend = false; - }, - - /** - * Calls all registered callbacks. - */ - _changed: function(sizeChanged) { - if(!this.suspendChange) { - this._changedCallbacks.each(function(callback) { - callback(this, sizeChanged); - }.bind(this)); - this.changedWhileSuspend = false; - } else - this.changedWhileSuspend = true; - }, - - /** - * Registers a callback that is called, if the bounds changes. - * @param callback {Function} The callback function. - */ - registerCallback: function(callback) { - if(!this._changedCallbacks.member(callback)) { - this._changedCallbacks.push(callback); - } - }, - - /** - * Unregisters a callback. - * @param callback {Function} The callback function. - */ - unregisterCallback: function(callback) { - this._changedCallbacks = this._changedCallbacks.without(callback); - }, - - /** - * Sets position and size of the shape dependent of four coordinates - * (set(ax, ay, bx, by);), two points (set({x: ax, y: ay}, {x: bx, y: by});) - * or one bound (set({a: {x: ax, y: ay}, b: {x: bx, y: by}});). - */ - set: function() { - - var changed = false; - - switch (arguments.length) { - - case 1: - if(this.a.x !== arguments[0].a.x) { - changed = true; - this.a.x = arguments[0].a.x; - } - if(this.a.y !== arguments[0].a.y) { - changed = true; - this.a.y = arguments[0].a.y; - } - if(this.b.x !== arguments[0].b.x) { - changed = true; - this.b.x = arguments[0].b.x; - } - if(this.b.y !== arguments[0].b.y) { - changed = true; - this.b.y = arguments[0].b.y; - } - break; - - case 2: - var ax = Math.min(arguments[0].x, arguments[1].x); - var ay = Math.min(arguments[0].y, arguments[1].y); - var bx = Math.max(arguments[0].x, arguments[1].x); - var by = Math.max(arguments[0].y, arguments[1].y); - if(this.a.x !== ax) { - changed = true; - this.a.x = ax; - } - if(this.a.y !== ay) { - changed = true; - this.a.y = ay; - } - if(this.b.x !== bx) { - changed = true; - this.b.x = bx; - } - if(this.b.y !== by) { - changed = true; - this.b.y = by; - } - break; - - case 4: - var ax = Math.min(arguments[0], arguments[2]); - var ay = Math.min(arguments[1], arguments[3]); - var bx = Math.max(arguments[0], arguments[2]); - var by = Math.max(arguments[1], arguments[3]); - if(this.a.x !== ax) { - changed = true; - this.a.x = ax; - } - if(this.a.y !== ay) { - changed = true; - this.a.y = ay; - } - if(this.b.x !== bx) { - changed = true; - this.b.x = bx; - } - if(this.b.y !== by) { - changed = true; - this.b.y = by; - } - break; - } - - if(changed) { - this._changed(true); - } - }, - - /** - * Moves the bounds so that the point p will be the new upper left corner. - * @param {Point} p - * or - * @param {Number} x - * @param {Number} y - */ - moveTo: function() { - - var currentPosition = this.upperLeft(); - switch (arguments.length) { - case 1: - this.moveBy({ - x: arguments[0].x - currentPosition.x, - y: arguments[0].y - currentPosition.y - }); - break; - case 2: - this.moveBy({ - x: arguments[0] - currentPosition.x, - y: arguments[1] - currentPosition.y - }); - break; - default: - //TODO error - } - - }, - - /** - * Moves the bounds relatively by p. - * @param {Point} p - * or - * @param {Number} x - * @param {Number} y - * - */ - moveBy: function() { - var changed = false; - - switch (arguments.length) { - case 1: - var p = arguments[0]; - if(p.x !== 0 || p.y !== 0) { - changed = true; - this.a.x += p.x; - this.b.x += p.x; - this.a.y += p.y; - this.b.y += p.y; - } - break; - case 2: - var x = arguments[0]; - var y = arguments[1]; - if(x !== 0 || y !== 0) { - changed = true; - this.a.x += x; - this.b.x += x; - this.a.y += y; - this.b.y += y; - } - break; - default: - //TODO error - } - - if(changed) { - this._changed(); - } - }, - - /*** - * Includes the bounds b into the current bounds. - * @param {Bounds} b - */ - include: function(b) { - - if( (this.a.x === undefined) && (this.a.y === undefined) && - (this.b.x === undefined) && (this.b.y === undefined)) { - return b; - }; - - var cx = Math.min(this.a.x,b.a.x); - var cy = Math.min(this.a.y,b.a.y); - - var dx = Math.max(this.b.x,b.b.x); - var dy = Math.max(this.b.y,b.b.y); - - - this.set(cx, cy, dx, dy); - }, - - /** - * Relatively extends the bounds by p. - * @param {Point} p - */ - extend: function(p) { - - if(p.x !== 0 || p.y !== 0) { - // this is over cross for the case that a and b have same coordinates. - //((this.a.x > this.b.x) ? this.a : this.b).x += p.x; - //((this.b.y > this.a.y) ? this.b : this.a).y += p.y; - this.b.x += p.x; - this.b.y += p.y; - - this._changed(true); - } - }, - - /** - * Widens the scope of the bounds by x. - * @param {Number} x - */ - widen: function(x) { - if (x !== 0) { - this.suspendChange = true; - this.moveBy({x: -x, y: -x}); - this.extend({x: 2*x, y: 2*x}); - this.suspendChange = false; - if(this.changedWhileSuspend) { - this._changed(true); - } - } - }, - - /** - * Returns the upper left corner's point regardless of the - * bound delimiter points. - */ - upperLeft: function() { - var result = {}; - result.x = this.a.x; - result.y = this.a.y; - return result; - }, - - /** - * Returns the lower Right left corner's point regardless of the - * bound delimiter points. - */ - lowerRight: function() { - var result = {}; - result.x = this.b.x; - result.y = this.b.y; - return result; - }, - - /** - * @return {Number} Width of bounds. - */ - width: function() { - return this.b.x - this.a.x; - }, - - /** - * @return {Number} Height of bounds. - */ - height: function() { - return this.b.y - this.a.y; - }, - - /** - * @return {Point} The center point of this bounds. - */ - center: function() { - var center = {}; - center.x =(this.a.x + this.b.x)/2.0; - center.y =(this.a.y + this.b.y)/2.0; - return center; - }, + _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], - - /** - * @return {Point} The center point of this bounds relative to upperLeft. - */ - midPoint: function() { - - var midpoint = {}; - midpoint.x = (this.b.x - this.a.x)/2.0; - midpoint.y = (this.b.y - this.a.y)/2.0; - return midpoint; - }, - - /** - * Moves the center point of this bounds to the new position. - * @param p {Point} - * or - * @param x {Number} - * @param y {Number} - */ - centerMoveTo: function() { - var currentPosition = this.center(); - - switch (arguments.length) { - - case 1: - this.moveBy(arguments[0].x - currentPosition.x, - arguments[0].y - currentPosition.y); - break; - - case 2: - this.moveBy(arguments[0] - currentPosition.x, - arguments[1] - currentPosition.y); - break; - } - }, - - isIncluded: function(point, offset) { - - var pointX, pointY, offset; - - // Get the the two Points - switch(arguments.length) { - case 1: - pointX = arguments[0].x; - pointY = arguments[0].y; - offset = 0; - - break; - case 2: - if(arguments[0].x && arguments[0].y) { - pointX = arguments[0].x; - pointY = arguments[0].y; - offset = Math.abs(arguments[1]); - } else { - pointX = arguments[0]; - pointY = arguments[1]; - offset = 0; - } - break; - case 3: - pointX = arguments[0]; - pointY = arguments[1]; - offset = Math.abs(arguments[2]); - break; - default: - throw "isIncluded needs one, two or three arguments"; - } - - var ul = this.upperLeft(); - var lr = this.lowerRight(); - - if(pointX >= ul.x - offset - && pointX <= lr.x + offset && pointY >= ul.y - offset - && pointY <= lr.y + offset) - return true; - else - return false; - }, - - /** - * @return {Bounds} A copy of this bounds. - */ - clone: function() { - - //Returns a new bounds object without the callback - // references of the original bounds - return new ORYX.Core.Bounds(this); - }, - - toString: function() { - - return "( "+this.a.x+" | "+this.a.y+" )/( "+this.b.x+" | "+this.b.y+" )"; - }, - - serializeForERDF: function() { + /** + * Constructor + * @param options {Object} : + * textElement + * + */ + construct: function (options) { + arguments.callee.$.construct.apply(this, arguments); - return this.a.x+","+this.a.y+","+this.b.x+","+this.b.y; - } - }; - -ORYX.Core.Bounds = Clazz.extend(ORYX.Core.Bounds);/* - * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. - * License rights for this program may be obtained from Alfresco Software, Ltd. - * pursuant to a written agreement and any use of this program without such an - * agreement is prohibited. - */ -/* - * All code Copyright 2013 KIS Consultancy all rights reserved - */ + if (!options.textElement) { + throw "Label: No parameter textElement." + } else if (!ORYX.Editor.checkClassType(options.textElement, SVGTextElement)) { + throw "Label: Parameter textElement is not an SVGTextElement." + } -/** - * Init namespaces - */ -if(!ORYX) {var ORYX = {};} -if(!ORYX.Core) {ORYX.Core = {};} + this.invisibleRenderPoint = -5000; + this.node = options.textElement; -/** - * @classDescription Abstract base class for all objects that have a graphical representation - * within the editor. - * @extends Clazz - */ -ORYX.Core.UIObject = { - /** - * Constructor of the UIObject class. - */ - construct: function(options) { - - this.isChanged = true; //Flag, if UIObject has been changed since last update. - this.isResized = true; - this.isVisible = true; //Flag, if UIObject's display attribute is set to 'inherit' or 'none' - this.isSelectable = false; //Flag, if UIObject is selectable. - this.isResizable = false; //Flag, if UIObject is resizable. - this.isMovable = false; //Flag, if UIObject is movable. - - this.id = ORYX.Editor.provideId(); //get unique id - this.parent = undefined; //parent is defined, if this object is added to another uiObject. - this.node = undefined; //this is a reference to the SVG representation, either locally or in DOM. - this.children = []; //array for all add uiObjects - - this.bounds = new ORYX.Core.Bounds(); //bounds with undefined values - - this._changedCallback = this._changed.bind(this); //callback reference for calling _changed - this.bounds.registerCallback(this._changedCallback); //set callback in bounds - - if(options && options.eventHandlerCallback) { - this.eventHandlerCallback = options.eventHandlerCallback; - } - }, - - /** - * Sets isChanged flag to true. Callback for the bounds object. - */ - _changed: function(bounds, isResized) { - this.isChanged = true; - if(this.bounds == bounds) - this.isResized = isResized || this.isResized; - }, - - /** - * If something changed, this method calls the refresh method that must be implemented by subclasses. - */ - update: function() { - if(this.isChanged) { - this.refresh(); - this.isChanged = false; - - //call update of all children - this.children.each(function(value) { - value.update(); - }); - } - }, - - /** - * Is called in update method, if isChanged is set to true. Sub classes should call the super class method. - */ - refresh: function() { - - }, - - /** - * @return {Array} Array of all child UIObjects. - */ - getChildren: function() { - return this.children.clone(); - }, - - /** - * @return {Array} Array of all parent UIObjects. - */ - getParents: function(){ - var parents = []; - var parent = this.parent; - while(parent){ - parents.push(parent); - parent = parent.parent; - } - return parents; - }, - - /** - * Returns TRUE if the given parent is one of the UIObjects parents or the UIObject themselves, otherwise FALSE. - * @param {UIObject} parent - * @return {Boolean} - */ - isParent: function(parent){ - var cparent = this; - while(cparent){ - if (cparent === parent){ - return true; - } - cparent = cparent.parent; - } - return false; - }, - - /** - * @return {String} Id of this UIObject - */ - getId: function() { - return this.id; - }, - - /** - * Method for accessing child uiObjects by id. - * @param {String} id - * @param {Boolean} deep - * - * @return {UIObject} If found, it returns the UIObject with id. - */ - getChildById: function(id, deep) { - return this.children.find(function(uiObj) { - if(uiObj.getId() === id) { - return uiObj; - } else { - if(deep) { - var obj = uiObj.getChildById(id, deep); - if(obj) { - return obj; - } - } - } - }); - }, - - /** - * Adds an UIObject to this UIObject and sets the parent of the - * added UIObject. It is also added to the SVG representation of this - * UIObject. - * @param {UIObject} uiObject - */ - add: function(uiObject) { - //add uiObject, if it is not already a child of this object - if (!(this.children.member(uiObject))) { - //if uiObject is child of another parent, remove it from that parent. - if(uiObject.parent) { - uiObject.remove(uiObject); - } - - //add uiObject to children - this.children.push(uiObject); - - //set parent reference - uiObject.parent = this; - - //add uiObject.node to this.node - uiObject.node = this.node.appendChild(uiObject.node); - - //register callback to get informed, if child is changed - uiObject.bounds.registerCallback(this._changedCallback); - - //uiObject.update(); - } else { - ORYX.Log.info("add: ORYX.Core.UIObject is already a child of this object."); - } - }, - - /** - * Removes UIObject from this UIObject. The SVG representation will also - * be removed from this UIObject's SVG representation. - * @param {UIObject} uiObject - */ - remove: function(uiObject) { - //if uiObject is a child of this object, remove it. - if (this.children.member(uiObject)) { - //remove uiObject from children - this.children = this._uiObjects.without(uiObject); - - //delete parent reference of uiObject - uiObject.parent = undefined; - - //delete uiObject.node from this.node - uiObject.node = this.node.removeChild(uiObject.node); - - //unregister callback to get informed, if child is changed - uiObject.bounds.unregisterCallback(this._changedCallback); - } else { - ORYX.Log.info("remove: ORYX.Core.UIObject is not a child of this object."); - } - - }, - - /** - * Calculates absolute bounds of this UIObject. - */ - absoluteBounds: function() { - if(this.parent) { - var absUL = this.absoluteXY(); - return new ORYX.Core.Bounds(absUL.x, absUL.y, - absUL.x + this.bounds.width(), - absUL.y + this.bounds.height()); - } else { - return this.bounds.clone(); - } - }, - /** - * @return {Point} The absolute position of this UIObject. - */ - absoluteXY: function() { - if(this.parent) { - var pXY = this.parent.absoluteXY(); - var result = {}; - result.x = pXY.x + this.bounds.upperLeft().x; - result.y = pXY.y + this.bounds.upperLeft().y; - return result; - } else { - var result = {}; - result.x = this.bounds.upperLeft().x; - result.y = this.bounds.upperLeft().y; - return result; - } - }, + this.node.setAttributeNS(null, 'stroke-width', '0pt'); + this.node.setAttributeNS(null, 'letter-spacing', '-0.01px'); - /** - * @return {Point} The absolute position from the Center of this UIObject. - */ - absoluteCenterXY: function() { - if(this.parent) { - var pXY = this.parent.absoluteXY(); - var result = {}; - result.x = pXY.x + this.bounds.center().x; - result.y = pXY.y + this.bounds.center().y; - return result; - - } else { - var result = {}; - result.x = this.bounds.center().x; - result.y = this.bounds.center().y; - return result; - } - }, - - /** - * Hides this UIObject and all its children. - */ - hide: function() { - this.node.setAttributeNS(null, 'display', 'none'); - this.isVisible = false; - this.children.each(function(uiObj) { - uiObj.hide(); - }); - }, - - /** - * Enables visibility of this UIObject and all its children. - */ - show: function() { - this.node.setAttributeNS(null, 'display', 'inherit'); - this.isVisible = true; - this.children.each(function(uiObj) { - uiObj.show(); - }); - }, - - addEventHandlers: function(node) { - - node.addEventListener(ORYX.CONFIG.EVENT_MOUSEDOWN, this._delegateEvent.bind(this), false); - node.addEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, this._delegateEvent.bind(this), false); - node.addEventListener(ORYX.CONFIG.EVENT_MOUSEUP, this._delegateEvent.bind(this), false); - node.addEventListener(ORYX.CONFIG.EVENT_MOUSEOVER, this._delegateEvent.bind(this), false); - node.addEventListener(ORYX.CONFIG.EVENT_MOUSEOUT, this._delegateEvent.bind(this), false); - node.addEventListener('click', this._delegateEvent.bind(this), false); - node.addEventListener(ORYX.CONFIG.EVENT_DBLCLICK, this._delegateEvent.bind(this), false); - - }, - - _delegateEvent: function(event) { - if(this.eventHandlerCallback) { - this.eventHandlerCallback(event, this); - } - }, - - toString: function() { return "UIObject " + this.id } - }; - ORYX.Core.UIObject = Clazz.extend(ORYX.Core.UIObject);/* - * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. - * License rights for this program may be obtained from Alfresco Software, Ltd. - * pursuant to a written agreement and any use of this program without such an - * agreement is prohibited. - */ -/* - * All code Copyright 2013 KIS Consultancy all rights reserved - */ + this.shapeId = options.shapeId; -/** - * Init namespaces - */ -if(!ORYX) {var ORYX = {};} -if(!ORYX.Core) {ORYX.Core = {};} + this.id; -/** - * Top Level uiobject. - * @class ORYX.Core.AbstractShape - * @extends ORYX.Core.UIObject - */ -ORYX.Core.AbstractShape = ORYX.Core.UIObject.extend( -/** @lends ORYX.Core.AbstractShape.prototype */ -{ + this.fitToElemId; - /** - * Constructor - */ - construct: function(options, stencil, facade) { - - arguments.callee.$.construct.apply(this, arguments); - - this.resourceId = ORYX.Editor.provideId(); //Id of resource in DOM - - // stencil reference - this._stencil = stencil; - // if the stencil defines a super stencil that should be used for its instances, set it. - if (this._stencil._jsonStencil.superId){ - stencilId = this._stencil.id() - superStencilId = stencilId.substring(0, stencilId.indexOf("#") + 1) + stencil._jsonStencil.superId; - stencilSet = this._stencil.stencilSet(); - this._stencil = stencilSet.stencil(superStencilId); - } - - //Hash map for all properties. Only stores the values of the properties. - this.properties = new Hash(); - this.propertiesChanged = new Hash(); - - // List of properties which are not included in the stencilset, - // but which gets (de)serialized - this.hiddenProperties = new Hash(); - - - //Initialization of property map and initial value. - this._stencil.properties().each((function(property) { - var key = property.prefix() + "-" + property.id(); - this.properties[key] = property.value(); - this.propertiesChanged[key] = true; - }).bind(this)); - - // if super stencil was defined, also regard stencil's properties: - if (stencil._jsonStencil.superId) { - stencil.properties().each((function(property) { - var key = property.prefix() + "-" + property.id(); - var value = property.value(); - var oldValue = this.properties[key]; - this.properties[key] = value; - this.propertiesChanged[key] = true; - - // Raise an event, to show that the property has changed - // required for plugins like processLink.js - //window.setTimeout( function(){ - - this._delegateEvent({ - type : ORYX.CONFIG.EVENT_PROPERTY_CHANGED, - name : key, - value : value, - oldValue: oldValue - }); - - //}.bind(this), 10) - - }).bind(this)); - } + this.edgePosition; - }, + this.x; + this.y; + this.oldX; + this.oldY; - layout: function() { + this.isVisible = true; - }, - - /** - * Returns the stencil object specifiing the type of the shape. - */ - getStencil: function() { - return this._stencil; - }, - - /** - * - * @param {Object} resourceId - */ - getChildShapeByResourceId: function(resourceId) { + this._text; + this._verticalAlign; + this._horizontalAlign; + this._rotate; + this._rotationPoint; - resourceId = ERDF.__stripHashes(resourceId); - - return this.getChildShapes(true).find(function(shape) { - return shape.resourceId == resourceId - }); - }, - /** - * - * @param {Object} deep - * @param {Object} iterator - */ - getChildShapes: function(deep, iterator) { - var result = []; - - this.children.each(function(uiObject) { - if(uiObject instanceof ORYX.Core.Shape && uiObject.isVisible ) { - if(iterator) { - iterator(uiObject); - } - result.push(uiObject); - if(deep) { - result = result.concat(uiObject.getChildShapes(deep, iterator)); - } - } - }); + //this.anchors = []; + this.anchorLeft; + this.anchorRight; + this.anchorTop; + this.anchorBottom; - return result; - }, - - /** - * @param {Object} shape - * @return {boolean} true if any of shape's childs is given shape - */ - hasChildShape: function(shape){ - return this.getChildShapes().any(function(child){ - return (child === shape) || child.hasChildShape(shape); - }); - }, - - /** - * - * @param {Object} deep - * @param {Object} iterator - */ - getChildNodes: function(deep, iterator) { - var result = []; - - this.children.each(function(uiObject) { - if(uiObject instanceof ORYX.Core.Node && uiObject.isVisible) { - if(iterator) { - iterator(uiObject); - } - result.push(uiObject); - } - if(uiObject instanceof ORYX.Core.Shape) { - if(deep) { - result = result.concat(uiObject.getChildNodes(deep, iterator)); - } - } - }); + this._isChanged = true; - return result; - }, - - /** - * - * @param {Object} deep - * @param {Object} iterator - */ - getChildEdges: function(deep, iterator) { - var result = []; - - this.children.each(function(uiObject) { - if(uiObject instanceof ORYX.Core.Edge && uiObject.isVisible) { - if(iterator) { - iterator(uiObject); - } - result.push(uiObject); - } - if(uiObject instanceof ORYX.Core.Shape) { - if(deep) { - result = result.concat(uiObject.getChildEdges(deep, iterator)); - } - } - }); + //if the text element already has an id, don't change it. + var _id = this.node.getAttributeNS(null, 'id'); + if (_id) { + this.id = _id; + } - return result; - }, - - /** - * Returns a sorted array of ORYX.Core.Node objects. - * Ordered in z Order, the last object has the highest z Order. - */ - //TODO deep iterator - getAbstractShapesAtPosition: function() { - var x, y; - switch (arguments.length) { - case 1: - x = arguments[0].x; - y = arguments[0].y; - break; - case 2: //two or more arguments - x = arguments[0]; - y = arguments[1]; - break; - default: - throw "getAbstractShapesAtPosition needs 1 or 2 arguments!" - } + //initialization + + //set referenced element the text is fit to + this.fitToElemId = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'fittoelem'); + if (this.fitToElemId) + this.fitToElemId = this.shapeId + this.fitToElemId; + + //set alignment + var alignValues = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'align'); + if (alignValues) { + alignValues = alignValues.replace(/,/g, " "); + alignValues = alignValues.split(" "); + alignValues = alignValues.without(""); + + alignValues.each((function (alignValue) { + switch (alignValue) { + case 'top': + case 'middle': + case 'bottom': + if (!this._verticalAlign) { + this._originVerticalAlign = this._verticalAlign = alignValue; + } + break; + case 'left': + case 'center': + case 'right': + if (!this._horizontalAlign) { + this._originHorizontalAlign = this._horizontalAlign = alignValue; + } + break; + } + }).bind(this)); + } - if(this.isPointIncluded(x, y)) { - - var result = []; - result.push(this); - - //check, if one child is at that position - - - var childNodes = this.getChildNodes(); - var childEdges = this.getChildEdges(); - - [childNodes, childEdges].each(function(ne){ - var nodesAtPosition = new Hash(); - - ne.each(function(node) { - if(!node.isVisible){ return } - var candidates = node.getAbstractShapesAtPosition( x , y ); - if(candidates.length > 0) { - var nodesInZOrder = $A(node.node.parentNode.childNodes); - var zOrderIndex = nodesInZOrder.indexOf(node.node); - nodesAtPosition[zOrderIndex] = candidates; - } - }); - - nodesAtPosition.keys().sort().each(function(key) { - result = result.concat(nodesAtPosition[key]); - }); - }); - - return result; - - } else { - return []; - } - }, - - /** - * - * @param key {String} Must be 'prefix-id' of property - * @param value {Object} Can be of type String or Number according to property type. - */ - setProperty: function(key, value, force) { - var oldValue = this.properties[key]; - if(oldValue !== value || force === true) { - this.properties[key] = value; - this.propertiesChanged[key] = true; - this._changed(); - - // Raise an event, to show that the property has changed - //window.setTimeout( function(){ - - if (!this._isInSetProperty) { - this._isInSetProperty = true; - - this._delegateEvent({ - type : ORYX.CONFIG.EVENT_PROPERTY_CHANGED, - elements : [this], - name : key, - value : value, - oldValue: oldValue - }); - - delete this._isInSetProperty; - } - //}.bind(this), 10) - } - }, - - /** - * Returns TRUE if one of the properties is flagged as dirty - * @return {boolean} - */ - isPropertyChanged: function(){ - return this.propertiesChanged.any(function(property){ return property.value }); - }, + //set edge position (only in case the label belongs to an edge) + this.edgePosition = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'edgePosition'); + if (this.edgePosition) { + this.originEdgePosition = this.edgePosition = this.edgePosition.toLowerCase(); + } - /** - * - * @param {String} Must be 'prefix-id' of property - * @param {Object} Can be of type String or Number according to property type. - */ - setHiddenProperty: function(key, value) { - // IF undefined, Delete - if (value === undefined) { - delete this.hiddenProperties[key]; - return; - } - var oldValue = this.hiddenProperties[key]; - if (oldValue !== value) { - this.hiddenProperties[key] = value; - } - }, - /** - * Calculate if the point is inside the Shape - * @param {Point} - */ - isPointIncluded: function(pointX, pointY, absoluteBounds) { - var absBounds = absoluteBounds ? absoluteBounds : this.absoluteBounds(); - return absBounds.isIncluded(pointX, pointY); - - }, - - /** - * Get the serialized object - * return Array with hash-entrees (prefix, name, value) - * Following values will given: - * Type - * Properties - */ - serialize: function() { - var serializedObject = []; - - // Add the type - serializedObject.push({name: 'type', prefix:'oryx', value: this.getStencil().id(), type: 'literal'}); - - // Add hidden properties - this.hiddenProperties.each(function(prop){ - serializedObject.push({name: prop.key.replace("oryx-", ""), prefix: "oryx", value: prop.value, type: 'literal'}); - }.bind(this)); - - // Add all properties - this.getStencil().properties().each((function(property){ - - var prefix = property.prefix(); // Get prefix - var name = property.id(); // Get name - - //if(typeof this.properties[prefix+'-'+name] == 'boolean' || this.properties[prefix+'-'+name] != "") - serializedObject.push({name: name, prefix: prefix, value: this.properties[prefix+'-'+name], type: 'literal'}); - }).bind(this)); - - return serializedObject; - }, - - - deserialize: function(serialize){ - // Search in Serialize - var initializedDocker = 0; - - // Sort properties so that the hidden properties are first in the list - serialize = 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)); - - serialize.each((function(obj){ - - var name = obj.name; - var prefix = obj.prefix; - var value = obj.value; - - // Complex properties can be real json objects, encode them to a string - if (Object.prototype.toString.call(value) === "Object") value = JSON.stringify(value); - - switch(prefix + "-" + name){ - case 'raziel-parent': - // Set parent - if(!this.parent) {break}; - - // Set outgoing Shape - var parent = this.getCanvas().getChildShapeByResourceId(value); - if(parent) { - parent.add(this); - } - - break; - default: - // If list, eval as an array - var prop = this.getStencil().property(prefix+"-"+name); - if (prop && prop.isList() && typeof value === "string"){ - if ((value||"").strip()&&!value.startsWith("[")&&!value.startsWith("]")) - value = "[\""+value.strip()+"\"]"; - value = ((value||"").strip()||"[]").evalJSON(); - } - - // Set property - if(this.properties.keys().member(prefix+"-"+name)) { - this.setProperty(prefix+"-"+name, value); - } else if(!(name === "bounds"||name === "parent"||name === "target"||name === "dockers"||name === "docker"||name === "outgoing"||name === "incoming")) { - this.setHiddenProperty(prefix+"-"+name, value); - } - - } - }).bind(this)); - }, - - toString: function() { return "ORYX.Core.AbstractShape " + this.id }, - - /** - * Converts the shape to a JSON representation. - * @return {Object} A JSON object with included ORYX.Core.AbstractShape.JSONHelper and getShape() method. - */ - toJSON: function(){ - var json = { - resourceId: this.resourceId, - properties: jQuery.extend({}, this.properties, this.hiddenProperties).inject({}, function(props, prop){ - var key = prop[0]; - var value = prop[1]; - - //If complex property, value should be a json object - if ( this.getStencil().property(key) - && this.getStencil().property(key).type() === ORYX.CONFIG.TYPE_COMPLEX - && Object.prototype.toString.call(value) === "String"){ - - try {value = JSON.parse(value);} catch(error){} - //try {value = JSON.parse(value);} catch(error){} - - // Parse date - } else if (value instanceof Date&&this.getStencil().property(key)){ - try { - value = value.format(this.getStencil().property(key).dateFormat()); - } catch(e){} - } - - //Takes "my_property" instead of "oryx-my_property" as key - key = key.replace(/^[\w_]+-/, ""); - props[key] = value; - - return props; - }.bind(this)), - stencil: { - id: this.getStencil().idWithoutNs() - }, - childShapes: this.getChildShapes().map(function(shape){ - return shape.toJSON(); - }) - }; - - if(this.getOutgoingShapes){ - json.outgoing = this.getOutgoingShapes().map(function(shape){ - return { - resourceId: shape.resourceId - }; - }); - } - - if(this.bounds){ - json.bounds = { - lowerRight: this.bounds.lowerRight(), - upperLeft: this.bounds.upperLeft() - }; + //get offset top + this.offsetTop = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'offsetTop') || ORYX.CONFIG.OFFSET_EDGE_LABEL_TOP; + if (this.offsetTop) { + this.offsetTop = parseInt(this.offsetTop); } - - if(this.dockers){ - json.dockers = this.dockers.map(function(docker){ - var d = docker.getDockedShape() && docker.referencePoint ? docker.referencePoint : docker.bounds.center(); - d.getDocker = function(){return docker;}; - return d; - }); + + //get offset top + this.offsetBottom = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'offsetBottom') || ORYX.CONFIG.OFFSET_EDGE_LABEL_BOTTOM; + if (this.offsetBottom) { + this.offsetBottom = parseInt(this.offsetBottom); } - - jQuery.extend(json, ORYX.Core.AbstractShape.JSONHelper); - - // do not pollute the json attributes (for serialization), so put the corresponding - // shape is encapsulated in a method - json.getShape = function(){ - return this; - }.bind(this); - - return json; - } - }); - -/** - * @namespace Collection of methods which can be used on a shape json object (ORYX.Core.AbstractShape#toJSON()). - * @example - * jQuery.extend(shapeAsJson, ORYX.Core.AbstractShape.JSONHelper); - */ -ORYX.Core.AbstractShape.JSONHelper = { - /** - * Iterates over each child shape. - * @param {Object} iterator Iterator function getting a child shape and his parent as arguments. - * @param {boolean} [deep=false] Iterate recursively (childShapes of childShapes) - * @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. - * @example - * // Increases the lowerRight x value of each direct child shape by one. - * myShapeAsJson.eachChild(function(shape, parentShape){ - * shape.bounds.lowerRight.x = shape.bounds.lowerRight.x + 1; - * return shape; - * }, false, true); - */ - eachChild: function(iterator, deep, modify){ - if(!this.childShapes) return; - - var newChildShapes = []; //needed if modify = true - - this.childShapes.each(function(shape){ - if (!(shape.eachChild instanceof Function)){ - jQuery.extend(shape, ORYX.Core.AbstractShape.JSONHelper); - } - var res = iterator(shape, this); - if(res) newChildShapes.push(res); //if false is returned, and modify = true, current shape is deleted. - - if(deep) shape.eachChild(iterator, deep, modify); - }.bind(this)); - - if(modify) this.childShapes = newChildShapes; - }, - - getShape: function(){ - return null; - }, - getChildShapes: function(deep){ - var allShapes = this.childShapes; - - if(deep){ - this.eachChild(function(shape){ - if (!(shape.getChildShapes instanceof Function)){ - jQuery.extend(shape, ORYX.Core.AbstractShape.JSONHelper); - } - allShapes = allShapes.concat(shape.getChildShapes(deep)); - }, true); - } - - return allShapes; - }, - - /** - * @return {String} Serialized JSON object - */ - serialize: function(){ - return JSON.stringify(this); - } - } -/* - * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. - * License rights for this program may be obtained from Alfresco Software, Ltd. - * pursuant to a written agreement and any use of this program without such an - * agreement is prohibited. - */ -/* - * All code Copyright 2013 KIS Consultancy all rights reserved - */ -/** - * Init namespaces - */ -if(!ORYX) {var ORYX = {};} -/** - @namespace Namespace for the Oryx core elements. - @name ORYX.Core -*/ -if(!ORYX.Core) {ORYX.Core = {};} + //set rotation + var rotateValue = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'rotate'); + if (rotateValue) { + try { + this._rotate = parseFloat(rotateValue); + } catch (e) { + this._rotate = 0; + } + } else { + this._rotate = 0; + } -/** - * @class Oryx canvas. - * @extends ORYX.Core.AbstractShape - * - */ -ORYX.Core.Canvas = ORYX.Core.AbstractShape.extend({ - /** @lends ORYX.Core.Canvas.prototype */ + //anchors + var anchorAttr = this.node.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, "anchors"); + if (anchorAttr) { + anchorAttr = anchorAttr.replace("/,/g", " "); + var anchors = anchorAttr.split(" ").without(""); - /** - * Defines the current zoom level - */ - zoomLevel:1, + for (var i = 0; i < anchors.length; i++) { + switch (anchors[i].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; + } + } + } - /** - * Constructor - */ - construct: function(options, stencil, facade) { - arguments.callee.$.construct.apply(this, arguments); + //if no alignment defined, set default alignment + if (!this._verticalAlign) { + this._verticalAlign = 'bottom'; + } + if (!this._horizontalAlign) { + this._horizontalAlign = 'left'; + } - if(!(options && options.width && options.height)) { - - ORYX.Log.fatal("Canvas is missing mandatory parameters options.width and options.height."); - return; - } - this.facade = facade; - //TODO: set document resource id - this.resourceId = options.id; - - this.nodes = []; - - this.edges = []; - - // Row highlighting states - this.colHighlightState = 0; - - this.colHighlightEnabled = false; - - //init svg document - this.rootNode = ORYX.Editor.graft("http://www.w3.org/2000/svg", options.parentNode, - ['svg', {id: this.id, width: options.width, height: options.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", options.parentNode, - ['div', {id: "oryx_canvas_htmlContainer", style:"position:absolute; top:5px"}]); - - // Additional SVG-node BELOW the stencils to allow underlays (if that is even a word) by plugins - this.underlayNode = ORYX.Editor.graft("http://www.w3.org/2000/svg", this.rootNode, - ['svg', {id: "underlay-container"}]); - - // Create 2 svg-elements in the svg-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"}] - ]); - - /* - var off = 2 * ORYX.CONFIG.GRID_DISTANCE; - var size = 3; - var d = ""; - for(var i = 0; i <= options.width; i += off) - for(var j = 0; j <= options.height; j += off) - d = d + "M" + (i - size) + " " + j + " l" + (2*size) + " 0 m" + (-size) + " " + (-size) + " l0 " + (2*size) + " m0" + (-size) + " "; - - ORYX.Editor.graft("http://www.w3.org/2000/svg", this.node.firstChild.firstChild, - ['path', {d:d , stroke:'#000000', 'stroke-width':'0.15px'},]); - */ - - //Global definition of default font for shapes - //Definitions in the SVG definition of a stencil will overwrite these settings for - // that stencil. - /*if(navigator.platform.indexOf("Mac") > -1) { - this.node.setAttributeNS(null, 'stroke', 'black'); - this.node.setAttributeNS(null, 'stroke-width', '0.5px'); - this.node.setAttributeNS(null, 'font-family', 'Skia'); - //this.node.setAttributeNS(null, 'letter-spacing', '2px'); - this.node.setAttributeNS(null, 'font-size', ORYX.CONFIG.LABEL_DEFAULT_LINE_HEIGHT); - } else { - this.node.setAttributeNS(null, 'stroke', 'none'); - this.node.setAttributeNS(null, 'font-family', 'Verdana'); - this.node.setAttributeNS(null, 'font-size', ORYX.CONFIG.LABEL_DEFAULT_LINE_HEIGHT); - }*/ - - 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,options.width, options.height); - - this.addEventHandlers(this.rootNode.parentNode); - - //disable context menu - this.rootNode.oncontextmenu = function() {return false;}; - }, - - focus: function(){ - - try { - // Get a href - if (!this.focusEl) - { - this.focusEl = jQuery('body').append(jQuery('')); - this.focusEl.swallowEvent("click", true); - } - - // Focus it - this.focusEl.focus.defer(1, this.focusEl); - this.focusEl.blur.defer(3, this.focusEl); - - } catch(e){} - }, - - setHightlightState: function(state) { - if(this.colHighlightEnabled && this.colHighlightState != state) { - if(state == 0) { - this.columnHightlight1.setAttribute("visibility", "hidden"); - this.columnHightlight2.setAttribute("visibility", "hidden"); - } else if(state == 1) { - this.columnHightlight1.setAttribute("visibility", "visible"); - this.columnHightlight2.setAttribute("visibility", "hidden"); - } else if(state == 2) { - this.columnHightlight1.setAttribute("visibility", "hidden"); - this.columnHightlight2.setAttribute("visibility", "visible"); - } else if(state == 3) { - this.columnHightlight1.setAttribute("visibility", "visible"); - this.columnHightlight2.setAttribute("visibility", "visible"); - } - this.colHighlightState = state; - } - }, - - setHightlightStateBasedOnX : function(x) { - if(x > ORYX.CONFIG.FORM_ROW_WIDTH + 30) { - this.setHightlightState(2); - } else { - this.setHightlightState(1); - } - }, - - update: function() { - - this.nodes.each(function(node) { - this._traverseForUpdate(node); - }.bind(this)); - - // call stencil's layout callback - // (needed for row layouting of xforms) - //this.getStencil().layout(this); - - var layoutEvents = this.getStencil().layout(); - - if(layoutEvents) { - layoutEvents.each(function(event) { - - // setup additional attributes - event.shape = this; - event.forceExecution = true; - event.target = this.rootNode; - - // do layouting - - this._delegateEvent(event); - }.bind(this)) - } - - this.nodes.invoke("_update"); - - this.edges.invoke("_update", true); - - /*this.children.each(function(child) { - child._update(); - });*/ - }, - - _traverseForUpdate: function(shape) { - var childRet = shape.isChanged; - shape.getChildNodes(false, function(child) { - if(this._traverseForUpdate(child)) { - childRet = true; - } - }.bind(this)); - - if(childRet) { - shape.layout(); - return true; - } else { - return false; - } - }, - - layout: function() { - - - - }, - - /** - * - * @param {Object} deep - * @param {Object} iterator - */ - getChildNodes: function(deep, iterator) { - if(!deep && !iterator) { - return this.nodes.clone(); - } else { - var result = []; - this.nodes.each(function(uiObject) { - if(iterator) { - iterator(uiObject); - } - result.push(uiObject); - - if(deep && uiObject instanceof ORYX.Core.Shape) { - result = result.concat(uiObject.getChildNodes(deep, iterator)); - } - }); - - return result; - } - }, - - /** - * buggy crap! use base class impl instead! - * @param {Object} iterator - */ -/* getChildEdges: function(iterator) { - if(iterator) { - this.edges.each(function(edge) { - iterator(edge); - }); - } - - return this.edges.clone(); - }, -*/ - /** - * Overrides the UIObject.add method. Adds uiObject to the correct sub node. - * @param {UIObject} uiObject - */ - add: function(uiObject, index, silent) { - //if uiObject is child of another UIObject, remove it. - if(uiObject instanceof ORYX.Core.UIObject) { - if (!(this.children.member(uiObject))) { - //if uiObject is child of another parent, remove it from that parent. - if(uiObject.parent) { - uiObject.parent.remove(uiObject, true); - } - - //add uiObject to the Canvas - //add uiObject to this Shape - if(index != undefined) - this.children.splice(index, 0, uiObject); - else - this.children.push(uiObject); - - //set parent reference - uiObject.parent = this; - - //add uiObject.node to this.node depending on the type of uiObject - if(uiObject instanceof ORYX.Core.Shape) { - if(uiObject instanceof ORYX.Core.Edge) { - uiObject.addMarkers(this.rootNode.getElementsByTagNameNS(NAMESPACE_SVG, "defs")[0]); - uiObject.node = this.node.childNodes[0].childNodes[2].appendChild(uiObject.node); - this.edges.push(uiObject); - } else { - uiObject.node = this.node.childNodes[0].childNodes[1].appendChild(uiObject.node); - this.nodes.push(uiObject); - } - } else { //UIObject - uiObject.node = this.node.appendChild(uiObject.node); - } - - uiObject.bounds.registerCallback(this._changedCallback); - - if(this.eventHandlerCallback && silent !== true) - this.eventHandlerCallback({type:ORYX.CONFIG.EVENT_SHAPEADDED,shape:uiObject}) - } 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."); - } - }, + var xValue = this.node.getAttributeNS(null, 'x'); + if (xValue) { + this.oldX = this.x = parseFloat(xValue); + } else { + //TODO error + } - /** - * Overrides the UIObject.remove method. Removes uiObject. - * @param {UIObject} uiObject - */ - remove: function(uiObject, silent) { - //if uiObject is a child of this object, remove it. - if (this.children.member(uiObject)) { - //remove uiObject from children - var parent = uiObject.parent; - - this.children = this.children.without(uiObject); - - //delete parent reference of uiObject - uiObject.parent = undefined; - - //delete uiObject.node from this.node - if(uiObject instanceof ORYX.Core.Shape) { - if(uiObject instanceof ORYX.Core.Edge) { - uiObject.removeMarkers(); - uiObject.node = this.node.childNodes[0].childNodes[2].removeChild(uiObject.node); - this.edges = this.edges.without(uiObject); - } else { - uiObject.node = this.node.childNodes[0].childNodes[1].removeChild(uiObject.node); - this.nodes = this.nodes.without(uiObject); - } - } else { //UIObject - uiObject.node = this.node.removeChild(uiObject.node); - } + var yValue = this.node.getAttributeNS(null, 'y'); + if (yValue) { + this.oldY = this.y = parseFloat(yValue); + } else { + //TODO error + } - if(this.eventHandlerCallback && silent !== true) - this.eventHandlerCallback({type:ORYX.CONFIG.EVENT_SHAPEREMOVED,shape:uiObject, parent:parent}); - - uiObject.bounds.unregisterCallback(this._changedCallback); - } else { + //set initial text + this.text(this.node.textContent); + }, - ORYX.Log.warn("remove: ORYX.Core.UIObject is not a child of this object."); - } - }, - /** - * Creates shapes out of the given collection of shape objects and adds them to the canvas. - * @example - * canvas.addShapeObjects({ - bounds:{ lowerRight:{ y:510, x:633 }, upperLeft:{ y:146, x:210 } }, - resourceId:"oryx_F0715955-50F2-403D-9851-C08CFE70F8BD", - childShapes:[], - properties:{}, - stencil:{ - id:"Subprocess" - }, - outgoing:[{resourceId: 'aShape'}], - target: {resourceId: 'aShape'} - }); - * @param {Object} shapeObjects - * @param {Function} [eventHandler] An event handler passed to each newly created shape (as eventHandlerCallback) - * @return {Array} A collection of ORYX.Core.Shape - * @methodOf ORYX.Core.Canvas.prototype + * Reset the anchor position to the original value + * which was specified in the stencil set + * */ - addShapeObjects: function(shapeObjects, eventHandler){ - if(!shapeObjects) return; - - this.initializingShapes = true; - - /*FIXME This implementation is very evil! At first, all shapes are created on - canvas. In a second step, the attributes are applied. There must be a distinction - between the configuration phase (where the outgoings, for example, are just named), - and the creation phase (where the outgoings are evaluated). This must be reflected - in code to provide a nicer API/ implementation!!! */ - - var addShape = function(shape, parent){ - // Create a new Stencil - var stencil = ORYX.Core.StencilSet.stencil(this.getStencil().namespace() + shape.stencil.id ); - - // Create a new Shape - var ShapeClass = (stencil.type() == "node") ? ORYX.Core.Node : ORYX.Core.Edge; - var newShape = new ShapeClass( - {'eventHandlerCallback': eventHandler}, - stencil, this.facade); - - // Set the resource id - newShape.resourceId = shape.resourceId; - newShape.node.id = "svg-" + shape.resourceId; - - // Set parent to json object to be used later - // Due to the nested json structure, normally shape.parent is not set/ must not be set. - // In special cases, it can be easier to set this directly instead of a nested structure. - shape.parent = "#" + ((shape.parent && shape.parent.resourceId) || parent.resourceId); - - // Add the shape to the canvas - this.add( newShape ); + resetAnchorPosition: function () { + this.anchorLeft = this.originAnchorLeft || false; + this.anchorRight = this.originAnchorRight || false; + this.anchorTop = this.originAnchorTop || false; + this.anchorBottom = this.originAnchorBottom || false; + }, - return { - json: shape, - object: newShape - }; - }.bind(this); - - /** Builds up recursively a flatted array of shapes, including a javascript object and json representation - * @param {Object} shape Any object that has Object#childShapes - */ - var addChildShapesRecursively = function(shape){ - var addedShapes = []; - - if (shape.childShapes && shape.childShapes.constructor == String) - { - shape.childShapes = JSON.parse(shape.childShapes); - } - - shape.childShapes.each(function(childShape){ - addedShapes.push(addShape(childShape, shape)); - addedShapes = addedShapes.concat(addChildShapesRecursively(childShape)); - }); - - return addedShapes; - }.bind(this); + isOriginAnchorLeft: function () { + return this.originAnchorLeft || false; + }, + isOriginAnchorRight: function () { + return this.originAnchorRight || false; + }, + isOriginAnchorTop: function () { + return this.originAnchorTop || false; + }, + isOriginAnchorBottom: function () { + return this.originAnchorBottom || false; + }, - var shapes = addChildShapesRecursively({ - childShapes: shapeObjects, - resourceId: this.resourceId - }); - - // prepare deserialisation parameter - shapes.each( - function(shape){ - var properties = []; - for(field in shape.json.properties){ - properties.push({ - prefix: 'oryx', - name: field, - value: shape.json.properties[field] - }); - } - - // Outgoings - shape.json.outgoing.each(function(out){ - properties.push({ - prefix: 'raziel', - name: 'outgoing', - value: "#"+out.resourceId - }); - }); - - // Target - // (because of a bug, the first outgoing is taken when there is no target, - // can be removed after some time) - if(shape.object instanceof ORYX.Core.Edge) { - var target = shape.json.target || shape.json.outgoing[0]; - if(target){ - properties.push({ - prefix: 'raziel', - name: 'target', - value: "#"+target.resourceId - }); - } - } - - // Bounds - if (shape.json.bounds) { - properties.push({ - prefix: 'oryx', - name: 'bounds', - value: shape.json.bounds.upperLeft.x + "," + shape.json.bounds.upperLeft.y + "," + shape.json.bounds.lowerRight.x + "," + shape.json.bounds.lowerRight.y - }); - } - - //Dockers [{x:40, y:50}, {x:30, y:60}] => "40 50 30 60 #" - if(shape.json.dockers){ - properties.push({ - prefix: 'oryx', - name: 'dockers', - value: shape.json.dockers.inject("", function(dockersStr, docker){ - return dockersStr + docker.x + " " + docker.y + " "; - }) + " #" - }); - } - - //Parent - properties.push({ - prefix: 'raziel', - name: 'parent', - value: shape.json.parent - }); - - shape.__properties = properties; - }.bind(this) - ); - - // Deserialize the properties from the shapes - // This can't be done earlier because Shape#deserialize expects that all referenced nodes are already there - - // first, deserialize all nodes - shapes.each(function(shape) { - if(shape.object instanceof ORYX.Core.Node) { - shape.object.deserialize(shape.__properties, shape.json); - } - }); - - // second, deserialize all edges - shapes.each(function(shape) { - if(shape.object instanceof ORYX.Core.Edge) { - shape.object.deserialize(shape.__properties, shape.json); - shape.object._oldBounds = shape.object.bounds.clone(); - shape.object._update(); - } - }); - - delete this.initializingShapes; - return shapes.pluck("object"); + isAnchorLeft: function () { + return this.anchorLeft || false; + }, + isAnchorRight: function () { + return this.anchorRight || false; + }, + isAnchorTop: function () { + return this.anchorTop || false; }, - + isAnchorBottom: function () { + return this.anchorBottom || false; + }, + /** - * Updates the size of the canvas, regarding to the containg shapes. + * Returns the x coordinate + * @return {number} */ - updateSize: function(){ - // Check the size for the canvas - var maxWidth = 0; - var maxHeight = 0; - var offset = 100; - this.getChildShapes(true, function(shape){ - var b = shape.bounds; - maxWidth = Math.max( maxWidth, b.lowerRight().x + offset) - maxHeight = Math.max( maxHeight, b.lowerRight().y + offset) - }); - - if( this.bounds.width() < maxWidth || this.bounds.height() < maxHeight ){ - this.setSize({width: Math.max(this.bounds.width(), maxWidth), height: Math.max(this.bounds.height(), maxHeight)}) + getX: function () { + try { + var x = this.node.x.baseVal.getItem(0).value; + switch (this.horizontalAlign()) { + case "left": + return x; + case "center": + return x - (this.getWidth() / 2); + case "right": + return x - this.getWidth(); + } + return this.node.getBBox().x; + } catch (e) { + return this.x; } }, - getRootNode: function() { - return this.rootNode; - }, - - getUnderlayNode: function() { - return this.underlayNode; - }, - - getSvgContainer: function() { - return this.node.childNodes[1]; - }, - - getHTMLContainer: function() { - return this._htmlContainer; - }, - - /** - * Return all elements of the same highest level - * @param {Object} elements - */ - getShapesWithSharedParent: function(elements) { - - // If there is no elements, return [] - if(!elements || elements.length < 1) { return []; } - // If there is one element, return this element - if(elements.length == 1) { return elements;} - - return elements.findAll(function(value){ - var parentShape = value.parent; - while(parentShape){ - if(elements.member(parentShape)) return false; - parentShape = parentShape.parent; - } - return true; - }); - - }, - - setSize: function(size, dontSetBounds) { - if(!size || !size.width || !size.height){return;}; - - if(this.rootNode.parentNode){ - this.rootNode.parentNode.style.width = size.width + 'px'; - this.rootNode.parentNode.style.height = size.height + 'px'; - } - - this.rootNode.setAttributeNS(null, 'width', size.width); - this.rootNode.setAttributeNS(null, 'height', size.height); + setX: function (x) { + if (this.position) + this.position.x = x; + else + this.setOriginX(x); + }, - //this._htmlContainer.style.top = "-" + (size.height + 4) + 'px'; - if( !dontSetBounds ){ - this.bounds.set({a:{x:0,y:0},b:{x:size.width/this.zoomLevel,y:size.height/this.zoomLevel}}); - } - }, - - /** - * Returns an SVG document of the current process. - * @param {Boolean} escapeText Use true, if you want to parse it with an XmlParser, - * false, if you want to use the SVG document in browser on client side. - */ - getSVGRepresentation: function(escapeText) { - // Get the serialized svg image source - var svgClone = this.getRootNode().cloneNode(true); - - this._removeInvisibleElements(svgClone); - - var x1, y1, x2, y2; - this.getChildShapes(true).each(function(shape) { - var absBounds = shape.absoluteBounds(); - var ul = absBounds.upperLeft(); - var lr = absBounds.lowerRight(); - if(x1 == undefined) { - x1 = ul.x; - y1 = ul.y; - x2 = lr.x; - y2 = lr.y; - } else { - x1 = Math.min(x1, ul.x); - y1 = Math.min(y1, ul.y); - x2 = Math.max(x2, lr.x); - y2 = Math.max(y2, lr.y); - } - }); - - var margin = 50; - var width, height, tx, ty; - if(x1 == undefined) { - width = 0; - height = 0; - tx = 0; - ty = 0; - } else { - width = x2; - height = y2; - tx = -x1+margin/2; - ty = -y1+margin/2; - } - - // Set the width and height - svgClone.setAttributeNS(null, 'width', width + margin); - svgClone.setAttributeNS(null, 'height', height + margin); - - //remove scale factor - svgClone.childNodes[1].removeAttributeNS(null, 'transform'); - - try{ - var svgCont = svgClone.childNodes[1].childNodes[1]; - svgCont.parentNode.removeChild(svgCont); - } catch(e) {} - - if(escapeText) { - $A(svgClone.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'tspan')).each(function(elem) { - elem.textContent = elem.textContent.escapeHTML(); - }); - - $A(svgClone.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'text')).each(function(elem) { - if(elem.childNodes.length == 0) - elem.textContent = elem.textContent.escapeHTML(); - }); - } - - // generating absolute urls for the pdf-exporter - $A(svgClone.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'image')).each(function(elem) { - var href = elem.getAttributeNS("http://www.w3.org/1999/xlink","href"); - - if(!href.match("^(http|https)://")) { - href = window.location.protocol + "//" + window.location.host + href; - elem.setAttributeNS("http://www.w3.org/1999/xlink", "href", href); - } - }); - - - // escape all links - $A(svgClone.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'a')).each(function(elem) { - elem.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", (elem.getAttributeNS("http://www.w3.org/1999/xlink","href")||"").escapeHTML()); - }); - - return svgClone; - }, - - /** - * Removes all nodes (and its children) that has the - * attribute visibility set to "hidden" - */ - _removeInvisibleElements: function(element) { - var index = 0; - while(index < element.childNodes.length) { - var child = element.childNodes[index]; - if(child.getAttributeNS && - child.getAttributeNS(null, "visibility") === "hidden") { - element.removeChild(child); - } else { - this._removeInvisibleElements(child); - index++; - } - } - - }, - - /** - * This method checks all shapes on the canvas and removes all shapes that - * contain invalid bounds values or dockers values(NaN) - */ - /*cleanUp: function(parent) { - if (!parent) { - parent = this; - } - parent.getChildShapes().each(function(shape){ - var a = shape.bounds.a; - var b = shape.bounds.b; - if (isNaN(a.x) || isNaN(a.y) || isNaN(b.x) || isNaN(b.y)) { - parent.remove(shape); - } - else { - shape.getDockers().any(function(docker) { - a = docker.bounds.a; - b = docker.bounds.b; - if (isNaN(a.x) || isNaN(a.y) || isNaN(b.x) || isNaN(b.y)) { - parent.remove(shape); - return true; - } - return false; - }); - shape.getMagnets().any(function(magnet) { - a = magnet.bounds.a; - b = magnet.bounds.b; - if (isNaN(a.x) || isNaN(a.y) || isNaN(b.x) || isNaN(b.y)) { - parent.remove(shape); - return true; - } - return false; - }); - this.cleanUp(shape); - } - }.bind(this)); - },*/ - _delegateEvent: function(event) { - if(this.eventHandlerCallback && ( event.target == this.rootNode || event.target == this.rootNode.parentNode )) { - this.eventHandlerCallback(event, this); - } - }, - - toString: function() { return "Canvas " + this.id }, - /** - * Calls {@link ORYX.Core.AbstractShape#toJSON} and adds some stencil set information. + * Returns the y coordinate + * @return {number} */ - toJSON: function() { - var json = arguments.callee.$.toJSON.apply(this, arguments); - -// if(ORYX.CONFIG.STENCILSET_HANDLER.length > 0) { -// json.stencilset = { -// url: this.getStencil().stencilSet().namespace() -// }; -// } else { - json.stencilset = { - url: this.getStencil().stencilSet().source(), - namespace: this.getStencil().stencilSet().namespace() - }; -// } - - - return json; - } - });/* - * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. - * License rights for this program may be obtained from Alfresco Software, Ltd. - * pursuant to a written agreement and any use of this program without such an - * agreement is prohibited. - */ -var idCounter = 0; -var ID_PREFIX = "resource"; + getY: function () { + try { + return this.node.getBBox().y; + } catch (e) { + return this.y; + } + }, -/** - * Main initialization method. To be called when loading - * of the document, including all scripts, is completed. - */ -function init() { + setY: function (y) { + if (this.position) + this.position.y = y; + else + this.setOriginY(y); + }, - ORYX.Log.debug("Querying editor instances"); + setOriginX: function (x) { + this.x = x; + }, - // Hack for WebKit to set the SVGElement-Classes - ORYX.Editor.setMissingClasses(); - - // If someone wants to create the editor instance himself - if (window.onOryxResourcesLoaded) { - window.onOryxResourcesLoaded(); - } - // Else fetch the model from server and display editor - else { - var modelId = window.location.search.substring(4); - var modelUrl = "./service/model/" + modelId + "/json"; + setOriginY: function (y) { + this.y = y; + }, - ORYX.Editor.createByUrl(modelUrl); - } -} -/** - @namespace Global Oryx name space - @name ORYX -*/ -if(!ORYX) {var ORYX = {};} + /** + * Returns the width of the label + * @return {number} + */ + getWidth: function () { + try { + try { + var width, cn = this.node.childNodes; + if (cn.length == 0) { + width = this.node.getBBox().width; + } else { + for (var i = 0, size = cn.length; i < size; ++i) { + var w = cn[i].getComputedTextLength(); + if ("undefined" == typeof width || width < w) { + width = w; + } + } + } + return width + (width % 2 == 0 ? 0 : 1); + } catch (ee) { + return this.node.getBBox().width; + } + } catch (e) { + return 0; + } + }, -/** - * The Editor class. - * @class ORYX.Editor - * @extends Clazz - * @param {Object} config An editor object, passed to {@link ORYX.Editor#loadSerialized} - * @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. - * @param {boolean} [config.fullscreen=true] Render editor in fullscreen mode or not. - * @param {String} config.stencilset.url Stencil set URL. - * @param {String} [config.stencil.id] Stencil type used for creating the canvas. - * @param {Object} config.properties Any properties applied to the canvas. -*/ -ORYX.Editor = { - /** @lends ORYX.Editor.prototype */ - // Defines the global dom event listener - DOMEventListeners: new Hash(), - - // Defines the selection - selection: [], - - // Defines the current zoom level - zoomLevel:1.0, - - construct: function(config) { - - // initialization. - this._eventsQueue = []; - this.loadedPlugins = []; - this.pluginsData = []; - - - //meta data about the model for the signavio warehouse - //directory, new, name, description, revision, model (the model data) - - this.modelMetaData = config; - - var model = config; - - this.id = model.modelId; - - if(config.model) { - model = config.model; - } - - if(!this.id) { - this.id = model.id; - if(!this.id) { - this.id = ORYX.Editor.provideId(); - } - } - - // Defines if the editor should be fullscreen or not - this.fullscreen = config.fullscreen !== false; - - // Initialize the eventlistener - this._initEventListener(); - - // Load particular stencilset - if(ORYX.CONFIG.BACKEND_SWITCH) { - var ssUrl = (model.stencilset.namespace||model.stencilset.url).replace("#", "%23"); - ORYX.Core.StencilSet.loadStencilSet(ssUrl, this.modelMetaData, this.id); - } else { - var ssUrl = model.stencilset.url; - ORYX.Core.StencilSet.loadStencilSet(ssUrl, this.modelMetaData, this.id); - } + getOriginUpperLeft: function () { + var x = this.x, y = this.y; + switch (this._horizontalAlign) { + case 'center' : + x -= this.getWidth() / 2; + break; + case 'right' : + x -= this.getWidth(); + break; + } + switch (this._verticalAlign) { + case 'middle' : + y -= this.getHeight() / 2; + break; + case 'bottom' : + y -= this.getHeight(); + break; + } + return {x: x, y: y}; + }, - // CREATES the canvas - this._createCanvas(model.stencil ? model.stencil.id : null, model.properties); - - // GENERATES the whole EXT.VIEWPORT - this._generateGUI(); - - // Initializing of a callback to check loading ends - var loadPluginFinished = false; - var loadContentFinished = false; - var initFinished = function(){ - if( !loadPluginFinished || !loadContentFinished ){ return } - this._finishedLoading(); - }.bind(this) - - // LOAD the plugins - window.setTimeout(function(){ - this.loadPlugins(); - loadPluginFinished = true; - initFinished(); - }.bind(this), 100); - - // LOAD the content of the current editor instance - window.setTimeout(function(){ - this.loadSerialized(model, true); // Request the meta data as well - this.getCanvas().update(); - loadContentFinished = true; - initFinished(); - }.bind(this), 200); - }, - - _finishedLoading: function() { - // Raise Loaded Event - this.handleEvents( {type:ORYX.CONFIG.EVENT_LOADED} ) - }, - - _initEventListener: function(){ - - // Register on Events - - document.documentElement.addEventListener(ORYX.CONFIG.EVENT_KEYDOWN, this.catchKeyDownEvents.bind(this), false); - document.documentElement.addEventListener(ORYX.CONFIG.EVENT_KEYUP, this.catchKeyUpEvents.bind(this), false); - - // Enable Key up and down Event - this._keydownEnabled = true; - this._keyupEnabled = true; - - this.DOMEventListeners[ORYX.CONFIG.EVENT_MOUSEDOWN] = []; - this.DOMEventListeners[ORYX.CONFIG.EVENT_MOUSEUP] = []; - this.DOMEventListeners[ORYX.CONFIG.EVENT_MOUSEOVER] = []; - this.DOMEventListeners[ORYX.CONFIG.EVENT_MOUSEOUT] = []; - this.DOMEventListeners[ORYX.CONFIG.EVENT_SELECTION_CHANGED] = []; - this.DOMEventListeners[ORYX.CONFIG.EVENT_MOUSEMOVE] = []; - - }, - - /** - * Generate the whole viewport of the - * Editor and initialized the Ext-Framework - * - */ - _generateGUI: function() { - - // Defines the layout height if it's NOT fullscreen - var layoutHeight = ORYX.CONFIG.WINDOW_HEIGHT; - var canvasParent = this.getCanvas().rootNode.parentNode; - - jQuery("#canvasSection").append(canvasParent); - - // Set the editor to the center, and refresh the size - canvasParent.parentNode.setAttributeNS(null, 'align', 'center'); - canvasParent.setAttributeNS(null, 'align', 'left'); - this.getCanvas().setSize({ - width : ORYX.CONFIG.CANVAS_WIDTH, - height : ORYX.CONFIG.CANVAS_HEIGHT - }); - - }, - - getAvailablePlugins: function(){ - var curAvailablePlugins=ORYX.availablePlugins.clone(); - curAvailablePlugins.each(function(plugin){ - if(this.loadedPlugins.find(function(loadedPlugin){ - return loadedPlugin.type==this.name; - }.bind(plugin))){ - plugin.engaged=true; - }else{ - plugin.engaged=false; - } - }.bind(this)); - return curAvailablePlugins; - }, + /** + * Returns the height of the label + * @return {number} + */ + getHeight: function () { + try { + return this.node.getBBox().height; + } catch (e) { + return 0; + } + }, - loadScript: function (url, callback){ - var script = document.createElement("script") - script.type = "text/javascript"; - if (script.readyState){ //IE - script.onreadystatechange = function(){ - if (script.readyState == "loaded" || script.readyState == "complete"){ - script.onreadystatechange = null; - callback(); - } - }; - } else { //Others - script.onload = function(){ - callback(); - }; - } - script.src = url; - document.getElementsByTagName("head")[0].appendChild(script); - }, - /** - * activate Plugin - * - * @param {String} name - * @param {Function} callback - * callback(sucess, [errorCode]) - * errorCodes: NOTUSEINSTENCILSET, REQUIRESTENCILSET, NOTFOUND, YETACTIVATED - */ - 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 there is an GUI-Plugin, they get all Plugins-Offer-Meta-Data - if (newPlugin.registryChanged) - newPlugin.registryChanged(me.pluginsData); - - // If there have an onSelection-Method it will pushed to the Editor Event-Handler - 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"); - //TODO error handling - } - }, + /** + * Returns the relative center position of the label + * to its parent shape. + * @return {Object} + */ + getCenter: function () { + var up = {x: this.getX(), y: this.getY()}; + up.x += this.getWidth() / 2; + up.y += this.getHeight() / 2; + return up; + }, - /** - * Laden der Plugins - */ - loadPlugins: function() { - - // if there should be plugins but still are none, try again. - // TODO this should wait for every plugin respectively. - /*if (!ORYX.Plugins && ORYX.availablePlugins.length > 0) { - window.setTimeout(this.loadPlugins.bind(this), 100); - return; - }*/ - - var me = this; - var newPlugins = []; - - - var loadedStencilSetsNamespaces = this.getStencilSets().keys(); - - // Available Plugins will be initalize - var facade = this._getPluginFacade(); - - // If there is an Array where all plugins are described, than only take those - // (that comes from the usage of oryx with a mashup api) - if( ORYX.MashupAPI && ORYX.MashupAPI.loadablePlugins && ORYX.MashupAPI.loadablePlugins instanceof Array ){ - - // Get the plugins from the available plugins (those who are in the plugins.xml) - ORYX.availablePlugins = $A(ORYX.availablePlugins).findAll(function(value){ - return ORYX.MashupAPI.loadablePlugins.include( value.name ) - }) - - // Add those plugins to the list, which are only in the loadablePlugins list - ORYX.MashupAPI.loadablePlugins.each(function( className ){ - if( !(ORYX.availablePlugins.find(function(val){ return val.name == className }))){ - ORYX.availablePlugins.push( {name: className } ); - } - }) - } - - - ORYX.availablePlugins.each(function(value) { - ORYX.Log.debug("Initializing plugin '%0'", value.name); - if( (!value.requires || !value.requires.namespaces || value.requires.namespaces.any(function(req){ return loadedStencilSetsNamespaces.indexOf(req) >= 0 }) ) && - (!value.notUsesIn || !value.notUsesIn.namespaces || !value.notUsesIn.namespaces.any(function(req){ return loadedStencilSetsNamespaces.indexOf(req) >= 0 }) )&& - /*only load activated plugins or undefined */ - (value.engaged || (value.engaged===undefined)) ){ - - try { - var className = eval(value.name); - if( className ){ - var plugin = new className(facade, value); - plugin.type = value.name; - newPlugins.push( plugin ); - plugin.engaged=true; - } - } catch(e) { - ORYX.Log.warn("Plugin %0 is not available %1", value.name, e); - } - - } else { - ORYX.Log.info("Plugin need a stencilset which is not loaded'", value.name); - } - - }); + /** + * Sets the position of a label relative to the parent. + * @param {Object} position + */ + setPosition: function (position) { + if (!position || position.x === undefined || position.y === undefined) { + delete this.position; + } else { + this.position = position; + } - newPlugins.each(function(value) { - // If there is an GUI-Plugin, they get all Plugins-Offer-Meta-Data - if(value.registryChanged) - value.registryChanged(me.pluginsData); + if (this.position) { + delete this._referencePoint; + delete this.edgePosition; + } - // If there have an onSelection-Method it will pushed to the Editor Event-Handler - if(value.onSelectionChanged) - me.registerOnEvent(ORYX.CONFIG.EVENT_SELECTION_CHANGED, value.onSelectionChanged.bind(value)); - }); + this._isChanged = true; + this.update(); + }, - this.loadedPlugins = newPlugins; - - this.registerPluginsOnKeyEvents(); - - this.setSelection(); - - }, + /** + * Return the position + */ + getPosition: function () { + return this.position; + }, - /** - * Creates the Canvas - * @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. - * @param {Object} [canvasConfig] Any canvas properties (like language). - */ - _createCanvas: function(stencilType, canvasConfig) { - if (stencilType) { - // Add namespace to stencilType - if (stencilType.search(/^http/) === -1) { - stencilType = this.getStencilSets().values()[0].namespace() + stencilType; - } - } - else { - // Get any root stencil type - stencilType = this.getStencilSets().values()[0].findRootStencilName(); + setReferencePoint: function (ref) { + if (ref) { + this._referencePoint = ref; + } else { + delete this._referencePoint; } - - // get the stencil associated with the type - var canvasStencil = ORYX.Core.StencilSet.stencil(stencilType); - - if (!canvasStencil) - ORYX.Log.fatal("Initialisation failed, because the stencil with the type %0 is not part of one of the loaded stencil sets.", stencilType); - - // create all dom - // TODO fix border, so the visible canvas has a double border and some spacing to the scrollbars - var div = ORYX.Editor.graft("http://www.w3.org/1999/xhtml", null, ['div']); - // set class for custom styling - div.addClassName("ORYX_Editor"); - - // create the canvas - 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 : div - }, canvasStencil, this._getPluginFacade()); - - if (canvasConfig) { - // Migrate canvasConfig to an RDF-like structure - //FIXME this isn't nice at all because we don't want rdf any longer - var properties = []; - for(field in canvasConfig){ - properties.push({ - prefix: 'oryx', - name: field, - value: canvasConfig[field] - }); - } - - this._canvas.deserialize(properties); + if (this._referencePoint) { + delete this.position; } - - }, - - /** - * Returns a per-editor singleton plugin facade. - * To be used in plugin initialization. - */ - _getPluginFacade: function() { - - // if there is no pluginfacade already created: - if(!(this._pluginFacade)) - - // create it. - this._pluginFacade = { - - activatePluginByName: this.activatePluginByName.bind(this), - //deactivatePluginByName: this.deactivatePluginByName.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 it. - return this._pluginFacade; - }, + }, - isExecutingCommands: function(){ - return !!this.commandExecuting; - }, + getReferencePoint: function () { + return this._referencePoint || undefined; + }, - /** - * Implementes the command pattern - * (The real usage of the command pattern - * is implemented and shown in the Plugins/undo.js) - * - * @param [] Array of commands - */ - executeCommands: function(commands){ - - if (!this.commandStack){ - this.commandStack = []; - } - if (!this.commandStackExecuted){ - this.commandStackExecuted = []; - } - - - this.commandStack = [].concat(this.commandStack) - .concat(commands); - - // Check if already executes - if (this.commandExecuting){ return; } - - // Start execution - this.commandExecuting = true; - - // Iterate over all commands - while(this.commandStack.length > 0){ - var command = this.commandStack.shift(); - // and execute it - command.execute(); - this.commandStackExecuted.push(command); - } - - // Raise event for executing commands - this.handleEvents({ - type : ORYX.CONFIG.EVENT_EXECUTE_COMMANDS, - commands : this.commandStackExecuted - }); - - // Remove temporary vars - delete this.commandStack; - delete this.commandStackExecuted; - delete this.commandExecuting; - - - this.updateSelection(); + changed: function () { + this._isChanged = true; + }, - }, - /** - * Returns JSON of underlying canvas (calls ORYX.Canvas#toJSON()). - * @return {Object} Returns JSON representation as JSON object. + * Register a callback which will be called if the label + * was rendered. + * @param {Object} fn */ - getJSON: function(){ - delete Array.prototype.toJSON; - var canvasJSON = this.getCanvas().toJSON(); - canvasJSON.ssextensions = this.getStencilSets().values()[0].extensions().keys().findAll(function(sse){ return !sse.endsWith('/meta#') }); - return canvasJSON; + registerOnChange: function (fn) { + if (!this.changeCallbacks) { + this.changeCallbacks = []; + } + if (fn instanceof Function && !this.changeCallbacks.include(fn)) { + this.changeCallbacks.push(fn); + } }, - + /** - * Serializes a call to toJSON(). - * @return {String} Returns JSON representation as string. + * Unregister the callback for changes. + * @param {Object} fn */ - getSerializedJSON: function(){ - return JSON.stringify(this.getJSON()); + unregisterOnChange: function (fn) { + if (this.changeCallbacks && fn instanceof Function && this.changeCallbacks.include(fn)) { + this.changeCallbacks = this.changeCallbacks.without(fn); + } }, - - /** - * Imports shapes in JSON as expected by {@link ORYX.Editor#loadSerialized} - * @param {Object|String} jsonObject The (serialized) json object to be imported - * @param {boolean } [noSelectionAfterImport=false] Set to true if no shapes should be selected after import - * @throws {SyntaxError} If the serialized json object contains syntax errors - */ - importJSON: function(jsonObject, noSelectionAfterImport) { - - try { - jsonObject = this.renewResourceIds(jsonObject); - } catch(error){ - throw error; - } - //check, if the imported json model can be loaded in this editor - // (stencil set has to fit) - if(jsonObject.stencilset.namespace && jsonObject.stencilset.namespace !== this.getCanvas().getStencil().stencilSet().namespace()) { - alert(String.format(ORYX.I18N.JSONImport.wrongSS, jsonObject.stencilset.namespace, this.getCanvas().getStencil().stencilSet().namespace())); - return null; - } else { - var commandClass = ORYX.Core.Command.extend({ - construct: function(jsonObject, loadSerializedCB, noSelectionAfterImport, facade){ - this.jsonObject = jsonObject; - this.noSelection = noSelectionAfterImport; - this.facade = facade; - this.shapes; - this.connections = []; - this.parents = new Hash(); - this.selection = this.facade.getSelection(); - this.loadSerialized = loadSerializedCB; - }, - execute: function(){ - - if (!this.shapes) { - // Import the shapes out of the serialization - this.shapes = this.loadSerialized( this.jsonObject ); - - //store all connections - this.shapes.each(function(shape) { - - if (shape.getDockers) { - var dockers = shape.getDockers(); - if (dockers) { - if (dockers.length > 0) { - this.connections.push([dockers.first(), dockers.first().getDockedShape(), dockers.first().referencePoint]); - } - if (dockers.length > 1) { - this.connections.push([dockers.last(), dockers.last().getDockedShape(), dockers.last().referencePoint]); - } - } - } - - //store parents - this.parents[shape.id] = shape.parent; - }.bind(this)); - } else { - this.shapes.each(function(shape) { - this.parents[shape.id].add(shape); - }.bind(this)); - - this.connections.each(function(con) { - con[0].setDockedShape(con[1]); - con[0].setReferencePoint(con[2]); - con[0].update(); - }); - } - - //this.parents.values().uniq().invoke("update"); - this.facade.getCanvas().update(); - - if(!this.noSelection) - this.facade.setSelection(this.shapes); - else - this.facade.updateSelection(); - - // call updateSize again, because during loadSerialized the edges' bounds - // are not yet initialized properly - this.facade.getCanvas().updateSize(); - - }, - rollback: function(){ - var selection = this.facade.getSelection(); - - this.shapes.each(function(shape) { - selection = selection.without(shape); - this.facade.deleteShape(shape); - }.bind(this)); - - /*this.parents.values().uniq().each(function(parent) { - if(!this.shapes.member(parent)) - parent.update(); - }.bind(this));*/ - - this.facade.getCanvas().update(); - - this.facade.setSelection(selection); - } - }) - - var command = new commandClass(jsonObject, - this.loadSerialized.bind(this), - noSelectionAfterImport, - this._getPluginFacade()); - - this.executeCommands([command]); - - return command.shapes.clone(); - } - }, - + /** - * This method renew all resource Ids and according references. - * Warning: The implementation performs a substitution on the serialized object for - * easier implementation. This results in a low performance which is acceptable if this - * is only used when importing models. - * @param {Object|String} jsonObject - * @throws {SyntaxError} If the serialized json object contains syntax errors. - * @return {Object} The jsonObject with renewed ids. - * @private + * Returns TRUE if the labe is currently in + * the update mechanism. + * @return {Boolean} */ - renewResourceIds: function(jsonObject){ - // For renewing resource ids, a serialized and object version is needed - if(Object.prototype.toString.call(jsonObject) === "String"){ - try { - var serJsonObject = jsonObject; - jsonObject = JSON.parse(jsonObject); - } catch(error){ - throw new SyntaxError(error.message); - } - } else { - var serJsonObject = JSON.stringify(jsonObject); - } - - // collect all resourceIds recursively - var collectResourceIds = function(shapes){ - if(!shapes) return []; - - return shapes.map(function(shape){ - return collectResourceIds(shape.childShapes).concat(shape.resourceId); - }).flatten(); - } - var resourceIds = collectResourceIds(jsonObject.childShapes); - - // Replace each resource id by a new one - resourceIds.each(function(oldResourceId){ - var newResourceId = ORYX.Editor.provideId(); - serJsonObject = serJsonObject.replace(new RegExp(oldResourceId, 'g'), newResourceId); - }); - - return JSON.parse(serJsonObject); + isUpdating: function () { + return !!this._isUpdating; + }, + + + getOriginEdgePosition: function () { + return this.originEdgePosition; }, /** - * Loads serialized model to the oryx. - * @example - * editor.loadSerialized({ - * resourceId: "mymodel1", - * childShapes: [ - * { - * stencil:{ id:"Subprocess" }, - * outgoing:[{resourceId: 'aShape'}], - * target: {resourceId: 'aShape'}, - * bounds:{ lowerRight:{ y:510, x:633 }, upperLeft:{ y:146, x:210 } }, - * resourceId: "myshape1", - * childShapes:[], - * properties:{}, - * } - * ], - * properties:{ - * language: "English" - * }, - * stencilset:{ - * url:"http://localhost:8080/oryx/stencilsets/bpmn1.1/bpmn1.1.json" - * }, - * stencil:{ - * id:"BPMNDiagram" - * } - * }); - * @param {Object} model Description of the model to load. - * @param {Array} [model.ssextensions] List of stenctil set extensions. - * @param {String} model.stencilset.url - * @param {String} model.stencil.id - * @param {Array} model.childShapes - * @param {Array} [model.properties] - * @param {String} model.resourceId - * @return {ORYX.Core.Shape[]} List of created shapes - * @methodOf ORYX.Editor.prototype + * Returns the edgeposition. + * + * @return {String} "starttop", "startmiddle", "startbottom", + * "midtop", "midbottom", "endtop", "endbottom" or null */ - loadSerialized: function(model, requestMeta){ - var canvas = this.getCanvas(); - - // Bugfix (cf. http://code.google.com/p/oryx-editor/issues/detail?id=240) - // Deserialize the canvas' stencil set extensions properties first! - this.loadSSExtensions(model.ssextensions); - - // Load Meta Data Extension if available - // #Signavio - if (requestMeta === true) { - var metaDataExtension = this.getExtensionForMetaData(); - if (metaDataExtension) { - this.loadSSExtension(metaDataExtension); - } - } - - var shapes = this.getCanvas().addShapeObjects(model.childShapes, this.handleEvents.bind(this)); - - if(model.properties) { - for(key in model.properties) { - var value = model.properties[key]; - var prop = this.getCanvas().getStencil().property("oryx-"+key); - if (!(typeof value === "string") && (!prop || !prop.isList())) { - value = JSON.stringify(value); - } - this.getCanvas().setProperty("oryx-" + key, value); - } - } - - - this.getCanvas().updateSize(); - - // Force to update the selection - this.selection = [null]; - this.setSelection([]); - - return shapes; + getEdgePosition: function () { + return this.edgePosition || null; }, - - /** - * Return the namespace of the extension which - * provided all the self defined meta data - * @return {String} Returns null if no extension is defined, otherwise the namespace - * - */ - getExtensionForMetaData: function(){ - if (!this.ss_extensions_def||!(this.ss_extensions_def.extensions instanceof Array)){ - return null; - } - - var stencilsets = this.getStencilSets(); - var extension = this.ss_extensions_def.extensions.find(function(ex){ - return !!stencilsets[ex["extends"]] && ex.namespace.endsWith("/meta#"); - }); - - return extension ? extension.namespace || null : null; - }, - + /** - * Calls ORYX.Editor.prototype.ss_extension_namespace for each element - * @param {Array} ss_extension_namespaces An array of stencil set extension namespaces. + * Set the edge position, must be one of the valid + * edge positions (see getEdgePosition). + * Removes the reference point and the absolute position as well. + * + * @param {Object} position */ - loadSSExtensions: function(ss_extension_namespaces){ - if(!ss_extension_namespaces) return; - - ss_extension_namespaces.each(function(ss_extension_namespace){ - this.loadSSExtension(ss_extension_namespace); - }.bind(this)); + setEdgePosition: function (position) { + if (["starttop", "startmiddle", "startbottom", + "midtop", "midbottom", "endtop", "endbottom"].include(position)) { + this.edgePosition = position; + delete this.position; + delete this._referencePoint; + } else { + delete this.edgePosition; + } }, - - /** - * Loads a stencil set extension. - * The stencil set extensions definiton file must already - * be loaded when the editor is initialized. - */ - loadSSExtension: function(ss_extension_namespace) { - - if (this.ss_extensions_def) { - var extension = this.ss_extensions_def.extensions.find(function(ex){ - return (ex.namespace == ss_extension_namespace); - }); - - if (!extension) { - return; - } - - var stencilset = this.getStencilSets()[extension["extends"]]; - - if (!stencilset) { - return; - } - - // Check if absolute or relative url - if ((extension["definition"]||"").startsWith("/")){ - stencilset.addExtension(extension["definition"]) - } else { - stencilset.addExtension(ORYX.CONFIG.SS_EXTENSIONS_FOLDER + extension["definition"]) - } - - //stencilset.addExtension("/oryx/build/stencilsets/extensions/" + extension["definition"]) - this.getRules().initializeRules(stencilset); - - this._getPluginFacade().raiseEvent({ - type: ORYX.CONFIG.EVENT_STENCIL_SET_LOADED - }); - } - - }, - - disableEvent: function(eventType){ - if(eventType == ORYX.CONFIG.EVENT_KEYDOWN) { - this._keydownEnabled = false; - } - if(eventType == ORYX.CONFIG.EVENT_KEYUP) { - this._keyupEnabled = false; - } - if(this.DOMEventListeners.keys().member(eventType)) { - var value = this.DOMEventListeners.remove(eventType); - this.DOMEventListeners['disable_' + eventType] = value; - } - }, - enableEvent: function(eventType){ - if(eventType == ORYX.CONFIG.EVENT_KEYDOWN) { - this._keydownEnabled = true; - } - - if(eventType == ORYX.CONFIG.EVENT_KEYUP) { - this._keyupEnabled = true; - } - - if(this.DOMEventListeners.keys().member("disable_" + eventType)) { - var value = this.DOMEventListeners.remove("disable_" + eventType); - this.DOMEventListeners[eventType] = value; - } - }, + /** + * Update the SVG text element. + */ + update: function (force) { - /** - * Methods for the PluginFacade - */ - registerOnEvent: function(eventType, callback) { - if(!(this.DOMEventListeners.keys().member(eventType))) { - this.DOMEventListeners[eventType] = []; - } + var x = this.x, y = this.y; + if (this.position) { + x = this.position.x; + y = this.position.y; + } + x = Math.floor(x); + y = Math.floor(y); + + if (this._isChanged || x !== this.oldX || y !== this.oldY || force === true) { + if (this.isVisible) { + this._isChanged = false; + this._isUpdating = true; + + this.node.setAttributeNS(null, 'x', x); + this.node.setAttributeNS(null, 'y', y); + this.node.removeAttributeNS(null, "fill-opacity"); + + //this.node.setAttributeNS(null, 'font-size', this._fontSize); + //this.node.setAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'align', this._horizontalAlign + " " + this._verticalAlign); + + this.oldX = x; + this.oldY = y; + + //set rotation + 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(x) + ' ' + Math.floor(y) + ')'); + } + } else { + this.node.removeAttributeNS(null, 'transform'); + } - this.DOMEventListeners[eventType].push(callback); - }, + var textLines = this._text.split("\n"); + while (textLines.last() == "") + textLines.pop(); + + + if (this.node.ownerDocument) { + // Only reset the tspans if the text + // has changed or has to be wrapped + if (this.fitToElemId || this._textHasChanged) { + this.node.textContent = ""; // Remove content + textLines.each((function (textLine, index) { + var tspan = this.node.ownerDocument.createElementNS(ORYX.CONFIG.NAMESPACE_SVG, 'tspan'); + tspan.textContent = textLine.trim(); + if (this.fitToElemId) { + tspan.setAttributeNS(null, 'x', this.invisibleRenderPoint); + tspan.setAttributeNS(null, 'y', this.invisibleRenderPoint); + } - unregisterOnEvent: function(eventType, callback) { - if(this.DOMEventListeners.keys().member(eventType)) { - this.DOMEventListeners[eventType] = this.DOMEventListeners[eventType].without(callback); - } else { - // Event is not supported - // TODO: Error Handling - } - }, + /* + * Chrome's getBBox() method fails, if a text node contains an empty tspan element. + * So, we add a whitespace to such a tspan element. + */ + if (tspan.textContent === "") { + tspan.textContent = " "; + } - getSelection: function() { - return this.selection || []; - }, + //append tspan to text node + this.node.appendChild(tspan); + }).bind(this)); + delete this._textHasChanged; + delete this.indices; + } - getStencilSets: function() { - return ORYX.Core.StencilSet.stencilSets(this.id); - }, - - getRules: function() { - return ORYX.Core.StencilSet.rules(this.id); - }, - - loadStencilSet: function(source) { - try { - ORYX.Core.StencilSet.loadStencilSet(source, this.modelMetaData, this.id); - this.handleEvents({type:ORYX.CONFIG.EVENT_STENCIL_SET_LOADED}); - } catch (e) { - ORYX.Log.warn("Requesting stencil set file failed. (" + e + ")"); - } - }, + //Work around for Mozilla bug 293581 + if (this.isVisible && this.fitToElemId) { + this.node.setAttributeNS(null, 'visibility', 'hidden'); + } - offer: function(pluginData) { - if(!this.pluginsData.member(pluginData)){ - this.pluginsData.push(pluginData); - } - }, - - /** - * It creates an new event or adds the callback, if already existing, - * for the key combination that the plugin passes in keyCodes attribute - * of the offer method. - * - * The new key down event fits the schema: - * key.event[.metactrl][.alt][.shift].'thekeyCode' - */ - registerPluginsOnKeyEvents: function() { - this.pluginsData.each(function(pluginData) { - - if(pluginData.keyCodes) { - - pluginData.keyCodes.each(function(keyComb) { - var eventName = "key.event"; - - /* Include key action */ - eventName += '.' + keyComb.keyAction; - - if(keyComb.metaKeys) { - /* Register on ctrl or apple meta key as meta key */ - if(keyComb.metaKeys. - indexOf(ORYX.CONFIG.META_KEY_META_CTRL) > -1) { - eventName += "." + ORYX.CONFIG.META_KEY_META_CTRL; - } - - /* Register on alt key as meta key */ - if(keyComb.metaKeys. - indexOf(ORYX.CONFIG.META_KEY_ALT) > -1) { - eventName += '.' + ORYX.CONFIG.META_KEY_ALT; - } - - /* Register on shift key as meta key */ - if(keyComb.metaKeys. - indexOf(ORYX.CONFIG.META_KEY_SHIFT) > -1) { - eventName += '.' + ORYX.CONFIG.META_KEY_SHIFT; - } - } - - /* Register on the actual key */ - if(keyComb.keyCode) { - eventName += '.' + keyComb.keyCode; - } - - /* Register the event */ - ORYX.Log.debug("Register Plugin on Key Event: %0", eventName); - if (pluginData.toggle === true && pluginData.buttonInstance) { - this.registerOnEvent(eventName, function(){ - pluginData.buttonInstance.toggle(!pluginData.buttonInstance.pressed); // Toggle - pluginData.functionality.call(pluginData, pluginData.buttonInstance, pluginData.buttonInstance.pressed); // Call function - }); - } else { - this.registerOnEvent(eventName, pluginData.functionality) - } - - }.bind(this)); - } - }.bind(this)); - }, - - isEqual: function(a,b){ - return a === b || (a.length === b.length && a.all(function(r){ return b.include(r) })) - }, - - isDirty: function(a){ - return a.any(function(shape){ return shape.isPropertyChanged() }) - }, + if (this.fitToElemId) { + window.setTimeout(this._checkFittingToReferencedElem.bind(this), 0); + //this._checkFittingToReferencedElem(); + } else { + window.setTimeout(this._positionText.bind(this), 0); + //this._positionText(); + } + } + } else { + this.node.textContent = ""; + //this.node.setAttributeNS(null, "fill-opacity", "0.2"); + } + } + }, - setSelection: function(elements, subSelectionElement, force) { - - if (!elements) { elements = []; } - if (!(elements instanceof Array)) { elements = [elements]; } - - elements = elements.findAll(function(n){ return n && n instanceof ORYX.Core.Shape }); - - if (elements[0] instanceof ORYX.Core.Canvas) { - elements = []; - } - - if (!force && this.isEqual(this.selection, elements) && !this.isDirty(elements)){ - return; - } - - this.selection = elements; - this._subSelection = subSelectionElement; - - this.handleEvents({type:ORYX.CONFIG.EVENT_SELECTION_CHANGED, elements:elements, subSelection: subSelectionElement, force: !!force}) - }, - - updateSelection: function() { - this.setSelection(this.selection, this._subSelection, true); - /*var s = this.selection; - this.setSelection(); - this.setSelection(s);*/ - }, + _checkFittingToReferencedElem: function () { + try { + var tspans = $A(this.node.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'tspan')); - getCanvas: function() { - return this._canvas; - }, - - - /** - * option = { - * type: string, - * position: {x:int, y:int}, - * connectingType: uiObj-Class - * connectedShape: uiObj - * draggin: bool - * namespace: url - * parent: ORYX.Core.AbstractShape - * template: a template shape that the newly created inherits properties from. - * } - */ - createShape: function(option) { - - if(option && option.serialize && option.serialize instanceof Array){ - - var type = option.serialize.find(function(obj){return (obj.prefix+"-"+obj.name) == "oryx-type"}); - var stencil = ORYX.Core.StencilSet.stencil(type.value); - - if(stencil.type() == 'node'){ - var newShapeObject = new ORYX.Core.Node({'eventHandlerCallback':this.handleEvents.bind(this)}, stencil, this._getPluginFacade()); - } else { - var newShapeObject = new ORYX.Core.Edge({'eventHandlerCallback':this.handleEvents.bind(this)}, stencil, this._getPluginFacade()); - } - - this.getCanvas().add(newShapeObject); - newShapeObject.deserialize(option.serialize); - - return newShapeObject; - } + //only do this in firefox 3. all other browsers do not support word wrapping!!!!! + //if (/Firefox[\/\s](\d+\.\d+)/.test(navigator.userAgent) && new Number(RegExp.$1)>=3) { + var newtspans = []; - // If there is no argument, throw an exception - if(!option || !option.type || !option.namespace) { throw "To create a new shape you have to give an argument with type and namespace";} - - var canvas = this.getCanvas(); - var newShapeObject; + var refNode = this.node.ownerDocument.getElementById(this.fitToElemId); - // Get the shape type - var shapetype = option.type; + if (refNode) { + var refbb = refNode.getBBox(); - // Get the stencil set - var sset = ORYX.Core.StencilSet.stencilSet(option.namespace); - // Create an New Shape, dependents on an Edge or a Node - if(sset.stencil(shapetype).type() == "node") { - newShapeObject = new ORYX.Core.Node({'eventHandlerCallback':this.handleEvents.bind(this)}, sset.stencil(shapetype), this._getPluginFacade()) - } else { - newShapeObject = new ORYX.Core.Edge({'eventHandlerCallback':this.handleEvents.bind(this)}, sset.stencil(shapetype), this._getPluginFacade()) - } - - // when there is a template, inherit the properties. - if(option.template) { + var fontSize = this.getFontSize(); - newShapeObject._jsonStencil.properties = option.template._jsonStencil.properties; - newShapeObject.postProcessProperties(); - } + for (var j = 0; j < tspans.length; j++) { + var tspan = tspans[j]; - // Add to the canvas - if(option.parent && newShapeObject instanceof ORYX.Core.Node) { - option.parent.add(newShapeObject); - } else { - canvas.add(newShapeObject); - } - - - // Set the position - var point = option.position ? option.position : {x:100, y:200}; - - - var con; - // If there is create a shape and in the argument there is given an ConnectingType and is instance of an edge - if(option.connectingType && option.connectedShape && !(newShapeObject instanceof ORYX.Core.Edge)) { - - // there will be create a new Edge - con = new ORYX.Core.Edge({'eventHandlerCallback':this.handleEvents.bind(this)}, sset.stencil(option.connectingType)); - - // And both endings dockers will be referenced to the both shapes - con.dockers.first().setDockedShape(option.connectedShape); - - var magnet = option.connectedShape.getDefaultMagnet() - var cPoint = magnet ? magnet.bounds.center() : option.connectedShape.bounds.midPoint(); - con.dockers.first().setReferencePoint( cPoint ); - con.dockers.last().setDockedShape(newShapeObject); - con.dockers.last().setReferencePoint(newShapeObject.getDefaultMagnet().bounds.center()); - - // The Edge will be added to the canvas and be updated - canvas.add(con); - //con.update(); - - } - - // Move the new Shape to the position - if(newShapeObject instanceof ORYX.Core.Edge && option.connectedShape) { - - newShapeObject.dockers.first().setDockedShape(option.connectedShape); - - if( option.connectedShape instanceof ORYX.Core.Node ){ - newShapeObject.dockers.first().setReferencePoint(option.connectedShape.getDefaultMagnet().bounds.center()); - newShapeObject.dockers.last().bounds.centerMoveTo(point); - } else { - newShapeObject.dockers.first().setReferencePoint(option.connectedShape.bounds.midPoint()); - } - - var start = newShapeObject.dockers.first(); - var end = newShapeObject.dockers.last(); - - if(start.getDockedShape() && end.getDockedShape()) { - var startPoint = start.getAbsoluteReferencePoint(); - var endPoint = end.getAbsoluteReferencePoint(); - - var docker = newShapeObject.createDocker(); - docker.bounds.centerMoveTo({ - x: startPoint.x + (endPont.x - startPoint.x) / 2, - y: startPoint.y + (endPont.y - startPoint.y) / 2 - }); - } + var textLength = this._getRenderedTextLength(tspan, undefined, undefined, fontSize); - } else { - - var b = newShapeObject.bounds - if( newShapeObject instanceof ORYX.Core.Node && newShapeObject.dockers.length == 1){ - b = newShapeObject.dockers.first().bounds - } - - b.centerMoveTo(point); - - var upL = b.upperLeft(); - b.moveBy( -Math.min(upL.x, 0) , -Math.min(upL.y, 0) ) - - var lwR = b.lowerRight(); - b.moveBy( -Math.max(lwR.x-canvas.bounds.width(), 0) , -Math.max(lwR.y-canvas.bounds.height(), 0) ) - - } - - // Update the shape - if (newShapeObject instanceof ORYX.Core.Edge) { - newShapeObject._update(false); - } - - // And refresh the selection - if(!(newShapeObject instanceof ORYX.Core.Edge)&&!(option.dontUpdateSelection)) { - this.setSelection([newShapeObject]); - } - - if(con && con.alignDockers) { - //con.alignDockers(); - } - if(newShapeObject.alignDockers) { - newShapeObject.alignDockers(); - } + var refBoxLength = (this._rotate != 0 + && this._rotate % 180 != 0 + && this._rotate % 90 == 0 ? + refbb.height : refbb.width); - return newShapeObject; - }, - - deleteShape: function(shape) { - - if (!shape || !shape.parent){ return } - - //remove shape from parent - // this also removes it from DOM - shape.parent.remove(shape); - - //delete references to outgoing edges - shape.getOutgoingShapes().each(function(os) { - var docker = os.getDockers().first(); - if(docker && docker.getDockedShape() == shape) { - docker.setDockedShape(undefined); - } - }); - - //delete references to incoming edges - shape.getIncomingShapes().each(function(is) { - var docker = is.getDockers().last(); - if(docker && docker.getDockedShape() == shape) { - docker.setDockedShape(undefined); - } - }); - - //delete references of the shape's dockers - shape.getDockers().each(function(docker) { - docker.setDockedShape(undefined); - }); - }, - - /** - * Returns an object with meta data about the model. - * Like name, description, ... - * - * Empty object with the current backend. - * - * @return {Object} Meta data about the model - */ - getModelMetaData: function() { - return this.modelMetaData; - }, + if (textLength > refBoxLength) { - /* Event-Handler Methods */ - - /** - * Helper method to execute an event immediately. The event is not - * scheduled in the _eventsQueue. Needed to handle Layout-Callbacks. - */ - _executeEventImmediately: function(eventObj) { - if(this.DOMEventListeners.keys().member(eventObj.event.type)) { - this.DOMEventListeners[eventObj.event.type].each((function(value) { - value(eventObj.event, eventObj.arg); - }).bind(this)); - } - }, + var startIndex = 0; + var lastSeperatorIndex = 0; - _executeEvents: function() { - this._queueRunning = true; - while(this._eventsQueue.length > 0) { - var val = this._eventsQueue.shift(); - this._executeEventImmediately(val); - } - this._queueRunning = false; - }, - - /** - * Leitet die Events an die Editor-Spezifischen Event-Methoden weiter - * @param {Object} event Event , welches gefeuert wurde - * @param {Object} uiObj Target-UiObj - */ - handleEvents: function(event, uiObj) { - - ORYX.Log.trace("Dispatching event type %0 on %1", event.type, uiObj); - - switch(event.type) { - case ORYX.CONFIG.EVENT_MOUSEDOWN: - this._handleMouseDown(event, uiObj); - break; - case ORYX.CONFIG.EVENT_MOUSEMOVE: - this._handleMouseMove(event, uiObj); - break; - case ORYX.CONFIG.EVENT_MOUSEUP: - this._handleMouseUp(event, uiObj); - break; - case ORYX.CONFIG.EVENT_MOUSEOVER: - this._handleMouseHover(event, uiObj); - break; - case ORYX.CONFIG.EVENT_MOUSEOUT: - this._handleMouseOut(event, uiObj); - break; - } - /* Force execution if necessary. Used while handle Layout-Callbacks. */ - if(event.forceExecution) { - this._executeEventImmediately({event: event, arg: uiObj}); - } else { - this._eventsQueue.push({event: event, arg: uiObj}); - } - - if(!this._queueRunning) { - this._executeEvents(); - } - - // TODO: Make this return whether no listener returned false. - // So that, when one considers bubbling undesireable, it won't happen. - return false; - }, + var numOfChars = this.getTrimmedTextLength(tspan.textContent); + for (var i = 0; i < numOfChars; i++) { + var sslength = this._getRenderedTextLength(tspan, startIndex, i - startIndex, fontSize); - isValidEvent: function(e){ - try { - var isInput = ["INPUT", "TEXTAREA"].include(e.target.tagName.toUpperCase()); - var gridHasFocus = e.target.className.include("x-grid3-focus") && !e.target.className.include("x-grid3-focus-canvas"); - return !isInput && !gridHasFocus; - } catch(e){ - return false; - } - }, + if (sslength > refBoxLength - 2) { + var newtspan = this.node.ownerDocument.createElementNS(ORYX.CONFIG.NAMESPACE_SVG, 'tspan'); + if (lastSeperatorIndex <= startIndex) { + lastSeperatorIndex = (i == 0) ? i : i - 1; + newtspan.textContent = tspan.textContent.slice(startIndex, lastSeperatorIndex).trim(); + //lastSeperatorIndex = i; + } else { + newtspan.textContent = tspan.textContent.slice(startIndex, ++lastSeperatorIndex).trim(); + } - catchKeyUpEvents: function(event) { - if(!this._keyupEnabled) { - return; - } - /* assure we have the current event. */ - if (!event) - event = window.event; - - // Checks if the event comes from some input field - if (!this.isValidEvent(event)){ - return; - } - - /* Create key up event type */ - var keyUpEvent = this.createKeyCombEvent(event, ORYX.CONFIG.KEY_ACTION_UP); - - ORYX.Log.debug("Key Event to handle: %0", keyUpEvent); - - /* forward to dispatching. */ - this.handleEvents({type: keyUpEvent, event:event}); - }, - - /** - * Catches all key down events and forward the appropriated event to - * dispatching concerning to the pressed keys. - * - * @param {Event} - * The key down event to handle - */ - catchKeyDownEvents: function(event) { - if(!this._keydownEnabled) { - return; - } - /* Assure we have the current event. */ - if (!event) - event = window.event; - - /* Fixed in FF3 */ - // This is a mac-specific fix. The mozilla event object has no knowledge - // of meta key modifier on osx, however, it is needed for certain - // shortcuts. This fix adds the metaKey field to the event object, so - // that all listeners that registered per Oryx plugin facade profit from - // this. The original bug is filed in - // https://bugzilla.mozilla.org/show_bug.cgi?id=418334 - //if (this.__currentKey == ORYX.CONFIG.KEY_CODE_META) { - // event.appleMetaKey = true; - //} - //this.__currentKey = pressedKey; - - // Checks if the event comes from some input field - if (!this.isValidEvent(event)){ - return; - } - - /* Create key up event type */ - var keyDownEvent = this.createKeyCombEvent(event, ORYX.CONFIG.KEY_ACTION_DOWN); - - ORYX.Log.debug("Key Event to handle: %0", keyDownEvent); - - /* Forward to dispatching. */ - this.handleEvents({type: keyDownEvent,event: event}); - }, - - /** - * Creates the event type name concerning to the pressed keys. - * - * @param {Event} keyDownEvent - * The source keyDownEvent to build up the event name - */ - createKeyCombEvent: function(keyEvent, keyAction) { + newtspan.setAttributeNS(null, 'x', this.invisibleRenderPoint); + newtspan.setAttributeNS(null, 'y', this.invisibleRenderPoint); + + //insert tspan to text node + //this.node.insertBefore(newtspan, tspan); + newtspans.push(newtspan); + + startIndex = lastSeperatorIndex; + } else { + var curChar = tspan.textContent.charAt(i); + if (curChar == ' ' || + curChar == '-' || + curChar == "." || + curChar == "," || + curChar == ";" || + curChar == ":") { + lastSeperatorIndex = i; + } + } + } - /* Get the currently pressed key code. */ - var pressedKey = keyEvent.which || keyEvent.keyCode; - //this.__currentKey = pressedKey; - - /* Event name */ - var eventName = "key.event"; - - /* Key action */ - if(keyAction) { - eventName += "." + keyAction; - } - - /* Ctrl or apple meta key is pressed */ - if(keyEvent.ctrlKey || keyEvent.metaKey) { - eventName += "." + ORYX.CONFIG.META_KEY_META_CTRL; - } - - /* Alt key is pressed */ - if(keyEvent.altKey) { - eventName += "." + ORYX.CONFIG.META_KEY_ALT; - } - - /* Alt key is pressed */ - if(keyEvent.shiftKey) { - eventName += "." + ORYX.CONFIG.META_KEY_SHIFT; - } - - /* Return the composed event name */ - return eventName + "." + pressedKey; - }, + tspan.textContent = tspan.textContent.slice(startIndex).trim(); + } - _handleMouseDown: function(event, uiObj) { - - // get canvas. - var canvas = this.getCanvas(); - // Try to get the focus - canvas.focus() - - // find the shape that is responsible for this element's id. - var element = event.currentTarget; - var elementController = uiObj; + newtspans.push(tspan); + } - // gather information on selection. - var currentIsSelectable = (elementController !== null) && - (elementController !== undefined) && (elementController.isSelectable); - var currentIsMovable = (elementController !== null) && - (elementController !== undefined) && (elementController.isMovable); - var modifierKeyPressed = event.shiftKey || event.ctrlKey; - var noObjectsSelected = this.selection.length === 0; - var currentIsSelected = this.selection.member(elementController); + while (this.node.hasChildNodes()) + this.node.removeChild(this.node.childNodes[0]); + while (newtspans.length > 0) { + this.node.appendChild(newtspans.shift()); + } + } + //} + } catch (e) { + ORYX.Log.fatal("Error " + e); + } + window.setTimeout(this._positionText.bind(this), 0); + //this._positionText(); + }, - // Rule #1: When there is nothing selected, select the clicked object. - if(currentIsSelectable && noObjectsSelected) { + /** + * This is a work around method for Mozilla bug 293581. + * Before the method getComputedTextLength works, the text has to be rendered. + */ + _positionText: function () { + try { - this.setSelection([elementController]); + var tspans = this.node.childNodes; - ORYX.Log.trace("Rule #1 applied for mouse down on %0", element.id); + var fontSize = this.getFontSize(this.node); - // Rule #3: When at least one element is selected, and there is no - // control key pressed, and the clicked object is not selected, select - // the clicked object. - } else if(currentIsSelectable && !noObjectsSelected && - !modifierKeyPressed && !currentIsSelected) { + var invalidTSpans = []; - this.setSelection([elementController]); + var x = this.x, y = this.y; + if (this.position) { + x = this.position.x; + y = this.position.y; + } + x = Math.floor(x); + y = Math.floor(y); + + var i = 0, indic = []; // Cache indices if the _positionText is called again, before update is called + var is = (this.indices || $R(0, tspans.length - 1).toArray()); + var length = is.length; + is.each((function (index) { + if ("undefined" == typeof index) { + return; + } - //var objectType = elementController.readAttributes(); - //alert(objectType[0] + ": " + objectType[1]); + var tspan = tspans[i++]; - ORYX.Log.trace("Rule #3 applied for mouse down on %0", element.id); + if (tspan.textContent.trim() === "") { + invalidTSpans.push(tspan); + } else { + //set vertical position + var dy = 0; + switch (this._verticalAlign) { + case 'bottom': + dy = -(length - index - 1) * (fontSize); + break; + case 'middle': + dy = -(length / 2.0 - index - 1) * (fontSize); + dy -= ORYX.CONFIG.LABEL_LINE_DISTANCE / 2; + break; + case 'top': + dy = index * (fontSize); + dy += fontSize; + break; + } + tspan.setAttributeNS(null, 'dy', Math.floor(dy)); - // Rule #4: When the control key is pressed, and the current object is - // not selected, add it to the selection. - } else if(currentIsSelectable && modifierKeyPressed - && !currentIsSelected) { - - var newSelection = this.selection.clone(); - newSelection.push(elementController) - this.setSelection(newSelection) + tspan.setAttributeNS(null, 'x', x); + tspan.setAttributeNS(null, 'y', y); + indic.push(index); + } - ORYX.Log.trace("Rule #4 applied for mouse down on %0", element.id); + }).bind(this)); - // Rule #6 - } else if(currentIsSelectable && currentIsSelected && - modifierKeyPressed) { + indic.length = tspans.length; + this.indices = this.indices || indic; - var newSelection = this.selection.clone(); - this.setSelection(newSelection.without(elementController)) + invalidTSpans.each(function (tspan) { + this.node.removeChild(tspan) + }.bind(this)); - ORYX.Log.trace("Rule #6 applied for mouse down on %0", elementController.id); + //set horizontal alignment + 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; + } - // Rule #5: When there is at least one object selected and no control - // key pressed, we're dragging. - /*} else if(currentIsSelectable && !noObjectsSelected - && !modifierKeyPressed) { + } catch (e) { + //console.log(e); + this._isChanged = true; + } - if(this.log.isTraceEnabled()) - this.log.trace("Rule #5 applied for mouse down on "+element.id); -*/ - // Rule #2: When clicked on something that is neither - // selectable nor movable, clear the selection, and return. - } else if (!currentIsSelectable && !currentIsMovable) { - - this.setSelection([]); - - ORYX.Log.trace("Rule #2 applied for mouse down on %0", element.id); - return; + if (this.isVisible) { + this.node.removeAttributeNS(null, 'visibility'); + } - // Rule #7: When the current object is not selectable but movable, - // it is probably a control. Leave the selection unchanged but set - // the movedObject to the current one and enable Drag. Dockers will - // be processed in the dragDocker plugin. - } else if(!currentIsSelectable && currentIsMovable && !(elementController instanceof ORYX.Core.Controls.Docker)) { - - // TODO: If there is any moveable elements, do this in a plugin - //ORYX.Core.UIEnableDrag(event, elementController); - - ORYX.Log.trace("Rule #7 applied for mouse down on %0", element.id); - - // Rule #8: When the element is selectable and is currently selected and no - // modifier key is pressed - } else if(currentIsSelectable && currentIsSelected && - !modifierKeyPressed) { - - this._subSelection = this._subSelection != elementController ? elementController : undefined; - - this.setSelection(this.selection, this._subSelection); - - ORYX.Log.trace("Rule #8 applied for mouse down on %0", element.id); - } - - - // prevent event from bubbling, return. - //Event.stop(event); - return; - }, - _handleMouseMove: function(event, uiObj) { - return; - }, + // Finished + delete this._isUpdating; - _handleMouseUp: function(event, uiObj) { - // get canvas. - var canvas = this.getCanvas(); + // Raise change event + (this.changeCallbacks || []).each(function (fn) { + fn.apply(fn); + }) - // find the shape that is responsible for this elemement's id. - var elementController = uiObj; + }, - //get event position - var evPos = this.eventCoordinates(event); + /** + * Returns the text length of the text content of an SVG tspan element. + * For all browsers but Firefox 3 the values are estimated. + * @param {TSpanSVGElement} tspan + * @param {int} startIndex Optional, for sub strings + * @param {int} endIndex Optional, for sub strings + */ + _getRenderedTextLength: function (tspan, startIndex, endIndex, fontSize) { + //if (/Firefox[\/\s](\d+\.\d+)/.test(navigator.userAgent) && new Number(RegExp.$1) >= 3) { + if (startIndex === undefined) { +//test string: abcdefghijklmnopqrstuvwxyz????????????????,.-#+ 1234567890?????ABCDEFGHIJKLMNOPQRSTUVWXYZ;:_'*???????????????!"????$%&/()=?[]{}|<>'~????`\^?????????@????????????????? +// for(var i = 0; i < tspan.textContent.length; i++) { +// console.log(tspan.textContent.charAt(i), tspan.getSubStringLength(i,1), this._estimateCharacterWidth(tspan.textContent.charAt(i))*(fontSize/14.0)); +// } + return tspan.getComputedTextLength(); + } else { + return tspan.getSubStringLength(startIndex, endIndex); + } + /*} else { + if(startIndex === undefined) { + return this._estimateTextWidth(tspan.textContent, fontSize); + } else { + return this._estimateTextWidth(tspan.textContent.substr(startIndex, endIndex).trim(), fontSize); + } + }*/ + }, - //Event.stop(event); - }, + /** + * Estimates the text width for a string. + * Used for word wrapping in all browser but FF3. + * @param {Object} text + */ + _estimateTextWidth: function (text, fontSize) { + var sum = 0.0; + for (var i = 0; i < text.length; i++) { + sum += this._estimateCharacterWidth(text.charAt(i)); + } - _handleMouseHover: function(event, uiObj) { - return; - }, + return sum * (fontSize / 14.0); + }, - _handleMouseOut: function(event, uiObj) { - return; - }, + /** + * Estimates the width of a single character for font size 14. + * Used for word wrapping in all browser but FF3. + * @param {Object} character + */ + _estimateCharacterWidth: function (character) { + for (var i = 0; i < this._characterSets.length; i++) { + if (this._characterSets[i].indexOf(character) >= 0) { + return this._characterSetValues[i]; + } + } + return 9; + }, - /** - * Calculates the event coordinates to SVG document coordinates. - * @param {Event} event - * @return {SVGPoint} The event coordinates in the SVG document - */ - eventCoordinates: function(event) { + getReferencedElementWidth: function () { + var refNode = this.node.ownerDocument.getElementById(this.fitToElemId); - var canvas = this.getCanvas(); + if (refNode) { + var refbb = refNode.getBBox(); - var svgPoint = canvas.node.ownerSVGElement.createSVGPoint(); - svgPoint.x = event.clientX; - svgPoint.y = event.clientY; - - var additionalIEZoom = 1; - if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) { - var ua = navigator.userAgent; - if (ua.indexOf('MSIE') >= 0) { - //IE 10 and below - var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100); - if (zoom !== 100) { - additionalIEZoom = zoom / 100 - } + if (refbb) { + return (this._rotate != 0 + && this._rotate % 180 != 0 + && this._rotate % 90 == 0 ? + refbb.height : refbb.width); } } - - if (additionalIEZoom !== 1) { - svgPoint.x = svgPoint.x * additionalIEZoom; - svgPoint.y = svgPoint.y * additionalIEZoom; - } - - var matrix = canvas.node.getScreenCTM(); - return svgPoint.matrixTransform(matrix.inverse()); - }, - - eventCoordinatesXY: function(x, y) { - var canvas = this.getCanvas(); + return undefined; + }, - var svgPoint = canvas.node.ownerSVGElement.createSVGPoint(); - svgPoint.x = x; - svgPoint.y = y; - - var additionalIEZoom = 1; - if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) { - var ua = navigator.userAgent; - if (ua.indexOf('MSIE') >= 0) { - //IE 10 and below - var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100); - if (zoom !== 100) { - additionalIEZoom = zoom / 100 + /** + * If no parameter is provided, this method returns the current text. + * @param text {String} Optional. Replaces the old text with this one. + */ + text: function () { + switch (arguments.length) { + case 0: + return this._text + break; + + case 1: + var oldText = this._text; + if (arguments[0]) { + // Filter out multiple spaces to fix issue in chrome for line-wrapping + this._text = arguments[0].toString(); + if (this._text != null && this._text != undefined) { + this._text = this._text.replace(/ {2,}/g, ' '); + } + } else { + this._text = ""; } - } + if (oldText !== this._text) { + this._isChanged = true; + this._textHasChanged = true; + } + break; + + default: + //TODO error + break; } - - if (additionalIEZoom !== 1) { - svgPoint.x = svgPoint.x * additionalIEZoom; - svgPoint.y = svgPoint.y * additionalIEZoom; + }, + + 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 oldValue = this._verticalAlign; + this._verticalAlign = arguments[0]; + if (this._verticalAlign !== oldValue) { + this._isChanged = true; + } + } + break; + + default: + //TODO error + break; } - - var matrix = canvas.node.getScreenCTM(); - return svgPoint.matrixTransform(matrix.inverse()); - } -}; -ORYX.Editor = Clazz.extend(ORYX.Editor); + }, -/** - * Creates a new ORYX.Editor instance by fetching a model from given url and passing it to the constructur - * @param {String} modelUrl The JSON URL of a model. - * @param {Object} config Editor config passed to the constructur, merged with the response of the request to modelUrl - */ -ORYX.Editor.createByUrl = function(modelUrl){ - new Ajax.Request(modelUrl, { - method: 'GET', - onSuccess: function(transport) { - var editorConfig = JSON.parse(transport.responseText); - new ORYX.Editor(editorConfig); - }.bind(this) - }); -} + getOriginHorizontalAlign: function () { + return this._originHorizontalAlign; + }, -// TODO Implement namespace awareness on attribute level. -/** - * graft() function - * Originally by Sean M. Burke from interglacial.com, altered for usage with - * SVG and namespace (xmlns) support. Be sure you understand xmlns before - * using this funtion, as it creates all grafted elements in the xmlns - * provided by you and all element's attribures in default xmlns. If you - * need to graft elements in a certain xmlns and wish to assign attributes - * in both that and another xmlns, you will need to do stepwise grafting, - * adding non-default attributes yourself or you'll have to enhance this - * function. Latter, I would appreciate: martin???apfelfabrik.de - * @param {Object} namespace The namespace in which - * elements should be grafted. - * @param {Object} parent The element that should contain the grafted - * structure after the function returned. - * @param {Object} t the crafting structure. - * @param {Object} doc the document in which grafting is performed. - */ -ORYX.Editor.graft = function(namespace, parent, t, doc) { + horizontalAlign: function () { + switch (arguments.length) { + case 0: + return this._horizontalAlign; + case 1: + if (['left', 'center', 'right'].member(arguments[0])) { + var oldValue = this._horizontalAlign; + this._horizontalAlign = arguments[0]; + if (this._horizontalAlign !== oldValue) { + this._isChanged = true; + } + } + break; - doc = (doc || (parent && parent.ownerDocument) || document); - var e; - if(t === undefined) { - throw "Can't graft an undefined value"; - } else if(t.constructor == String) { - e = doc.createTextNode( t ); - } else { - for(var i = 0; i < t.length; i++) { - if( i === 0 && t[i].constructor == String ) { - var snared; - snared = t[i].match( /^([a-z][a-z0-9]*)\.([^\s\.]+)$/i ); - if( snared ) { - e = doc.createElementNS(namespace, snared[1] ); - e.setAttributeNS(null, 'class', snared[2] ); - continue; + default: + //TODO error + 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; } - snared = t[i].match( /^([a-z][a-z0-9]*)$/i ); - if( snared ) { - e = doc.createElementNS(namespace, snared[1] ); // but no class - continue; + 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; } - // Otherwise: - e = doc.createElementNS(namespace, "span" ); - e.setAttribute(null, "class", "namelessFromLOL" ); - } + } + }, - if( t[i] === undefined ) { - throw "Can't graft an undefined value in a list!"; - } else if( t[i].constructor == String || t[i].constructor == Array ) { - this.graft(namespace, e, t[i], doc ); - } else if( t[i].constructor == Number ) { - this.graft(namespace, e, t[i].toString(), doc ); - } else if( t[i].constructor == Object ) { - // hash's properties => element's attributes - for(var k in t[i]) { e.setAttributeNS(null, k, t[i][k] ); } - } else { + hide: function () { + if (this.isVisible) { + this.isVisible = false; + this._isChanged = true; + } + }, - } + show: function () { + if (!this.isVisible) { + this.isVisible = true; + this._isChanged = true; + + // Since text is removed from the tspan when "hidden", mark + // the text as changed to get it redrawn + this._textHasChanged = true; } - } - if(parent && parent.appendChild) { - parent.appendChild( e ); - } else { + }, - } - return e; // return the topmost created node -}; + /** + * iterates parent nodes till it finds a SVG font-size + * attribute. + * @param {SVGElement} node + */ + getInheritedFontSize: function (node) { + if (!node || !node.getAttributeNS) + return; -ORYX.Editor.provideId = function() { - var res = [], hex = '0123456789ABCDEF'; + var attr = node.getAttributeNS(null, "font-size"); + if (attr) { + return parseFloat(attr); + } else if (!ORYX.Editor.checkClassType(node, SVGSVGElement)) { + return this.getInheritedFontSize(node.parentNode); + } + }, - for (var i = 0; i < 36; i++) res[i] = Math.floor(Math.random()*0x10); + getFontSize: function (node) { + var tspans = this.node.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'tspan'); - res[14] = 4; - res[19] = (res[19] & 0x3) | 0x8; + //trying to get an inherited font-size attribute + //NO CSS CONSIDERED! + var fontSize = this.getInheritedFontSize(this.node); - for (var i = 0; i < 36; i++) res[i] = hex[res[i]]; + if (!fontSize) { + //because this only works in firefox 3, all other browser use the default line height + if (tspans[0] && /Firefox[\/\s](\d+\.\d+)/.test(navigator.userAgent) && new Number(RegExp.$1) >= 3) { + fontSize = tspans[0].getExtentOfChar(0).height; + } else { + fontSize = ORYX.CONFIG.LABEL_DEFAULT_LINE_HEIGHT; + } - res[8] = res[13] = res[18] = res[23] = '-'; + //handling of unsupported method in webkit + if (fontSize <= 0) { + fontSize = ORYX.CONFIG.LABEL_DEFAULT_LINE_HEIGHT; + } + } - return "oryx_" + res.join(''); -}; + if (fontSize) + this.node.setAttribute("oryx:fontSize", fontSize); -/** - * When working with Ext, conditionally the window needs to be resized. To do - * so, use this class method. Resize is deferred until 100ms, and all subsequent - * resizeBugFix calls are ignored until the initially requested resize is - * performed. - */ -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); - } -}; + return fontSize; + }, -ORYX.Editor.Cookie = { - - callbacks:[], - - onChange: function( callback, interval ){ - - this.callbacks.push(callback); - this.start( interval ) - - }, - - start: function( interval ){ - - if( this.pe ){ - return; - } - - var currentString = document.cookie; - - this.pe = new PeriodicalExecuter( function(){ - - if( currentString != document.cookie ){ - currentString = document.cookie; - this.callbacks.each(function(callback){ callback(this.getParams()) }.bind(this)); - } - - }.bind(this), ( interval || 10000 ) / 1000); - }, - - stop: function(){ + /** + * Get trimmed text length for use with + * getExtentOfChar and getSubStringLength. + * @param {String} text + */ + getTrimmedTextLength: function (text) { + text = text.strip().gsub(' ', ' '); - if( this.pe ){ - this.pe.stop(); - this.pe = null; - } - }, - - getParams: function(){ - var res = {}; - - var p = document.cookie; - p.split("; ").each(function(param){ res[param.split("=")[0]] = param.split("=")[1];}); - - return res; - }, - - toString: function(){ - return document.cookie; - } -}; + var oldLength; + do { + oldLength = text.length; + text = text.gsub(' ', ' '); + } while (oldLength > text.length); -/** - * Workaround for SAFARI/Webkit, because - * when trying to check SVGSVGElement of instanceof there is - * raising an error - * - */ -ORYX.Editor.SVGClassElementsAreAvailable = true; -ORYX.Editor.setMissingClasses = function() { - - try { - SVGElement; - } catch(e) { - 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(); - //SVGMarkerElement = document.createElementNS('http://www.w3.org/2000/svg', 'marker').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( classInst, classType ) { - - if( ORYX.Editor.SVGClassElementsAreAvailable ){ - return classInst instanceof classType - } else { - return classInst == classType - } -}; -/* + return text.length; + }, + + /** + * Returns the offset from + * edge to the label which is + * positioned under the edge + * @return {int} + */ + getOffsetBottom: function () { + return this.offsetBottom; + }, + + + /** + * Returns the offset from + * edge to the label which is + * positioned over the edge + * @return {int} + */ + getOffsetTop: function () { + return this.offsetTop; + }, + + /** + * + * @param {Object} obj + */ + deserialize: function (obj, shape) { + if (obj && "undefined" != typeof obj.x && "undefined" != typeof obj.y) { + this.setPosition({x: obj.x, y: obj.y}); + + if ("undefined" != typeof obj.distance) { + var from = shape.dockers[obj.from]; + var to = shape.dockers[obj.to]; + if (from && to) { + this.setReferencePoint({ + dirty: true, + distance: obj.distance, + intersection: {x: obj.x, y: obj.y}, + orientation: obj.orientation, + segment: { + from: from, + fromIndex: obj.from, + fromPosition: from.bounds.center(), + to: to, + toIndex: obj.to, + toPosition: to.bounds.center() + } + }) + } + } + + if (obj.left) this.anchorLeft = true; + if (obj.right) this.anchorRight = true; + if (obj.top) this.anchorTop = true; + if (obj.bottom) this.anchorBottom = true; + if (obj.valign) this.verticalAlign(obj.valign); + if (obj.align) this.horizontalAlign(obj.align); + + } else if (obj && "undefined" != typeof obj.edge) { + this.setEdgePosition(obj.edge); + } + }, + + /** + * + * @return {Object} + */ + serialize: function () { + + // On edge position + if (this.getEdgePosition()) { + if (this.getOriginEdgePosition() !== this.getEdgePosition()) { + return {edge: this.getEdgePosition()}; + } else { + return null; + } + } + + // On self defined position + if (this.position) { + var pos = {x: this.position.x, y: this.position.y}; + if (this.isAnchorLeft() && this.isAnchorLeft() !== this.isOriginAnchorLeft()) { + pos.left = true; + } + if (this.isAnchorRight() && this.isAnchorRight() !== this.isOriginAnchorRight()) { + pos.right = true; + } + if (this.isAnchorTop() && this.isAnchorTop() !== this.isOriginAnchorTop()) { + pos.top = true; + } + if (this.isAnchorBottom() && this.isAnchorBottom() !== this.isOriginAnchorBottom()) { + pos.bottom = true; + } + + if (this.getOriginVerticalAlign() !== this.verticalAlign()) { + pos.valign = this.verticalAlign(); + } + if (this.getOriginHorizontalAlign() !== this.horizontalAlign()) { + pos.align = this.horizontalAlign(); + } + + return pos; + } + + // On reference point which is interesting for edges + if (this.getReferencePoint()) { + var ref = this.getReferencePoint(); + return { + distance: ref.distance, + x: ref.intersection.x, + y: ref.intersection.y, + from: ref.segment.fromIndex, + to: ref.segment.toIndex, + orientation: ref.orientation, + valign: this.verticalAlign(), + align: this.horizontalAlign() + } + } + return null; + }, + + toString: function () { + return "Label " + this.id + } +});/* * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. * License rights for this program may be obtained from Alfresco Software, Ltd. * pursuant to a written agreement and any use of this program without such an @@ -12611,2426 +5387,14710 @@ ORYX.Editor.checkClassType = function( classInst, classType ) { /** * Init namespaces */ -if(!ORYX) {var ORYX = {};} -if(!ORYX.Core) {ORYX.Core = {};} - - -new function(){ - - ORYX.Core.UIEnableDrag = function(event, uiObj, option) { - - this.uiObj = uiObj; - var upL = uiObj.bounds.upperLeft(); - - var a = uiObj.node.getScreenCTM(); - this.faktorXY= {x: a.a, y: a.d}; - - this.scrollNode = uiObj.node.ownerSVGElement.parentNode.parentNode; - - this.offSetPosition = { - x: Event.pointerX(event) - (upL.x * this.faktorXY.x), - y: Event.pointerY(event) - (upL.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 = option ? option.movedCallback : undefined; - this.upCallback = option ? option.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(event) { - - var position = { - x: Event.pointerX(event) - this.offSetPosition.x, - y: Event.pointerY(event) - this.offSetPosition.y} - - position.x -= this.offsetScroll.x - this.scrollNode.scrollLeft; - position.y -= this.offsetScroll.y - this.scrollNode.scrollTop; - - position.x /= this.faktorXY.x; - position.y /= this.faktorXY.y; - - this.uiObj.bounds.moveTo(position); - //this.uiObj.update(); - - if(this.movedCallback) - this.movedCallback(event); - - //Event.stop(event); - - }; - - ORYX.Core.UIDisableDrag = function(event) { - 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(event); - - this.upCallback = undefined; - this.movedCallback = undefined; - - Event.stop(event); - }; - - - - - /** - * Implements a command to move docker by an offset. - * - * @class ORYX.Core.MoveDockersCommand - * @param {Object} object An object with the docker id as key and docker and offset as object value - * - */ - ORYX.Core.MoveDockersCommand = ORYX.Core.Command.extend({ - construct: function(dockers){ - this.dockers = $H(dockers); - this.edges = $H({}); - }, - execute: function(){ - if (this.changes) { - this.executeAgain(); - return; - } else { - this.changes = $H({}); - } - - this.dockers.values().each(function(docker){ - var edge = docker.docker.parent; - if (!edge){ return } - - if (!this.changes[edge.getId()]) { - this.changes[edge.getId()] = { - edge : edge, - oldDockerPositions : edge.dockers.map(function(r){ return r.bounds.center() }) - } - } - docker.docker.bounds.moveBy(docker.offset); - this.edges[edge.getId()] = edge; - docker.docker.update(); - }.bind(this)); - this.edges.each(function(edge){ - this.updateEdge(edge.value); - if (this.changes[edge.value.getId()]) - this.changes[edge.value.getId()].dockerPositions = edge.value.dockers.map(function(r){ return r.bounds.center() }) - }.bind(this)); - }, - updateEdge: function(edge){ - edge._update(true); - [edge.getOutgoingShapes(), edge.getIncomingShapes()].flatten().invoke("_update", [true]) - }, - executeAgain: function(){ - this.changes.values().each(function(change){ - // Reset the dockers - this.removeAllDocker(change.edge); - change.dockerPositions.each(function(pos, i){ - if (i==0||i==change.dockerPositions.length-1){ return } - var docker = change.edge.createDocker(undefined, pos); - docker.bounds.centerMoveTo(pos); - docker.update(); - }.bind(this)); - this.updateEdge(change.edge); - }.bind(this)); - }, - rollback: function(){ - this.changes.values().each(function(change){ - // Reset the dockers - this.removeAllDocker(change.edge); - change.oldDockerPositions.each(function(pos, i){ - if (i==0||i==change.oldDockerPositions.length-1){ return } - var docker = change.edge.createDocker(undefined, pos); - docker.bounds.centerMoveTo(pos); - docker.update(); - }.bind(this)); - this.updateEdge(change.edge); - }.bind(this)); - }, - removeAllDocker: function(edge){ - edge.dockers.slice(1, edge.dockers.length-1).each(function(docker){ - edge.removeDocker(docker); - }) - } - }); - -}(); -/* - * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. - * License rights for this program may be obtained from Alfresco Software, Ltd. - * pursuant to a written agreement and any use of this program without such an - * agreement is prohibited. - */ -/* - * All code Copyright 2013 KIS Consultancy all rights reserved - */ +if (!ORYX) { + var ORYX = {}; +} +if (!ORYX.Core) { + ORYX.Core = {}; +} +if (!ORYX.Core.Math) { + ORYX.Core.Math = {}; +} /** - * Init namespaces + * Calculate the middle point between two given points + * @param {x:double, y:double} point1 + * @param {x:double, y:double} point2 + * @return the middle point */ -if(!ORYX) {var ORYX = {};} -if(!ORYX.Core) {ORYX.Core = {};} +ORYX.Core.Math.midPoint = function (point1, point2) { + return { + x: (point1.x + point2.x) / 2.0, + y: (point1.y + point2.y) / 2.0 + } +} /** - * @classDescription Base class for Shapes. - * @extends ORYX.Core.AbstractShape + * Returns a TRUE if the point is over a line (defined by + * point1 and point 2). In Addition a threshold can be set, + * which defines the weight of those line. + * + * @param {int} pointX - Point X + * @param {int} pointY - Point Y + * @param {int} lPoint1X - Line first Point X + * @param {int} lPoint1Y - Line first Point Y + * @param {int} lPoint2X - Line second Point X + * @param {int} lPoint2Y - Line second Point y + * @param {int} offset {optional} - maximal distance to line + * @class ORYX.Core.Math.prototype */ -ORYX.Core.Shape = { - - /** - * Constructor - */ - construct: function(options, stencil, facade) { - // call base class constructor - arguments.callee.$.construct.apply(this, arguments); - - this.facade = facade; - this.dockers = []; - this.magnets = []; - - this._defaultMagnet; - - this.incoming = []; - this.outgoing = []; - - this.nodes = []; - - this._dockerChangedCallback = this._dockerChanged.bind(this); - - //Hash map for all labels. Labels are not treated as children of shapes. - this._labels = new Hash(); - - // create SVG node - 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"}] - ] - ]); - }, +ORYX.Core.Math.isPointInLine = function (pointX, pointY, lPoint1X, lPoint1Y, lPoint2X, lPoint2Y, offset) { - /** - * If changed flag is set, refresh method is called. - */ - update: function() { - //if(this.isChanged) { - //this.layout(); - //} - }, - - /** - * !!!Not called from any sub class!!! - */ - _update: function() { + offset = offset ? Math.abs(offset) : 1; - }, - - /** - * Calls the super class refresh method - * and updates the svg elements that are referenced by a property. - */ - refresh: function() { - //call base class refresh method - arguments.callee.$.refresh.apply(this, arguments); - - if(this.node.ownerDocument) { - //adjust SVG to properties' values - var me = this; - this.propertiesChanged.each((function(propChanged) { - if(propChanged.value) { - var prop = this.properties[propChanged.key]; - var property = this.getStencil().property(propChanged.key); - if (property != undefined) { - this.propertiesChanged[propChanged.key] = false; - - //handle choice properties - if(property.type() == ORYX.CONFIG.TYPE_CHOICE) { - //iterate all references to SVG elements - property.refToView().each((function(ref) { - //if property is referencing a label, update the label - if(ref !== "") { - var label = this._labels[this.id + ref]; - if (label && property.item(prop)) { - label.text(property.item(prop).title()); - } - } - }).bind(this)); - - //if the choice's items are referencing SVG elements - // show the selected and hide all other referenced SVG - // elements - var refreshedSvgElements = new Hash(); - property.items().each((function(item) { - item.refToView().each((function(itemRef) { - if(itemRef == "") { return; } - - var svgElem = this.node.ownerDocument.getElementById(this.id + itemRef); - - if(!svgElem) { return; } - - - /* Do not refresh the same svg element multiple times */ - if(!refreshedSvgElements[svgElem.id] || prop == item.value()) { - svgElem.setAttributeNS(null, 'display', ((prop == item.value()) ? 'inherit' : 'none')); - refreshedSvgElements[svgElem.id] = svgElem; - } - - // Reload the href if there is an image-tag - if(ORYX.Editor.checkClassType(svgElem, SVGImageElement)) { - svgElem.setAttributeNS('http://www.w3.org/1999/xlink', 'href', svgElem.getAttributeNS('http://www.w3.org/1999/xlink', 'href')); - } - }).bind(this)); - }).bind(this)); - - } else { //handle properties that are not of type choice - //iterate all references to SVG elements - property.refToView().each((function(ref) { - //if the property does not reference an SVG element, - // do nothing - - if(ref === "") { return; } - - var refId = this.id + ref; - - if (property.type() === ORYX.CONFIG.TYPE_KISBPM_MULTIINSTANCE) - { - if (ref === "multiinstance") { - - var svgElemParallel = this.node.ownerDocument.getElementById(this.id + 'parallel'); - if(svgElemParallel) - { - if (prop === 'Parallel') - { - svgElemParallel.setAttributeNS(null, 'display', 'inherit'); - } - else - { - svgElemParallel.setAttributeNS(null, 'display', 'none'); - } - } - - var svgElemSequential = this.node.ownerDocument.getElementById(this.id + 'sequential'); - - if(svgElemSequential) - { - if (prop === 'Sequential') - { - svgElemSequential.setAttributeNS(null, 'display', 'inherit'); - } - else - { - svgElemSequential.setAttributeNS(null, 'display', 'none'); - } - } - } - return; - - } - else if (property.type() === "cancelactivity") - { - var svgElemFrame = this.node.ownerDocument.getElementById(this.id + 'frame'); - var svgElemFrame2 = this.node.ownerDocument.getElementById(this.id + 'frame2'); - - if (prop === 'true') - { - svgElemFrame.setAttributeNS(null, 'display', 'inherit'); - svgElemFrame2.setAttributeNS(null, 'display', 'inherit'); - } - else - { - svgElemFrame.setAttributeNS(null, 'display', 'none'); - svgElemFrame2.setAttributeNS(null, 'display', 'none'); - } - } - - //get the SVG element - var svgElem = this.node.ownerDocument.getElementById(refId); - - //if the SVG element can not be found - if(!svgElem || !(svgElem.ownerSVGElement)) { - //if the referenced SVG element is a SVGAElement, it cannot - // be found with getElementById (Firefox bug). - // this is a work around - if(property.type() === ORYX.CONFIG.TYPE_URL || property.type() === ORYX.CONFIG.TYPE_DIAGRAM_LINK) { - var svgElems = this.node.ownerDocument.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'a'); - - svgElem = $A(svgElems).find(function(elem) { - return elem.getAttributeNS(null, 'id') === refId; - }); - - if(!svgElem) { return; } - } else { - //this.propertiesChanged[propChanged.key] = true; - return; - } - } - - if (property.complexAttributeToView()) { - var label = this._labels[refId]; - if (label) { - try { - propJson = prop.evalJSON(); - var value = propJson[property.complexAttributeToView()] - label.text(value ? value : prop); - } catch (e) { - label.text(prop); - } - } - - } else { - switch (property.type()) { - case ORYX.CONFIG.TYPE_BOOLEAN: - if (typeof prop == "string") - prop = prop === "true" - - svgElem.setAttributeNS(null, 'display', (!(prop === property.inverseBoolean())) ? 'inherit' : 'none'); - - break; - case ORYX.CONFIG.TYPE_COLOR: - if(property.fill()) { - if (svgElem.tagName.toLowerCase() === "stop"){ - if (prop){ - - if (property.lightness() && property.lightness() !== 1){ - prop = ORYX.Utils.adjustLightness(prop, property.lightness()); - } - - svgElem.setAttributeNS(null, "stop-color", prop); - - // Adjust stop color of the others - if (svgElem.parentNode.tagName.toLowerCase() === "radialgradient"){ - ORYX.Utils.adjustGradient(svgElem.parentNode, svgElem); - } - } - - // If there is no value, set opaque - if (svgElem.parentNode.tagName.toLowerCase() === "radialgradient"){ - $A(svgElem.parentNode.getElementsByTagName('stop')).each(function(stop){ - stop.setAttributeNS(null, "stop-opacity", prop ? stop.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'default-stop-opacity') || 1 : 0); - }.bind(this)) - } - } else { - svgElem.setAttributeNS(null, 'fill', prop); - } - } - if(property.stroke()) { - svgElem.setAttributeNS(null, 'stroke', prop); - } - break; - case ORYX.CONFIG.TYPE_STRING: - var label = this._labels[refId]; - if (label) { - label.text(prop); - } - break; - case ORYX.CONFIG.TYPE_EXPRESSION: - var label = this._labels[refId]; - if (label) { - label.text(prop); - } - break; - case ORYX.CONFIG.TYPE_DATASOURCE: - var label = this._labels[refId]; - if (label) { - label.text(prop); - } - break; - case ORYX.CONFIG.TYPE_INTEGER: - var label = this._labels[refId]; - if (label) { - label.text(prop); - } - break; - case ORYX.CONFIG.TYPE_FLOAT: - if(property.fillOpacity()) { - svgElem.setAttributeNS(null, 'fill-opacity', prop); - } - if(property.strokeOpacity()) { - svgElem.setAttributeNS(null, 'stroke-opacity', prop); - } - if(!property.fillOpacity() && !property.strokeOpacity()) { - var label = this._labels[refId]; - if (label) { - label.text(prop); - } - } - break; - - case ORYX.CONFIG.TYPE_FORM_LINK: - if (ref == "pimg") { - var onclickAttr = svgElem.getAttributeNodeNS('', 'onclick'); - if(onclickAttr) { - if(prop && ("" + prop).length > 0) { - onclickAttr.textContent = "window.location = '../service/editor?id=" + prop + "_form'"; - } else { - newFormFacade = this.facade; - onclickAttr.textContent = "displayNewFormDialog('" + this.resourceId + "');"; - } - } - } else if (ref == "linkIndicator") { - if (prop && prop.length > 0) { - svgElem.setAttributeNS(null, 'display', 'inherit'); - } else { - svgElem.setAttributeNS(null, 'display', 'none'); - } - } - break; - case ORYX.CONFIG.TYPE_URL: - case ORYX.CONFIG.TYPE_DIAGRAM_LINK: - //TODO what is the dafault path? - var hrefAttr = svgElem.getAttributeNodeNS('http://www.w3.org/1999/xlink', 'xlink:href'); - if(hrefAttr) { - hrefAttr.textContent = prop; - } else { - svgElem.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', prop); - } - break; - - } - } - }).bind(this)); - - - } - } - - } - }).bind(this)); - - //update labels - this._labels.values().each(function(label) { - label.update(); - }); - } - }, - - layout: function() { - //this.getStencil().layout(this) - var layoutEvents = this.getStencil().layout() - if (layoutEvents) { - layoutEvents.each(function(event) { - - // setup additional attributes - event.shape = this; - event.forceExecution = true; - - // do layouting - this._delegateEvent(event); - }.bind(this)) - - } - }, - - /** - * Returns an array of Label objects. - */ - getLabels: function() { - return this._labels.values(); - }, - - /** - * Returns the label for a given ref - * @return {ORYX.Core.Label} Returns null if there is no label - */ - getLabel: function(ref){ - if (!ref){ - return null; - } - return (this._labels.find(function(o){ - return o.key.endsWith(ref); - })||{}).value || null; - }, - - /** - * Hides all related labels - * - */ - hideLabels: function(){ - this.getLabels().invoke("hide"); - }, + // Check if the edge is vertical + if (Math.abs(lPoint1X - lPoint2X) <= offset && Math.abs(pointX - lPoint1X) <= offset && pointY - Math.max(lPoint1Y, lPoint2Y) <= offset && Math.min(lPoint1Y, lPoint2Y) - pointY <= offset) { + return true + } - /** - * Shows all related labels - * - */ - showLabels: function(){ - var labels = this.getLabels(); - labels.invoke("show"); - labels.each(function(label) { - label.update(); - }); - }, - - setOpacity: function(value, animate){ - - value = Math.max(Math.min((typeof value == "number" ? value : 1.0), 1.0), 0.0); - - if (value !== 1.0){ - value = String(value); - this.node.setAttributeNS(null, "fill-opacity", value) - this.node.setAttributeNS(null, "stroke-opacity", value) - } else { - this.node.removeAttributeNS(null, "fill-opacity"); - this.node.removeAttributeNS(null, "stroke-opacity"); - } - }, - - /** - * Returns an array of dockers of this object. - */ - 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; - } - }, + // Check if the edge is horizontal + if (Math.abs(lPoint1Y - lPoint2Y) <= offset && Math.abs(pointY - lPoint1Y) <= offset && pointX - Math.max(lPoint1X, lPoint2X) <= offset && Math.min(lPoint1X, lPoint2X) - pointX <= offset) { + return true + } - getParentShape: function() { - return this.parent; - }, - - getIncomingShapes: function(iterator) { - if(iterator) { - this.incoming.each(iterator); - } - return this.incoming; - }, - - getIncomingNodes: function(iterator) { - return this.incoming.select(function(incoming){ - var isNode = (incoming instanceof ORYX.Core.Node); - if(isNode && iterator) iterator(incoming); - return isNode; - }); - }, - - - getOutgoingShapes: function(iterator) { - if(iterator) { - this.outgoing.each(iterator); - } - return this.outgoing; - }, - - getOutgoingNodes: function(iterator) { - return this.outgoing.select(function(out){ - var isNode = (out instanceof ORYX.Core.Node); - if(isNode && iterator) iterator(out); - return isNode; - }); - }, - - getAllDockedShapes: function(iterator) { - var result = this.incoming.concat(this.outgoing); - if(iterator) { - result.each(iterator); - } - return result - }, + if (pointX > Math.max(lPoint1X, lPoint2X) || pointX < Math.min(lPoint1X, lPoint2X)) { + return false + } - 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; - } - }, - - /** - * - * @param {Object} deep - * @param {Object} iterator - */ - getChildNodes: function(deep, iterator) { - if(!deep && !iterator) { - return this.nodes.clone(); - } else { - var result = []; - this.nodes.each(function(uiObject) { - if(!uiObject.isVisible){return} - if(iterator) { - iterator(uiObject); - } - result.push(uiObject); - - if(deep && uiObject instanceof ORYX.Core.Shape) { - result = result.concat(uiObject.getChildNodes(deep, iterator)); - } - }); - - return result; - } - }, - - /** - * Overrides the UIObject.add method. Adds uiObject to the correct sub node. - * @param {UIObject} uiObject - * @param {Number} index - */ - add: function(uiObject, index, silent) { - //parameter has to be an UIObject, but - // must not be an Edge. - if(uiObject instanceof ORYX.Core.UIObject - && !(uiObject instanceof ORYX.Core.Edge)) { - - if (!(this.children.member(uiObject))) { - //if uiObject is child of another parent, remove it from that parent. - if(uiObject.parent) { - uiObject.parent.remove(uiObject, true); - } - - //add uiObject to this Shape - if(index != undefined) - this.children.splice(index, 0, uiObject); - else - this.children.push(uiObject); - - //set parent reference - uiObject.parent = this; - - //add uiObject.node to this.node depending on the type of uiObject - var parent; - if(uiObject instanceof ORYX.Core.Node) { - parent = this.node.childNodes[0].childNodes[1]; - this.nodes.push(uiObject); - } else if(uiObject instanceof ORYX.Core.Controls.Control) { - var ctrls = this.node.childNodes[1]; - if(uiObject instanceof ORYX.Core.Controls.Docker) { - parent = ctrls.childNodes[0]; - if (this.dockers.length >= 2){ - this.dockers.splice(index!==undefined?Math.min(index, this.dockers.length-1):this.dockers.length-1, 0, uiObject); - } else { - this.dockers.push(uiObject); - } - } else if(uiObject instanceof ORYX.Core.Controls.Magnet) { - parent = ctrls.childNodes[1]; - this.magnets.push(uiObject); - } else { - parent = ctrls; - } - } else { //UIObject - parent = this.node; - } - - if(index != undefined && index < parent.childNodes.length) - uiObject.node = parent.insertBefore(uiObject.node, parent.childNodes[index]); - else - uiObject.node = parent.appendChild(uiObject.node); - - this._changed(); - //uiObject.bounds.registerCallback(this._changedCallback); - - - if(this.eventHandlerCallback && silent !== true) - this.eventHandlerCallback({type:ORYX.CONFIG.EVENT_SHAPEADDED,shape:uiObject}) - - } else { + if (pointY > Math.max(lPoint1Y, lPoint2Y) || pointY < Math.min(lPoint1Y, lPoint2Y)) { + return false + } - ORYX.Log.warn("add: ORYX.Core.UIObject is already a child of this object."); - } - } else { + var s = (lPoint1Y - lPoint2Y) / (lPoint1X - lPoint2X); - ORYX.Log.warn("add: Parameter is not of type ORYX.Core.UIObject."); - } - }, + return Math.abs(pointY - ((s * pointX) + lPoint1Y - s * lPoint1X)) < offset +} - /** - * Overrides the UIObject.remove method. Removes uiObject. - * @param {UIObject} uiObject - */ - remove: function(uiObject, silent) { - //if uiObject is a child of this object, remove it. - if (this.children.member(uiObject)) { - //remove uiObject from children - var parent = uiObject.parent; - - this.children = this.children.without(uiObject); - - //delete parent reference of uiObject - uiObject.parent = undefined; - - //delete uiObject.node from this.node - if(uiObject instanceof ORYX.Core.Shape) { - if(uiObject instanceof ORYX.Core.Edge) { - uiObject.removeMarkers(); - uiObject.node = this.node.childNodes[0].childNodes[2].removeChild(uiObject.node); - } else { - uiObject.node = this.node.childNodes[0].childNodes[1].removeChild(uiObject.node); - this.nodes = this.nodes.without(uiObject); - } - } else if(uiObject instanceof ORYX.Core.Controls.Control) { - if (uiObject instanceof ORYX.Core.Controls.Docker) { - uiObject.node = this.node.childNodes[1].childNodes[0].removeChild(uiObject.node); - this.dockers = this.dockers.without(uiObject); - } else if (uiObject instanceof ORYX.Core.Controls.Magnet) { - uiObject.node = this.node.childNodes[1].childNodes[1].removeChild(uiObject.node); - this.magnets = this.magnets.without(uiObject); - } else { - uiObject.node = this.node.childNodes[1].removeChild(uiObject.node); - } - } +/** + * Get a boolean if the point is in the polygone + * + */ +ORYX.Core.Math.isPointInEllipse = function (pointX, pointY, cx, cy, rx, ry) { - if(this.eventHandlerCallback && silent !== true) - this.eventHandlerCallback({type: ORYX.CONFIG.EVENT_SHAPEREMOVED, shape: uiObject, parent: parent}); - - this._changed(); - //uiObject.bounds.unregisterCallback(this._changedCallback); - } else { + if (cx === undefined || cy === undefined || rx === undefined || ry === undefined) { + throw "ORYX.Core.Math.isPointInEllipse needs a ellipse with these properties: x, y, radiusX, radiusY" + } - ORYX.Log.warn("remove: ORYX.Core.UIObject is not a child of this object."); - } - }, - - /** - * Calculate the Border Intersection Point between two points - * @param {PointA} - * @param {PointB} - */ - getIntersectionPoint: function() { - - var pointAX, pointAY, pointBX, pointBY; - - // Get the the two Points - switch(arguments.length) { - case 2: - pointAX = arguments[0].x; - pointAY = arguments[0].y; - pointBX = arguments[1].x; - pointBY = arguments[1].y; - break; - case 4: - pointAX = arguments[0]; - pointAY = arguments[1]; - pointBX = arguments[2]; - pointBY = arguments[3]; - break; - default: - throw "getIntersectionPoints needs two or four arguments"; - } - - - - // Defined an include and exclude point - var includePointX, includePointY, excludePointX, excludePointY; - - var bounds = this.absoluteBounds(); - - if(this.isPointIncluded(pointAX, pointAY, bounds)){ - includePointX = pointAX; - includePointY = pointAY; - } else { - excludePointX = pointAX; - excludePointY = pointAY; - } + var tx = (pointX - cx) / rx; + var ty = (pointY - cy) / ry; - if(this.isPointIncluded(pointBX, pointBY, bounds)){ - includePointX = pointBX; - includePointY = pointBY; - } else { - excludePointX = pointBX; - excludePointY = pointBY; - } - - // If there is no inclue or exclude Shape, than return - if(!includePointX || !includePointY || !excludePointX || !excludePointY) { - return undefined; - } + return tx * tx + ty * ty < 1.0; +} - var midPointX = 0; - var midPointY = 0; - - var refPointX, refPointY; - - var minDifferent = 1; - // Get the UpperLeft and LowerRight - //var ul = bounds.upperLeft(); - //var lr = bounds.lowerRight(); - - var i = 0; - - while(true) { - // Calculate the midpoint of the current to points - var midPointX = Math.min(includePointX, excludePointX) + ((Math.max(includePointX, excludePointX) - Math.min(includePointX, excludePointX)) / 2.0); - var midPointY = Math.min(includePointY, excludePointY) + ((Math.max(includePointY, excludePointY) - Math.min(includePointY, excludePointY)) / 2.0); - - - // Set the new midpoint by the means of the include of the bounds - if(this.isPointIncluded(midPointX, midPointY, bounds)){ - includePointX = midPointX; - includePointY = midPointY; - } else { - excludePointX = midPointX; - excludePointY = midPointY; - } - - // Calc the length of the line - var length = Math.sqrt(Math.pow(includePointX - excludePointX, 2) + Math.pow(includePointY - excludePointY, 2)) - // Calc a point one step from the include point - refPointX = includePointX + ((excludePointX - includePointX) / length), - refPointY = includePointY + ((excludePointY - includePointY) / length) - - - // If the reference point not in the bounds, break - if(!this.isPointIncluded(refPointX, refPointY, bounds)) { - break - } - - - } +/** + * Get a boolean if the point is in the polygone + * @param {int} pointX + * @param {int} pointY + * @param {[int]} Cornerpoints of the Polygone (x,y,x,y,...) + */ +ORYX.Core.Math.isPointInPolygone = function (pointX, pointY, polygone) { - // Return the last includepoint - return {x:refPointX , y:refPointY}; - }, + if (arguments.length < 3) { + throw "ORYX.Core.Math.isPointInPolygone needs two arguments" + } - - - /** - * Calculate if the point is inside the Shape - * @param {PointX} - * @param {PointY} - */ - isPointIncluded: function(){ - return false - }, + var lastIndex = polygone.length - 1; - /** - * Returns TRUE if the given node - * is a child node of the shapes node - * @param {Element} node - * @return {Boolean} - * - */ - containsNode: function(node){ - var me = this.node.firstChild.firstChild; - while(node){ - if (node == me){ - return true; - } - node = node.parentNode; - } - return false - }, - - /** - * Calculate if the point is over an special offset area - * @param {Point} - */ - isPointOverOffset: function(){ - return this.isPointIncluded.apply( this , arguments ) - }, - - _dockerChanged: function() { + if (polygone[0] !== polygone[lastIndex - 1] || polygone[1] !== polygone[lastIndex]) { + polygone.push(polygone[0]); + polygone.push(polygone[1]); + } - }, - - /** - * Create a Docker for this Edge - * - */ - createDocker: function(index, position) { - var docker = new ORYX.Core.Controls.Docker({eventHandlerCallback: this.eventHandlerCallback}); - docker.bounds.registerCallback(this._dockerChangedCallback); - if (position) { - docker.bounds.centerMoveTo(position); - } - this.add(docker, index); - - return docker - }, + var crossings = 0; - /** - * Get the serialized object - * return Array with hash-entrees (prefix, name, value) - * Following values will given: - * Bounds - * Outgoing Shapes - * Parent - */ - serialize: function() { - var serializedObject = arguments.callee.$.serialize.apply(this); + var x1, y1, x2, y2, d; - // Add the bounds - serializedObject.push({name: 'bounds', prefix:'oryx', value: this.bounds.serializeForERDF(), type: 'literal'}); + for (var i = 0; i < polygone.length - 3;) { + x1 = polygone[i]; + y1 = polygone[++i]; + x2 = polygone[++i]; + y2 = polygone[i + 1]; + d = (pointY - y1) * (x2 - x1) - (pointX - x1) * (y2 - y1); - // Add the outgoing shapes - this.getOutgoingShapes().each((function(followingShape){ - serializedObject.push({name: 'outgoing', prefix:'raziel', value: '#'+ERDF.__stripHashes(followingShape.resourceId), type: 'resource'}); - }).bind(this)); + if ((y1 >= pointY) != (y2 >= pointY)) { + crossings += y2 - y1 >= 0 ? d >= 0 : d <= 0; + } + if (!d && Math.min(x1, x2) <= pointX && pointX <= Math.max(x1, x2) + && Math.min(y1, y2) <= pointY && pointY <= Math.max(y1, y2)) { + return true; + } + } + return (crossings % 2) ? true : false; +} - // Add the parent shape, if the parent not the canvas - //if(this.parent instanceof ORYX.Core.Shape){ - serializedObject.push({name: 'parent', prefix:'raziel', value: '#'+ERDF.__stripHashes(this.parent.resourceId), type: 'resource'}); - //} - - return serializedObject; - }, - - - deserialize: function(serialize, json){ - arguments.callee.$.deserialize.apply(this, arguments); - - // Set the Bounds - var bounds = serialize.find(function(ser){ return 'oryx-bounds' === (ser.prefix+"-"+ser.name) }); - if (bounds) { - var b = bounds.value.replace(/,/g, " ").split(" ").without(""); - if (this instanceof ORYX.Core.Edge) { - if (!this.dockers.first().isChanged) - this.dockers.first().bounds.centerMoveTo(parseFloat(b[0]), parseFloat(b[1])); - if (!this.dockers.last().isChanged) - this.dockers.last().bounds.centerMoveTo(parseFloat(b[2]), parseFloat(b[3])); - } else { - this.bounds.set(parseFloat(b[0]), parseFloat(b[1]), parseFloat(b[2]), parseFloat(b[3])); - } - } - - if (json && json.labels instanceof Array){ - json.labels.each(function(slabel){ - var label = this.getLabel(slabel.ref); - if (label){ - label.deserialize(slabel, this); - } - }.bind(this)) - } - }, - - toJSON: function(){ - var json = arguments.callee.$.toJSON.apply(this, arguments); - - var labels = [], id = this.id; - this._labels.each(function(obj){ - var slabel = obj.value.serialize(); - if (slabel){ - slabel.ref = obj.key.replace(id, ''); - labels.push(slabel); - } - }); - - if (labels.length > 0){ - json.labels = labels; - } - return json; - }, - - - /** - * Private methods. - */ - - /** - * Child classes have to overwrite this method for initializing a loaded - * SVG representation. - * @param {SVGDocument} svgDocument - */ - _init: function(svgDocument) { - //adjust ids - this._adjustIds(svgDocument, 0); - }, - - _adjustIds: function(element, idIndex) { - if(element instanceof Element) { - var eid = element.getAttributeNS(null, 'id'); - if(eid && eid !== "") { - element.setAttributeNS(null, 'id', this.id + eid); - } else { - element.setAttributeNS(null, 'id', this.id + "_" + this.id + "_" + idIndex); - idIndex++; - } - - // Replace URL in fill attribute - var fill = element.getAttributeNS(null, 'fill'); - if (fill&&fill.include("url(#")){ - fill = fill.replace(/url\(#/g, 'url(#'+this.id); - element.setAttributeNS(null, 'fill', fill); - } - - if(element.hasChildNodes()) { - for(var i = 0; i < element.childNodes.length; i++) { - idIndex = this._adjustIds(element.childNodes[i], idIndex); - } - } - } - return idIndex; - }, +/** + * Calculates the distance between a point and a line. It is also testable, if + * the distance orthogonal to the line, matches the segment of the line. + * + * @param {float} lineP1 + * The starting point of the line segment + * @param {float} lineP2 + * The end point of the line segment + * @param {Point} point + * The point to calculate the distance to. + * @param {boolean} toSegmentOnly + * Flag to signal if only the segment of the line shell be evaluated. + */ +ORYX.Core.Math.distancePointLinie = function ( + lineP1, + lineP2, + point, + toSegmentOnly) { + + var intersectionPoint = + ORYX.Core.Math.getPointOfIntersectionPointLine(lineP1, + lineP2, + point, + toSegmentOnly); + + if (!intersectionPoint) { + return null; + } - toString: function() { return "ORYX.Core.Shape " + this.getId() } + return ORYX.Core.Math.getDistancePointToPoint(point, intersectionPoint); }; -ORYX.Core.Shape = ORYX.Core.AbstractShape.extend(ORYX.Core.Shape);/* - * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. - * License rights for this program may be obtained from Alfresco Software, Ltd. - * pursuant to a written agreement and any use of this program without such an - * agreement is prohibited. - */ -/* - * All code Copyright 2013 KIS Consultancy all rights reserved + +/** + * Calculates the distance between two points. + * + * @param {point} point1 + * @param {point} point2 */ +ORYX.Core.Math.getDistancePointToPoint = function (point1, point2) { + return Math.sqrt(Math.pow(point1.x - point2.x, 2) + Math.pow(point1.y - point2.y, 2)); +}; /** - * Init namespaces + * Calculates the relative distance of a point which is between two other points. + * + * @param {point} between1 + * @param {point} between2 + * @param {point} point */ -if(!ORYX) {var ORYX = {};} -if(!ORYX.Core) {ORYX.Core = {};} -if(!ORYX.Core.Controls) {ORYX.Core.Controls = {};} +ORYX.Core.Math.getDistanceBetweenTwoPoints = function (between1, between2, point) { + return ORYX.Core.Math.getDistancePointToPoint(point, between1) / + ORYX.Core.Math.getDistancePointToPoint(between1, between2); +}; /** - * @classDescription Abstract base class for all Controls. - */ -ORYX.Core.Controls.Control = ORYX.Core.UIObject.extend({ - - toString: function() { return "Control " + this.id; } - });/* - * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. - * License rights for this program may be obtained from Alfresco Software, Ltd. - * pursuant to a written agreement and any use of this program without such an - * agreement is prohibited. - */ -/* - * All code Copyright 2013 KIS Consultancy all rights reserved + * Returns true, if the point is of the left hand + * side of the regarding the line. + * + * @param {point} lineP1 Line first point + * @param {point} lineP2 Line second point + * @param {point} point */ +ORYX.Core.Math.pointIsLeftOfLine = function (lineP1, lineP2, point) { + + var vec1 = ORYX.Core.Math.getVector(lineP1, lineP2); + var vec2 = ORYX.Core.Math.getVector(lineP1, point); + // if the cross produkt is more than 0 + return ((vec1.x * vec2.y) - (vec2.x * vec1.y)) > 0 +}; /** - * Init namespaces + * Calculates the a point which is relatively between two other points. + * + * @param {point} point1 + * @param {point} point2 + * @param {number} relative Relative which is between 0 and 1 */ -if(!ORYX) {var ORYX = {};} -if(!ORYX.Core) {ORYX.Core = {};} -if(!ORYX.Core.Controls) {ORYX.Core.Controls = {};} +ORYX.Core.Math.getPointBetweenTwoPoints = function (point1, point2, relative) { + relative = Math.max(Math.min(relative || 0, 1), 0); + + if (relative === 0) { + return point1; + } else if (relative === 1) { + return point2; + } + + return { + x: point1.x + ((point2.x - point1.x) * relative), + y: point1.y + ((point2.y - point1.y) * relative) + } +}; /** - * @classDescription Represents a movable docker that can be bound to a shape. Dockers are used - * for positioning shape objects. - * @extends {Control} - * - * TODO absoluteXY und absoluteCenterXY von einem Docker liefern falsche Werte!!! + * Returns the vector of the both points + * + * @param {point} point1 + * @param {point} point2 */ -ORYX.Core.Controls.Docker = ORYX.Core.Controls.Control.extend({ - /** - * Constructor - */ - construct: function() { - arguments.callee.$.construct.apply(this, arguments); - - this.isMovable = true; // Enables movability - this.bounds.set(0, 0, 16, 16); // Set the bounds - this.referencePoint = undefined; // Refrenzpoint - this._dockedShapeBounds = undefined; - this._dockedShape = undefined; - this._oldRefPoint1 = undefined; - this._oldRefPoint2 = undefined; - - //this.anchors = []; - this.anchorLeft; - this.anchorRight; - this.anchorTop; - this.anchorBottom; - - this.node = ORYX.Editor.graft("http://www.w3.org/2000/svg", - null, - ['g']); - - // The DockerNode reprasentation - 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"}] - ]); - - // The ReferenzNode reprasentation - 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}]]); - - // Hide the Docker - this.hide(); - - //Add to the EventHandler - this.addEventHandlers(this._dockerNode); - - // Buffer the Update Callback for un-/register on Event-Handler - this._updateCallback = this._changed.bind(this); - }, - - update: function() { - // If there have an DockedShape - if(this._dockedShape) { - if(this._dockedShapeBounds && this._dockedShape instanceof ORYX.Core.Node) { - // Calc the delta of width and height of the lastBounds and the current Bounds - var dswidth = this._dockedShapeBounds.width(); - var dsheight = this._dockedShapeBounds.height(); - if(!dswidth) - dswidth = 1; - if(!dsheight) - dsheight = 1; - var widthDelta = this._dockedShape.bounds.width() / dswidth; - var heightDelta = this._dockedShape.bounds.height() / dsheight; - - // If there is an different - if(widthDelta !== 1.0 || heightDelta !== 1.0) { - // Set the delta - this.referencePoint.x *= widthDelta; - this.referencePoint.y *= heightDelta; - } - - // Clone these bounds - this._dockedShapeBounds = this._dockedShape.bounds.clone(); - } - - // Get the first and the last Docker of the parent Shape - var dockerIndex = this.parent.dockers.indexOf(this) - var dock1 = this; - var dock2 = this.parent.dockers.length > 1 ? - (dockerIndex === 0? // If there is the first element - this.parent.dockers[dockerIndex + 1]: // then take the next docker - this.parent.dockers[dockerIndex - 1]): // if not, then take the docker before - undefined; - - // Calculate the first absolute Refenzpoint - var absoluteReferenzPoint1 = dock1.getDockedShape() ? - dock1.getAbsoluteReferencePoint() : - dock1.bounds.center(); - - // Calculate the last absolute Refenzpoint - var absoluteReferenzPoint2 = dock2 && dock2.getDockedShape() ? - dock2.getAbsoluteReferencePoint() : - dock2 ? - dock2.bounds.center() : - undefined; - - // If there is no last absolute Referenzpoint - if(!absoluteReferenzPoint2) { - // Calculate from the middle of the DockedShape - var center = this._dockedShape.absoluteCenterXY(); - var minDimension = this._dockedShape.bounds.width() * this._dockedShape.bounds.height(); - absoluteReferenzPoint2 = { - x: absoluteReferenzPoint1.x + (center.x - absoluteReferenzPoint1.x) * -minDimension, - y: absoluteReferenzPoint1.y + (center.y - absoluteReferenzPoint1.y) * -minDimension - } - } - - var newPoint = undefined; - - /*if (!this._oldRefPoint1 || !this._oldRefPoint2 || - absoluteReferenzPoint1.x !== this._oldRefPoint1.x || - absoluteReferenzPoint1.y !== this._oldRefPoint1.y || - absoluteReferenzPoint2.x !== this._oldRefPoint2.x || - absoluteReferenzPoint2.y !== this._oldRefPoint2.y) {*/ - - // Get the new point for the Docker, calucalted by the intersection point of the Shape and the two points - newPoint = this._dockedShape.getIntersectionPoint(absoluteReferenzPoint1, absoluteReferenzPoint2); - - // If there is new point, take the referencepoint as the new point - if(!newPoint) { - newPoint = this.getAbsoluteReferencePoint(); - } - - if(this.parent && this.parent.parent) { - var grandParentPos = this.parent.parent.absoluteXY(); - newPoint.x -= grandParentPos.x; - newPoint.y -= grandParentPos.y; - } - - // Set the bounds to the new point - this.bounds.centerMoveTo(newPoint) - - this._oldRefPoint1 = absoluteReferenzPoint1; - this._oldRefPoint2 = absoluteReferenzPoint2; - } - /*else { - newPoint = this.bounds.center(); - }*/ - - - // } - - // Call the super class - arguments.callee.$.update.apply(this, arguments); - }, +ORYX.Core.Math.getVector = function (point1, point2) { + return { + x: point2.x - point1.x, + y: point2.y - point1.y + } +} - /** - * Calls the super class refresh method and updates the view of the docker. - */ - refresh: function() { - arguments.callee.$.refresh.apply(this, arguments); - - // Refresh the dockers node - var p = this.bounds.upperLeft(); - this._dockerNode.setAttributeNS(null, 'transform','translate(' + p.x + ', ' + p.y + ')'); - - // Refresh the referencepoints node - p = Object.clone(this.referencePoint); - - if(p && this._dockedShape){ - var upL - if(this.parent instanceof ORYX.Core.Edge) { - upL = this._dockedShape.absoluteXY(); - } else { - upL = this._dockedShape.bounds.upperLeft(); - } - p.x += upL.x; - p.y += upL.y; - } else { - p = this.bounds.center(); - } +/** + * Returns the an identity vector of the given vector, + * which has the length ot one. + * + * @param {point} vector + * or + * @param {point} point1 + * @param {point} point2 + */ +ORYX.Core.Math.getIdentityVector = function (vector) { - this._referencePointNode.setAttributeNS(null, 'transform','translate(' + p.x + ', ' + p.y + ')'); - }, + if (arguments.length == 2) { + vector = ORYX.Core.Math.getVector(arguments[0], arguments[1]); + } - /** - * Set the reference point - * @param {Object} point - */ - setReferencePoint: function(point) { - // Set the referencepoint - if(this.referencePoint !== point && - (!this.referencePoint || - !point || - this.referencePoint.x !== point.x || - this.referencePoint.y !== point.y)) { - - this.referencePoint = point; - this._changed(); - } + var length = Math.sqrt((vector.x * vector.x) + (vector.y * vector.y)) + return { + x: vector.x / (length || 1), + y: vector.y / (length || 1) + } +} - - // Update directly, because the referencepoint has no influence of the bounds - //this.refresh(); - }, - - /** - * Get the absolute referencepoint - */ - getAbsoluteReferencePoint: function() { - if(!this.referencePoint || !this._dockedShape) { - return undefined; - } else { - var absUL = this._dockedShape.absoluteXY(); - return { - x: this.referencePoint.x + absUL.x, - y: this.referencePoint.y + absUL.y - } - } - }, - - /** - * Set the docked Shape from the docker - * @param {Object} shape - */ - setDockedShape: function(shape) { - - // If there is an old docked Shape - if(this._dockedShape) { - this._dockedShape.bounds.unregisterCallback(this._updateCallback) - - // Delete the Shapes from the incoming and outgoing array - // If this Docker the incoming of the Shape - if(this === this.parent.dockers.first()) { - - this.parent.incoming = this.parent.incoming.without(this._dockedShape); - this._dockedShape.outgoing = this._dockedShape.outgoing.without(this.parent); - - // If this Docker the outgoing of the Shape - } 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); - - } - - } - - // Set the new Shape - this._dockedShape = shape; - this._dockedShapeBounds = undefined; - var referencePoint = undefined; - - // If there is an Shape, register the updateCallback if there are changes in the shape bounds - if(this._dockedShape) { - - // Add the Shapes to the incoming and outgoing array - // If this Docker the incoming of the Shape - if(this === this.parent.dockers.first()) { - - this.parent.incoming.push(shape); - shape.outgoing.push(this.parent); - - // If this Docker the outgoing of the Shape - } else if (this === this.parent.dockers.last()){ - - this.parent.outgoing.push(shape); - shape.incoming.push(this.parent); - - } - - // Get the bounds and set the new referencepoint - var bounds = this.bounds; - var absUL = shape.absoluteXY(); - - /*if(shape.parent){ - var b = shape.parent.bounds.upperLeft(); - absUL.x -= b.x; - absUL.y -= b.y; - }*/ - - referencePoint = { - x: bounds.center().x - absUL.x, - y: bounds.center().y - absUL.y - } - - this._dockedShapeBounds = this._dockedShape.bounds.clone(); - - this._dockedShape.bounds.registerCallback(this._updateCallback); - - // Set the color of the docker as docked - this.setDockerColor(ORYX.CONFIG.DOCKER_DOCKED_COLOR); - } else { - // Set the color of the docker as undocked - this.setDockerColor(ORYX.CONFIG.DOCKER_UNDOCKED_COLOR); - } +ORYX.Core.Math.getOrthogonalIdentityVector = function (point1, point2) { + var vec = arguments.length == 1 ? point1 : ORYX.Core.Math.getIdentityVector(point1, point2); + return { + x: vec.y, + y: -vec.x + } +} - // Set the referencepoint - this.setReferencePoint(referencePoint); - this._changed(); - //this.update(); - }, - - /** - * Get the docked Shape - */ - getDockedShape: function() { - return this._dockedShape; - }, - /** - * Returns TRUE if the docker has a docked shape - */ - isDocked: function() { - return !!this._dockedShape; - }, - - /** - * Set the Color of the Docker - * @param {Object} color - */ - setDockerColor: function(color) { - this._dockerNode.lastChild.setAttributeNS(null, "fill", color); - }, - - preventHiding: function(prevent){ - this._preventHiding = Math.max(0, (this._preventHiding||0) + (prevent ? 1 : -1)); - }, - - /** - * Hides this UIObject and all its children. - */ - hide: function() { - if (this._preventHiding){ - return false; - } - - // Hide docker and reference point - this.node.setAttributeNS(null, 'visibility', 'hidden'); - this._referencePointNode.setAttributeNS(null, 'visibility', 'hidden'); - - this.children.each(function(uiObj) { - uiObj.hide(); - }); - }, - - /** - * Enables visibility of this UIObject and all its children. - */ - show: function() { - // Show docker - this.node.setAttributeNS(null, 'visibility', 'visible'); - - // Hide reference point if the connected shape is an edge - if (this.getDockedShape() instanceof ORYX.Core.Edge){ - this._referencePointNode.setAttributeNS(null, 'visibility', 'hidden'); - } else { - this._referencePointNode.setAttributeNS(null, 'visibility', 'visible'); - } - - this.children.each(function(uiObj) { - uiObj.show(); - }); - }, - - toString: function() { return "Docker " + this.id } -});/* - * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. - * License rights for this program may be obtained from Alfresco Software, Ltd. - * pursuant to a written agreement and any use of this program without such an - * agreement is prohibited. - */ -/* - * All code Copyright 2013 KIS Consultancy all rights reserved +/** + * Returns the intersection point of a line and a point that defines a line + * orthogonal to the given line. + * + * @param {float} lineP1 + * The starting point of the line segment + * @param {float} lineP2 + * The end point of the line segment + * @param {Point} point + * The point to calculate the distance to. + * @param {boolean} onSegmentOnly + * Flag to signal if only the segment of the line shell be evaluated. */ +ORYX.Core.Math.getPointOfIntersectionPointLine = function ( + lineP1, + lineP2, + point, + onSegmentOnly) { + + /* + * [P3 - P1 - u(P2 - P1)] dot (P2 - P1) = 0 + * u =((x3-x1)(x2-x1)+(y3-y1)(y2-y1))/(p2-p1)?? + */ + var denominator = Math.pow(lineP2.x - lineP1.x, 2) + + Math.pow(lineP2.y - lineP1.y, 2); + if (denominator == 0) { + return undefined; + } + + var u = ((point.x - lineP1.x) * (lineP2.x - lineP1.x) + + (point.y - lineP1.y) * (lineP2.y - lineP1.y)) + / denominator; + + if (onSegmentOnly) { + if (!(0 <= u && u <= 1)) { + return undefined; + } + } + + pointOfIntersection = new Object(); + pointOfIntersection.x = lineP1.x + u * (lineP2.x - lineP1.x); + pointOfIntersection.y = lineP1.y + u * (lineP2.y - lineP1.y); + + return pointOfIntersection; +}; /** - * Init namespaces + * Translated the point with the given matrix. + * @param {Point} point + * @param {Matrix} matrix + * @return {Object} Includes x, y */ -if(!ORYX) {var ORYX = {};} -if(!ORYX.Core) {ORYX.Core = {};} -if(!ORYX.Core.Controls) {ORYX.Core.Controls = {};} +ORYX.Core.Math.getTranslatedPoint = function (point, matrix) { + var x = matrix.a * point.x + matrix.c * point.y + matrix.e * 1; + var y = matrix.b * point.x + matrix.d * point.y + matrix.f * 1; + return {x: x, y: y} +} /** - * @classDescription Represents a magnet that is part of another shape and can - * be attached to dockers. Magnets are used for linking edge objects - * to other Shape objects. - * @extends {Control} + * Returns the inverse matrix of the given SVG transformation matrix + * @param {SVGTransformationMatrix} matrix + * @return {Matrix} */ -ORYX.Core.Controls.Magnet = ORYX.Core.Controls.Control.extend({ - - /** - * Constructor - */ - construct: function() { - arguments.callee.$.construct.apply(this, arguments); - - //this.anchors = []; - this.anchorLeft; - this.anchorRight; - this.anchorTop; - this.anchorBottom; - - this.bounds.set(0, 0, 16, 16); - - //graft magnet's root node into owner's control group. - 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); - - //this.isChanged = true; - }, - - _update: function() { - arguments.callee.$.update.apply(this, arguments); - - //this.isChanged = true; - }, - - refresh: function() { - arguments.callee.$.refresh.apply(this, arguments); +ORYX.Core.Math.getInverseMatrix = function (matrix) { + + var det = ORYX.Core.Math.getDeterminant(matrix), m = matrix; + // +- -+ + // | a c e | + // | b d f | + // | 0 0 1 | + // +- -+ + return { + a: det * ((m.d * 1) - (m.f * 0)), + b: det * ((m.f * 0) - (m.b * 1)), + c: det * ((m.e * 0) - (m.c * 1)), + d: det * ((m.a * 1) - (m.e * 0)), + e: det * ((m.c * m.f) - (m.e * m.d)), + f: det * ((m.e * m.b) - (m.a * m.f)) + } +} - var p = this.bounds.upperLeft(); - /*if(this.parent) { - var parentPos = this.parent.bounds.upperLeft(); - p.x += parentPos.x; - p.y += parentPos.y; - }*/ - - this.node.setAttributeNS(null, 'transform','translate(' + p.x + ', ' + p.y + ')'); - }, - - show: function() { - //this.refresh(); - arguments.callee.$.show.apply(this, arguments); - }, - - toString: function() { - return "Magnet " + this.id; - } -}); -/* - * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. - * License rights for this program may be obtained from Alfresco Software, Ltd. - * pursuant to a written agreement and any use of this program without such an - * agreement is prohibited. +/** + * Returns the determinant of the svg transformation matrix + * @param {SVGTranformationMatrix} matrix + * @return {Number} + * */ -/* - * All code Copyright 2013 KIS Consultancy all rights reserved +ORYX.Core.Math.getDeterminant = function (m) { + // a11a22a33+a12a23a31+a13a21a32-a13a22a31-a12a21a33-a11a23a32 + return (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); +} + +/** + * Returns the bounding box of the given node. Translates the + * origin bounding box with the tranlation matrix. + * @param {SVGElement} node + * @return {Object} Includes x, y, width, height */ +ORYX.Core.Math.getTranslatedBoundingBox = function (node) { + var matrix = node.getCTM(); + var bb = node.getBBox(); + var ul = ORYX.Core.Math.getTranslatedPoint({x: bb.x, y: bb.y}, matrix); + var ll = ORYX.Core.Math.getTranslatedPoint({x: bb.x, y: bb.y + bb.height}, matrix); + var ur = ORYX.Core.Math.getTranslatedPoint({x: bb.x + bb.width, y: bb.y}, matrix); + var lr = ORYX.Core.Math.getTranslatedPoint({x: bb.x + bb.width, y: bb.y + bb.height}, matrix); + + var minPoint = { + x: Math.min(ul.x, ll.x, ur.x, lr.x), + y: Math.min(ul.y, ll.y, ur.y, lr.y) + } + var maxPoint = { + x: Math.max(ul.x, ll.x, ur.x, lr.x), + y: Math.max(ul.y, ll.y, ur.y, lr.y) + } + return { + x: minPoint.x, + y: minPoint.y, + width: maxPoint.x - minPoint.x, + height: maxPoint.y - minPoint.y + } +}; + /** - * Init namespaces + * Returns the angle of the given line, which is representated by the two points + * @param {Point} p1 + * @param {Point} p2 + * @return {Number} 0 <= x <= 359.99999 */ -if (!ORYX) { - var ORYX = {}; -} -if (!ORYX.Core) { - ORYX.Core = {}; -} +ORYX.Core.Math.getAngle = function (p1, p2) { + if (p1.x == p2.x && p1.y == p2.y) + return 0; + + var angle = Math.asin(Math.sqrt(Math.pow(p1.y - p2.y, 2)) + / (Math.sqrt(Math.pow(p2.x - p1.x, 2) + Math.pow(p1.y - p2.y, 2)))) + * 180 / Math.PI; + + if (p2.x >= p1.x && p2.y <= p1.y) + return angle; + else if (p2.x < p1.x && p2.y <= p1.y) + return 180 - angle; + else if (p2.x < p1.x && p2.y > p1.y) + return 180 + angle; + else + return 360 - angle; +}; + /** - * @classDescription Abstract base class for all Nodes. - * @extends ORYX.Core.Shape + * Implementation of the cohen-sutherland algorithm */ -ORYX.Core.Node = { +new function () { + + var RIGHT = 2, TOP = 8, BOTTOM = 4, LEFT = 1; + + function computeOutCode(x, y, xmin, ymin, xmax, ymax) { + var code = 0; + if (y > ymax) + code |= TOP; + else if (y < ymin) + code |= BOTTOM; + if (x > xmax) + code |= RIGHT; + else if (x < xmin) + code |= LEFT; + return code; + } /** - * Constructor - * @param options {Object} A container for arguments. - * @param stencil {Stencil} + * Returns TRUE if the rectangle is over the edge and has intersection points or includes it + * @param {Object} x1 Point A of the line + * @param {Object} y1 + * @param {Object} x2 Point B of the line + * @param {Object} y2 + * @param {Object} xmin Point A of the rectangle + * @param {Object} ymin + * @param {Object} xmax Point B of the rectangle + * @param {Object} ymax */ - construct: function(options, stencil, facade){ - arguments.callee.$.construct.apply(this, arguments); - - this.isSelectable = true; - this.isMovable = true; - this._dockerUpdated = false; - this.facade = facade; - - this._oldBounds = new ORYX.Core.Bounds(); //init bounds with undefined values - this._svgShapes = []; //array of all SVGShape objects of - // SVG representation - - //TODO vielleicht in shape verschieben? - this.minimumSize = undefined; // {width:..., height:...} - this.maximumSize = undefined; - - //TODO vielleicht in shape oder uiobject verschieben? - // vielleicht sogar isResizable ersetzen? - this.isHorizontallyResizable = false; - this.isVerticallyResizable = false; - - this.dataId = undefined; - - this._init(this._stencil.view()); - this.forcedHeight = -1; - }, - - /** - * This method checks whether the shape is resized correctly and calls the - * super class update method. - */ - _update: function(){ - - this.dockers.invoke("update"); - if (this.isChanged) { + ORYX.Core.Math.isRectOverLine = function (x1, y1, x2, y2, xmin, ymin, xmax, ymax) { + return !!ORYX.Core.Math.clipLineOnRect.apply(ORYX.Core.Math, arguments); + } - var bounds = this.bounds; - var oldBounds = this._oldBounds; - - if (this.isResized) { - - var widthDelta = bounds.width() / oldBounds.width(); - var heightDelta = bounds.height() / oldBounds.height(); - - //iterate over all relevant svg elements and resize them - this._svgShapes.each(function(svgShape){ - //adjust width - if (svgShape.isHorizontallyResizable) { - svgShape.width = svgShape.oldWidth * widthDelta; - } - //adjust height - if (svgShape.isVerticallyResizable) { - svgShape.height = svgShape.oldHeight * heightDelta; - } - - //check, if anchors are set - var anchorOffset; - var leftIncluded = svgShape.anchorLeft; - var rightIncluded = svgShape.anchorRight; - - if (rightIncluded) { - anchorOffset = oldBounds.width() - (svgShape.oldX + svgShape.oldWidth); - if (leftIncluded) { - svgShape.width = bounds.width() - svgShape.x - anchorOffset; - } - else { - svgShape.x = bounds.width() - (anchorOffset + svgShape.width); - } - } - else - if (!leftIncluded) { - svgShape.x = widthDelta * svgShape.oldX; - if (!svgShape.isHorizontallyResizable) { - svgShape.x = svgShape.x + svgShape.width * widthDelta / 2 - svgShape.width / 2; - } - } - - var topIncluded = svgShape.anchorTop; - var bottomIncluded = svgShape.anchorBottom; - - if (bottomIncluded) { - anchorOffset = oldBounds.height() - (svgShape.oldY + svgShape.oldHeight); - if (topIncluded) { - svgShape.height = bounds.height() - svgShape.y - anchorOffset; - } - else { - // Hack for choreography task layouting - if (!svgShape._isYLocked) { - svgShape.y = bounds.height() - (anchorOffset + svgShape.height); - } - } - } - else - if (!topIncluded) { - svgShape.y = heightDelta * svgShape.oldY; - if (!svgShape.isVerticallyResizable) { - svgShape.y = svgShape.y + svgShape.height * heightDelta / 2 - svgShape.height / 2; - } - } - }); - - //check, if the current bounds is unallowed horizontally or vertically resized - var p = { - x: 0, - y: 0 - }; - if (!this.isHorizontallyResizable && bounds.width() !== oldBounds.width()) { - p.x = oldBounds.width() - bounds.width(); - } - if (!this.isVerticallyResizable && bounds.height() !== oldBounds.height()) { - p.y = oldBounds.height() - bounds.height(); - } - if (p.x !== 0 || p.y !== 0) { - bounds.extend(p); - } - - //check, if the current bounds are between maximum and minimum bounds - p = { - x: 0, - y: 0 - }; - var widthDifference, heightDifference; - if (this.minimumSize) { - - ORYX.Log.debug("Shape (%0)'s min size: (%1x%2)", this, this.minimumSize.width, this.minimumSize.height); - widthDifference = this.minimumSize.width - bounds.width(); - if (widthDifference > 0) { - p.x += widthDifference; - } - heightDifference = this.minimumSize.height - bounds.height(); - if (heightDifference > 0) { - p.y += heightDifference; - } - } - if (this.maximumSize) { - - ORYX.Log.debug("Shape (%0)'s max size: (%1x%2)", this, this.maximumSize.width, this.maximumSize.height); - widthDifference = bounds.width() - this.maximumSize.width; - if (widthDifference > 0) { - p.x -= widthDifference; - } - heightDifference = bounds.height() - this.maximumSize.height; - if (heightDifference > 0) { - p.y -= heightDifference; - } - } - if (p.x !== 0 || p.y !== 0) { - bounds.extend(p); - } - - //update magnets - - var widthDelta = bounds.width() / oldBounds.width(); - var heightDelta = bounds.height() / oldBounds.height(); - - var leftIncluded, rightIncluded, topIncluded, bottomIncluded, center, newX, newY; - - this.magnets.each(function(magnet){ - leftIncluded = magnet.anchorLeft; - rightIncluded = magnet.anchorRight; - topIncluded = magnet.anchorTop; - bottomIncluded = magnet.anchorBottom; - - center = magnet.bounds.center(); - - if (leftIncluded) { - newX = center.x; - } - else - if (rightIncluded) { - newX = bounds.width() - (oldBounds.width() - center.x) - } - else { - newX = center.x * widthDelta; - } - - if (topIncluded) { - newY = center.y; - } - else - if (bottomIncluded) { - newY = bounds.height() - (oldBounds.height() - center.y); - } - else { - newY = center.y * heightDelta; - } - - if (center.x !== newX || center.y !== newY) { - magnet.bounds.centerMoveTo(newX, newY); - } - }); - - //set new position of labels - this.getLabels().each(function(label){ - // Set the position dependings on it anchor - if (!label.isAnchorLeft()) { - if (label.isAnchorRight()) { - label.setX(bounds.width() - (oldBounds.width() - label.oldX)) - } else { - label.setX((label.position?label.position.x:label.x) * widthDelta); - } - } - if (!label.isAnchorTop()) { - if (label.isAnchorBottom()) { - label.setY(bounds.height() - (oldBounds.height() - label.oldY)); - } else { - label.setY((label.position?label.position.y:label.y) * heightDelta); - } - } - - // If there is an position, - // set the origin position as well - if (label.position){ - if (!label.isOriginAnchorLeft()) { - if (label.isOriginAnchorRight()) { - label.setOriginX(bounds.width() - (oldBounds.width() - label.oldX)) - } else { - label.setOriginX(label.x * widthDelta); - } - } - if (!label.isOriginAnchorTop()) { - if (label.isOriginAnchorBottom()) { - label.setOriginY(bounds.height() - (oldBounds.height() - label.oldY)); - } else { - label.setOriginY(label.y * heightDelta); - } - } - } - }); - - //update docker - var docker = this.dockers[0]; - if (docker) { - docker.bounds.unregisterCallback(this._dockerChangedCallback); - if (!this._dockerUpdated) { - docker.bounds.centerMoveTo(this.bounds.center()); - this._dockerUpdated = false; - } - - docker.update(); - docker.bounds.registerCallback(this._dockerChangedCallback); - } - this.isResized = false; - } - - this.refresh(); - - this.isChanged = false; - - this._oldBounds = this.bounds.clone(); - } - - this.children.each(function(value) { - if(!(value instanceof ORYX.Core.Controls.Docker)) { - value._update(); - } - }); - - if (this.dockers.length > 0&&!this.dockers.first().getDockedShape()) { - this.dockers.each(function(docker){ - docker.bounds.centerMoveTo(this.bounds.center()) - }.bind(this)) - } - - /*this.incoming.each((function(edge) { - if(!(this.dockers[0] && this.dockers[0].getDockedShape() instanceof ORYX.Core.Node)) - edge._update(true); - }).bind(this)); - - this.outgoing.each((function(edge) { - if(!(this.dockers[0] && this.dockers[0].getDockedShape() instanceof ORYX.Core.Node)) - edge._update(true); - }).bind(this)); */ - }, - - /** - * This method repositions and resizes the SVG representation - * of the shape. - */ - refresh: function(){ - arguments.callee.$.refresh.apply(this, arguments); - - /** Movement */ - var x = this.bounds.upperLeft().x; - var y = this.bounds.upperLeft().y; - - // Move owner element - this.node.firstChild.setAttributeNS(null, "transform", "translate(" + x + ", " + y + ")"); - // Move magnets - this.node.childNodes[1].childNodes[1].setAttributeNS(null, "transform", "translate(" + x + ", " + y + ")"); - - /** Resize */ - - //iterate over all relevant svg elements and update them - this._svgShapes.each(function(svgShape){ - svgShape.update(); - }); - }, - - _dockerChanged: function(){ - var docker = this.dockers[0]; - - //set the bounds of the the association - this.bounds.centerMoveTo(docker.bounds.center()); - - this._dockerUpdated = true; - //this._update(true); - }, - /** - * This method traverses a tree of SVGElements and returns - * all SVGShape objects. For each basic shape or path element - * a SVGShape object is initialized. + * Returns the clipped line on the given rectangle. If there is + * no intersection, it will return NULL. * - * @param svgNode {SVGElement} - * @return {Array} Array of SVGShape objects + * @param {Object} x1 Point A of the line + * @param {Object} y1 + * @param {Object} x2 Point B of the line + * @param {Object} y2 + * @param {Object} xmin Point A of the rectangle + * @param {Object} ymin + * @param {Object} xmax Point B of the rectangle + * @param {Object} ymax */ - _initSVGShapes: function(svgNode){ - var svgShapes = []; - try { - var svgShape = new ORYX.Core.SVG.SVGShape(svgNode); - svgShapes.push(svgShape); - } - catch (e) { - //do nothing - } - - if (svgNode.hasChildNodes()) { - for (var i = 0; i < svgNode.childNodes.length; i++) { - svgShapes = svgShapes.concat(this._initSVGShapes(svgNode.childNodes[i])); + ORYX.Core.Math.clipLineOnRect = function (x1, y1, x2, y2, xmin, ymin, xmax, ymax) { + //Outcodes for P0, P1, and whatever point lies outside the clip rectangle + var outcode0, outcode1, outcodeOut, hhh = 0; + var accept = false, done = false; + + //compute outcodes + outcode0 = computeOutCode(x1, y1, xmin, ymin, xmax, ymax); + outcode1 = computeOutCode(x2, y2, xmin, ymin, xmax, ymax); + + do { + if ((outcode0 | outcode1) == 0) { + accept = true; + done = true; + } else if ((outcode0 & outcode1) > 0) { + done = true; + } else { + //failed both tests, so calculate the line segment to clip + //from an outside point to an intersection with clip edge + var x = 0, y = 0; + //At least one endpoint is outside the clip rectangle; pick it. + outcodeOut = outcode0 != 0 ? outcode0 : outcode1; + //Now find the intersection point; + //use formulas y = y0 + slope * (x - x0), x = x0 + (1/slope)* (y - y0) + if ((outcodeOut & TOP) > 0) { + x = x1 + (x2 - x1) * (ymax - y1) / (y2 - y1); + y = ymax; + } else if ((outcodeOut & BOTTOM) > 0) { + x = x1 + (x2 - x1) * (ymin - y1) / (y2 - y1); + y = ymin; + } else if ((outcodeOut & RIGHT) > 0) { + y = y1 + (y2 - y1) * (xmax - x1) / (x2 - x1); + x = xmax; + } else if ((outcodeOut & LEFT) > 0) { + y = y1 + (y2 - y1) * (xmin - x1) / (x2 - x1); + x = xmin; + } + + //Now we move outside point to intersection point to clip + //and get ready for next pass. + if (outcodeOut == outcode0) { + x1 = x; + y1 = y; + outcode0 = computeOutCode(x1, y1, xmin, ymin, xmax, ymax); + } else { + x2 = x; + y2 = y; + outcode1 = computeOutCode(x2, y2, xmin, ymin, xmax, ymax); + } } + hhh++; + } while (done != true && hhh < 5000); + + if (accept) { + return {a: {x: x1, y: y1}, b: {x: x2, y: y2}}; } - - return svgShapes; - }, - - /** - * Calculate if the point is inside the Shape - * @param {PointX} - * @param {PointY} - * @param {absoluteBounds} optional: for performance - */ - isPointIncluded: function(pointX, pointY, absoluteBounds){ - // If there is an arguments with the absoluteBounds - var absBounds = absoluteBounds && absoluteBounds instanceof ORYX.Core.Bounds ? absoluteBounds : this.absoluteBounds(); - - if (!absBounds.isIncluded(pointX, pointY)) { - return false; - } else { - - } - - - //point = Object.clone(point); - var ul = absBounds.upperLeft(); - var x = pointX - ul.x; - var y = pointY - ul.y; - - var i=0; - do { - var isPointIncluded = this._svgShapes[i++].isPointIncluded( x, y ); - } while( !isPointIncluded && i < this._svgShapes.length) - - return isPointIncluded; + return null; + } +}(); + + +/* + * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +/* + * All code Copyright 2013 KIS Consultancy all rights reserved + */ + +/** + * Init namespace + */ +if (!ORYX) { + var ORYX = {}; +} +if (!ORYX.Core) { + ORYX.Core = {}; +} +if (!ORYX.Core.StencilSet) { + ORYX.Core.StencilSet = {}; +} + +/** + * Class Stencil + * uses Prototpye 1.5.0 + * uses Inheritance + * + * This class represents one stencil of a stencil set. + */ +ORYX.Core.StencilSet.Stencil = { - /*return this._svgShapes.any(function(svgShape){ - return svgShape.isPointIncluded(point); - });*/ - }, - - /** - * Calculate if the point is over an special offset area - * @param {Point} + * Constructor */ - isPointOverOffset: function( pointX, pointY ){ - var isOverEl = arguments.callee.$.isPointOverOffset.apply( this , arguments ); - - if (isOverEl) { - - // If there is an arguments with the absoluteBounds - var absBounds = this.absoluteBounds(); - absBounds.widen( - ORYX.CONFIG.BORDER_OFFSET ); - - if ( !absBounds.isIncluded( pointX, pointY )) { - return true; - } - } - - return false; - - }, - - serialize: function(){ - var result = arguments.callee.$.serialize.apply(this); - - // Add the docker's bounds - // nodes only have at most one docker! - this.dockers.each((function(docker){ - if (docker.getDockedShape()) { - var center = docker.referencePoint; - center = center ? center : docker.bounds.center(); - result.push({ - name: 'docker', - prefix: 'oryx', - value: $H(center).values().join(','), - type: 'literal' - }); - } + construct: function (jsonStencil, namespace, source, stencilSet, propertyPackages, defaultPosition) { + arguments.callee.$.construct.apply(this, arguments); // super(); + + // check arguments and set defaults. + if (!jsonStencil) throw "Stencilset seems corrupt."; + if (!namespace) throw "Stencil does not provide namespace."; + if (!source) throw "Stencil does not provide SVG source."; + if (!stencilSet) throw "Fatal internal error loading stencilset."; + //if(!propertyPackages) throw "Fatal internal error loading stencilset."; + + this._source = source; + this._jsonStencil = jsonStencil; + this._stencilSet = stencilSet; + this._namespace = namespace; + this._propertyPackages = propertyPackages; + + if (defaultPosition && !this._jsonStencil.position) + this._jsonStencil.position = defaultPosition; + + this._view; + this._properties = new Hash(); + + // check stencil consistency and set defaults. + /*with(this._jsonStencil) { + + if(!type) throw "Stencil does not provide type."; + if((type != "edge") && (type != "node")) + throw "Stencil type must be 'edge' or 'node'."; + if(!id || id == "") throw "Stencil does not provide valid id."; + if(!title || title == "") + throw "Stencil does not provide title"; + if(!description) { description = ""; }; + if(!groups) { groups = []; } + if(!roles) { roles = []; } + + // add id of stencil to its roles + roles.push(id); + }*/ + + //init all JSON values + 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 = []; + } + + //add id of stencil to its roles + this._jsonStencil.roles.push(this._jsonStencil.id); + + //prepend namespace to each role + this._jsonStencil.roles.each((function (role, index) { + this._jsonStencil.roles[index] = namespace + role; }).bind(this)); - - // Get the spezific serialized object from the stencil - try { - //result = this.getStencil().serialize(this, result); - var serializeEvent = this.getStencil().serialize(); - - /* - * call serialize callback by reference, result should be found - * in serializeEvent.result - */ - if(serializeEvent.type) { - serializeEvent.shape = this; - serializeEvent.data = result; - serializeEvent.result = undefined; - serializeEvent.forceExecution = true; - - this._delegateEvent(serializeEvent); - - if(serializeEvent.result) { - result = serializeEvent.result; - } - } - } - catch (e) { + //delete duplicate roles + this._jsonStencil.roles = this._jsonStencil.roles.uniq(); + + //make id unique by prepending namespace of stencil set + this._jsonStencil.id = namespace + this._jsonStencil.id; + + this.postProcessProperties(); + + // init serialize callback + if (!this._jsonStencil.serialize) { + this._jsonStencil.serialize = {}; + //this._jsonStencil.serialize = function(shape, data) { return data;}; } - return result; - }, - - deserialize: function(data){ - arguments.callee.$.deserialize.apply(this, arguments); - - try { - //data = this.getStencil().deserialize(this, data); - var deserializeEvent = this.getStencil().deserialize(); - - /* - * call serialize callback by reference, result should be found - * in serializeEventInfo.result - */ - if(deserializeEvent.type) { - deserializeEvent.shape = this; - deserializeEvent.data = data; - deserializeEvent.result = undefined; - deserializeEvent.forceExecution = true; - - this._delegateEvent(deserializeEvent); - if(deserializeEvent.result) { - data = deserializeEvent.result; - } - } - } - catch (e) { - } - - // Set the outgoing shapes - var outgoing = data.findAll(function(ser){ return (ser.prefix+"-"+ser.name) == 'raziel-outgoing'}); - outgoing.each((function(obj){ - // TODO: Look at Canvas - if(!this.parent) {return}; - - // Set outgoing Shape - var next = this.getCanvas().getChildShapeByResourceId(obj.value); - - if(next){ - if(next instanceof ORYX.Core.Edge) { - //Set the first docker of the next shape - next.dockers.first().setDockedShape(this); - next.dockers.first().setReferencePoint(next.dockers.first().bounds.center()); - } else if(next.dockers.length > 0) { //next is a node and next has a docker - next.dockers.first().setDockedShape(this); - //next.dockers.first().setReferencePoint({x: this.bounds.width() / 2.0, y: this.bounds.height() / 2.0}); - } - } - - }).bind(this)); - - if (this.dockers.length === 1) { - var dockerPos; - dockerPos = data.find(function(entry){ - return (entry.prefix + "-" + entry.name === "oryx-dockers"); - }); - - if (dockerPos) { - var points = dockerPos.value.replace(/,/g, " ").split(" ").without("").without("#"); - if (points.length === 2 && this.dockers[0].getDockedShape()) { - this.dockers[0].setReferencePoint({ - x: parseFloat(points[0]), - y: parseFloat(points[1]) - }); - } - else { - this.dockers[0].bounds.centerMoveTo(parseFloat(points[0]), parseFloat(points[1])); - } + // init deserialize callback + if (!this._jsonStencil.deserialize) { + this._jsonStencil.deserialize = {}; + //this._jsonStencil.deserialize = function(shape, data) { return data;}; + } + + // init layout callback + if (!this._jsonStencil.layout) { + this._jsonStencil.layout = [] + //this._jsonStencil.layout = function() {return true;} + } + + //TODO does not work correctly, if the url does not exist + //How to guarantee that the view is loaded correctly before leaving the constructor??? + var url = source + "view/" + jsonStencil.view; + // override content type when this is webkit. + + if (this._jsonStencil.view.trim().match(/ 0); + }, + + getRepositoryEntries: function () { + return (this._jsonStencil.repositoryEntries) ? + $A(this._jsonStencil.repositoryEntries) : $A([]); + }, + + properties: function () { + return this._properties.values(); + }, + + property: function (id) { + return this._properties[id]; + }, + + roles: function () { + return this._jsonStencil.roles; + }, + + defaultAlign: function () { + if (!this._jsonStencil.defaultAlign) + return "east"; + return this._jsonStencil.defaultAlign; + }, + + serialize: function (shape, data) { + return this._jsonStencil.serialize; + //return this._jsonStencil.serialize(shape, data); + }, + + deserialize: function (shape, data) { + return this._jsonStencil.deserialize; + //return this._jsonStencil.deserialize(shape, data); + }, + + // in which case is targetShape used? +// layout: function(shape, targetShape) { +// return this._jsonStencil.layout(shape, targetShape); +// }, + // layout property to store events for layouting in plugins + layout: function (shape) { + return this._jsonStencil.layout + }, + + addProperty: function (property, namespace) { + if (property && namespace) { + var oProp = new ORYX.Core.StencilSet.Property(property, namespace, this); + this._properties[oProp.prefix() + "-" + oProp.id()] = oProp; + } + }, + + removeProperty: function (propertyId) { + if (propertyId) { + var oProp = this._properties.values().find(function (prop) { + return (propertyId == prop.id()); + }); + if (oProp) + delete this._properties[oProp.prefix() + "-" + oProp.id()]; + } + }, + + _loadSVGOnSuccess: function (result) { + + var xml = null; + + /* + * We want to get a dom object for the requested file. Unfortunately, + * safari has some issues here. this is meant as a fallback for all + * browsers that don't recognize the svg mimetype as XML but support + * data: urls on Ajax calls. + */ + + // responseXML != undefined. + // if(!(result.responseXML)) + + // get the dom by data: url. + // xml = _evenMoreEvilHack(result.responseText, 'text/xml'); + + // else + + // get it the usual way. + xml = result.responseXML; + + //check if result is a SVG document + if (ORYX.Editor.checkClassType(xml.documentElement, SVGSVGElement)) { + + this._view = xml.documentElement; + + } else { + throw "ORYX.Core.StencilSet.Stencil(_loadSVGOnSuccess): The response is not a SVG document." + } + }, + + _loadSVGOnFailure: function (result) { + 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); + +/** + * Transform a string into an xml document, the Safari way, as long as + * the nightlies are broken. Even more evil version. + * @param {Object} str + * @param {Object} contentType + */ +function _evenMoreEvilHack(str, contentType) { + + /* + * This even more evil hack was taken from + * http://web-graphics.com/mtarchive/001606.php#chatty004999 + */ + + if (window.ActiveXObject) { + var d = new ActiveXObject("MSXML.DomDocument"); + d.loadXML(str); + return d; + } else if (window.XMLHttpRequest) { + var req = new XMLHttpRequest; + req.open("GET", "data:" + (contentType || "application/xml") + + ";charset=utf-8," + encodeURIComponent(str), false); + if (req.overrideMimeType) { + req.overrideMimeType(contentType); + } + req.send(null); + return req.responseXML; + } +} + +/** + * Transform a string into an xml document, the Safari way, as long as + * the nightlies are broken. + * @param {Object} result the xml document object. + */ +function _evilSafariHack(serializedXML) { + + /* + * The Dave way. Taken from: + * http://web-graphics.com/mtarchive/001606.php + * + * There is another possibility to parse XML in Safari, by implementing + * the DOMParser in javascript. However, in the latest nightlies of + * WebKit, DOMParser is already available, but still buggy. So, this is + * the best compromise for the time being. + */ + + var xml = serializedXML; + var url = "data:text/xml;charset=utf-8," + encodeURIComponent(xml); + var dom = null; + + // your standard AJAX stuff + var req = new XMLHttpRequest(); + req.open("GET", url); + req.onload = function () { + dom = req.responseXML; + } + req.send(null); + + return dom; +} + +/* + * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +/* + * All code Copyright 2013 KIS Consultancy all rights reserved + */ + +/** + * Init namespace + */ +if (!ORYX) { + var ORYX = {}; +} +if (!ORYX.Core) { + ORYX.Core = {}; +} +if (!ORYX.Core.StencilSet) { + ORYX.Core.StencilSet = {}; +} + +/** + * Class Property + * uses Prototpye 1.5.0 + * uses Inheritance + */ +ORYX.Core.StencilSet.Property = Clazz.extend({ + + /** + * Constructor + */ + construct: function (jsonProp, namespace, stencil) { + arguments.callee.$.construct.apply(this, arguments); + + this._jsonProp = jsonProp || ORYX.Log.error("Parameter jsonProp is not defined."); + this._namespace = namespace || ORYX.Log.error("Parameter namespace is not defined."); + this._stencil = stencil || ORYX.Log.error("Parameter stencil is not defined."); + + this._items = {}; + this._complexItems = {}; + + // Flag to indicate whether or not the property should be hidden + // This can be for example when the stencil set is upgraded, but the model + // has a value for that specific property filled in which we still want to show. + // If the value is missing, the property can simply be not shown. + this._hidden = false; + + jsonProp.id = jsonProp.id || ORYX.Log.error("ORYX.Core.StencilSet.Property(construct): Id is not defined."); + jsonProp.id = jsonProp.id.toLowerCase(); + + if (!jsonProp.type) { + ORYX.Log.info("Type is not defined for stencil '%0', id '%1'. Falling back to 'String'.", stencil, jsonProp.id); + jsonProp.type = "string"; + } else { + jsonProp.type = jsonProp.type.toLowerCase(); + } + + jsonProp.prefix = jsonProp.prefix || "oryx"; + jsonProp.title = jsonProp.title || ""; + jsonProp.value = jsonProp.value || ""; + jsonProp.description = jsonProp.description || ""; + jsonProp.readonly = jsonProp.readonly || false; + jsonProp.optional = jsonProp.optional !== false; + + //init refToView + if (this._jsonProp.refToView) { + if (!(this._jsonProp.refToView instanceof Array)) { + this._jsonProp.refToView = [this._jsonProp.refToView]; + } + } else { + this._jsonProp.refToView = []; + } + + var globalMin = this.getMinForType(jsonProp.type); + if (jsonProp.min === undefined || jsonProp.min === null) { + jsonProp.min = globalMin; + } else if (jsonProp.min < globalMin) { + jsonProp.min = globalMin; + } + + var globalMax = this.getMaxForType(jsonProp.type); + if (jsonProp.max === undefined || jsonProp.max === null) { + jsonProp.max = globalMax; + } else if (jsonProp.max > globalMax) { + jsonProp.min = globalMax; + } + + if (!jsonProp.fillOpacity) { + jsonProp.fillOpacity = false; + } + + if ("number" != typeof jsonProp.lightness) { + jsonProp.lightness = 1; + } else { + jsonProp.lightness = Math.max(0, Math.min(1, jsonProp.lightness)); + } + + if (!jsonProp.strokeOpacity) { + jsonProp.strokeOpacity = false; + } + + if (jsonProp.length === undefined || jsonProp.length === null) { + jsonProp.length = Number.MAX_VALUE; + } + + if (!jsonProp.wrapLines) { + jsonProp.wrapLines = false; + } + + if (!jsonProp.dateFormat) { + jsonProp.dateFormat = ORYX.I18N.PropertyWindow.dateFormat || "m/d/y"; + } + + if (!jsonProp.fill) { + jsonProp.fill = false; + } + + if (!jsonProp.stroke) { + jsonProp.stroke = false; + } + + if (!jsonProp.inverseBoolean) { + jsonProp.inverseBoolean = false; + } + + if (!jsonProp.directlyEditable && jsonProp.directlyEditable != false) { + jsonProp.directlyEditable = true; + } + + if (jsonProp.visible !== false) { + jsonProp.visible = true; + } + + if (jsonProp.isList !== true) { + jsonProp.isList = false; + + if (!jsonProp.list || !(jsonProp.list instanceof Array)) { + jsonProp.list = []; + } + } + + if (!jsonProp.category) { + if (jsonProp.popular) { + jsonProp.category = "popular"; + } else { + jsonProp.category = "others"; + } + } + + if (!jsonProp.alwaysAppearInMultiselect) { + jsonProp.alwaysAppearInMultiselect = false; + } + + if (jsonProp.type === ORYX.CONFIG.TYPE_CHOICE) { + if (jsonProp.items && jsonProp.items instanceof Array) { + jsonProp.items.each((function (jsonItem) { + // why is the item's value used as the key??? + this._items[jsonItem.value.toLowerCase()] = new ORYX.Core.StencilSet.PropertyItem(jsonItem, namespace, this); + }).bind(this)); + } else { + throw "ORYX.Core.StencilSet.Property(construct): No property items defined." + } + // extended by Kerstin (start) + } else if (jsonProp.type === ORYX.CONFIG.TYPE_COMPLEX || jsonProp.type == ORYX.CONFIG.TYPE_MULTIPLECOMPLEX) { + if (jsonProp.complexItems && jsonProp.complexItems instanceof Array) { + jsonProp.complexItems.each((function (jsonComplexItem) { + this._complexItems[jsonComplexItem.id.toLowerCase()] = new ORYX.Core.StencilSet.ComplexPropertyItem(jsonComplexItem, namespace, this); + }).bind(this)); + } + } + // extended by Kerstin (end) + }, + + getMinForType: function (type) { + if (type.toLowerCase() == ORYX.CONFIG.TYPE_INTEGER) { + return -Math.pow(2, 31) + } else { + return -Number.MAX_VALUE + 1; + } + }, + getMaxForType: function (type) { + if (type.toLowerCase() == ORYX.CONFIG.TYPE_INTEGER) { + return Math.pow(2, 31) - 1 + } else { + return Number.MAX_VALUE; + } + }, + + /** + * @param {ORYX.Core.StencilSet.Property} property + * @return {Boolean} True, if property has the same namespace and id. + */ + equals: function (property) { + return (this._namespace === property.namespace() && + this.id() === property.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 (value) { + this._jsonProp.category = value; + }, + + 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"); + }, + + /** + * An optional link to a SVG element so that the property affects the + * graphical representation of the stencil. + */ + refToView: function () { + return this._jsonProp.refToView; + }, + + /** + * If type is integer or float, min is the lower bounds of value. + */ + min: function () { + return this._jsonProp.min; + }, + + /** + * If type ist integer or float, max is the upper bounds of value. + */ + max: function () { + return this._jsonProp.max; + }, + + /** + * If type is float, this method returns if the fill-opacity property should + * be set. + * @return {Boolean} + */ + fillOpacity: function () { + return this._jsonProp.fillOpacity; + }, + + /** + * If type is float, this method returns if the stroke-opacity property should + * be set. + * @return {Boolean} + */ + strokeOpacity: function () { + return this._jsonProp.strokeOpacity; + }, + + /** + * If type is string or richtext, length is the maximum length of the text. + * TODO how long can a string be. + */ + length: function () { + return this._jsonProp.length ? this._jsonProp.length : Number.MAX_VALUE; + }, + + wrapLines: function () { + return this._jsonProp.wrapLines; + }, + + /** + * If type is date, dateFormat specifies the format of the date. The format + * specification of the ext library is used: + * + * Format Output Description + * ------ ---------- -------------------------------------------------------------- + * d 10 Day of the month, 2 digits with leading zeros + * D Wed A textual representation of a day, three letters + * j 10 Day of the month without leading zeros + * l Wednesday A full textual representation of the day of the week + * S th English ordinal day of month suffix, 2 chars (use with j) + * w 3 Numeric representation of the day of the week + * z 9 The julian date, or day of the year (0-365) + * W 01 ISO-8601 2-digit week number of year, weeks starting on Monday (00-52) + * F January A full textual representation of the month + * m 01 Numeric representation of a month, with leading zeros + * M Jan Month name abbreviation, three letters + * n 1 Numeric representation of a month, without leading zeros + * t 31 Number of days in the given month + * L 0 Whether its a leap year (1 if it is a leap year, else 0) + * Y 2007 A full numeric representation of a year, 4 digits + * y 07 A two digit representation of a year + * a pm Lowercase Ante meridiem and Post meridiem + * A PM Uppercase Ante meridiem and Post meridiem + * g 3 12-hour format of an hour without leading zeros + * G 15 24-hour format of an hour without leading zeros + * h 03 12-hour format of an hour with leading zeros + * H 15 24-hour format of an hour with leading zeros + * i 05 Minutes with leading zeros + * s 01 Seconds, with leading zeros + * O -0600 Difference to Greenwich time (GMT) in hours + * T CST Timezone setting of the machine running the code + * Z -21600 Timezone offset in seconds (negative if west of UTC, positive if east) + * + * Example: + * F j, Y, g:i a -> January 10, 2007, 3:05 pm + */ + dateFormat: function () { + return this._jsonProp.dateFormat; + }, + + /** + * If type is color, this method returns if the fill property should + * be set. + * @return {Boolean} + */ + fill: function () { + return this._jsonProp.fill; + }, + + /** + * Lightness defines the satiation of the color + * 0 is the pure color + * 1 is white + * @return {Integer} lightness + */ + lightness: function () { + return this._jsonProp.lightness; + }, + + /** + * If type is color, this method returns if the stroke property should + * be set. + * @return {Boolean} + */ + stroke: function () { + return this._jsonProp.stroke; + }, + + /** + * If type is choice, items is a hash map with all alternative values + * (PropertyItem objects) with id as keys. + */ + items: function () { + return $H(this._items).values(); + }, + + item: function (value) { + if (value) { + return this._items[value.toLowerCase()]; + } else { + return null; + } + }, + + toString: function () { + return "Property " + this.title() + " (" + this.id() + ")"; + }, + + complexItems: function () { + return $H(this._complexItems).values(); + }, + + complexItem: function (id) { + if (id) { + return this._complexItems[id.toLowerCase()]; + } else { + return null; + } + + }, + + complexAttributeToView: function () { + return this._jsonProp.complexAttributeToView || ""; + }, + + isList: function () { + return !!this._jsonProp.isList; + }, + + getListItems: function () { + return this._jsonProp.list; + }, + + /** + * If type is glossary link, the + * type of category can be defined where + * the link only can go to. + * @return {String} The glossary category id + */ + 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; + } + +}); +/* + * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +/* + * All code Copyright 2013 KIS Consultancy all rights reserved + */ + +/** + * Init namespace + */ +if (!ORYX) { + var ORYX = {}; +} +if (!ORYX.Core) { + ORYX.Core = {}; +} +if (!ORYX.Core.StencilSet) { + ORYX.Core.StencilSet = {}; +} + +/** + * Class Stencil + * uses Prototpye 1.5.0 + * uses Inheritance + */ +ORYX.Core.StencilSet.PropertyItem = Clazz.extend({ + + /** + * Constructor + */ + construct: function (jsonItem, namespace, property) { + arguments.callee.$.construct.apply(this, arguments); + + if (!jsonItem) { + throw "ORYX.Core.StencilSet.PropertyItem(construct): Parameter jsonItem is not defined."; + } + if (!namespace) { + throw "ORYX.Core.StencilSet.PropertyItem(construct): Parameter namespace is not defined."; + } + if (!property) { + throw "ORYX.Core.StencilSet.PropertyItem(construct): Parameter property is not defined."; + } + + this._jsonItem = jsonItem; + this._namespace = namespace; + this._property = property; + + //init all values + if (!jsonItem.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 = []; + } + }, + + /** + * @param {ORYX.Core.StencilSet.PropertyItem} item + * @return {Boolean} True, if item has the same namespace and id. + */ + equals: function (item) { + return (this.property().equals(item.property()) && + this.value() === item.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() + ")"; + } +});/* + * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +/* + * All code Copyright 2013 KIS Consultancy all rights reserved + */ + +/** + * Init namespaces + */ +if (!ORYX) { + var ORYX = {}; +} +if (!ORYX.Core) { + ORYX.Core = {}; +} +if (!ORYX.Core.StencilSet) { + ORYX.Core.StencilSet = {}; +} + +/** + * Class Stencil + * uses Prototpye 1.5.0 + * uses Inheritance + */ +ORYX.Core.StencilSet.ComplexPropertyItem = Clazz.extend({ + + /** + * Constructor + */ + construct: function (jsonItem, namespace, property) { + arguments.callee.$.construct.apply(this, arguments); + + if (!jsonItem) { + throw "ORYX.Core.StencilSet.ComplexPropertyItem(construct): Parameter jsonItem is not defined."; + } + if (!namespace) { + throw "ORYX.Core.StencilSet.ComplexPropertyItem(construct): Parameter namespace is not defined."; + } + if (!property) { + throw "ORYX.Core.StencilSet.ComplexPropertyItem(construct): Parameter property is not defined."; + } + + this._jsonItem = jsonItem; + this._namespace = namespace; + this._property = property; + this._items = new Hash(); + this._complexItems = new Hash(); + + //init all values + if (!jsonItem.name) { + throw "ORYX.Core.StencilSet.ComplexPropertyItem(construct): Name is not defined."; + } + + if (!jsonItem.type) { + throw "ORYX.Core.StencilSet.ComplexPropertyItem(construct): Type is not defined."; + } else { + jsonItem.type = jsonItem.type.toLowerCase(); + } + + if (jsonItem.type === ORYX.CONFIG.TYPE_CHOICE) { + if (jsonItem.items && jsonItem.items instanceof Array) { + jsonItem.items.each((function (item) { + this._items[item.value] = new ORYX.Core.StencilSet.PropertyItem(item, namespace, this); + }).bind(this)); + } else { + throw "ORYX.Core.StencilSet.Property(construct): No property items defined." + } + } else if (jsonItem.type === ORYX.CONFIG.TYPE_COMPLEX) { + if (jsonItem.complexItems && jsonItem.complexItems instanceof Array) { + jsonItem.complexItems.each((function (complexItem) { + this._complexItems[complexItem.id] = new ORYX.Core.StencilSet.ComplexPropertyItem(complexItem, namespace, this); + }).bind(this)); + } else { + throw "ORYX.Core.StencilSet.Property(construct): No property items defined." + } + } + }, + + /** + * @param {ORYX.Core.StencilSet.PropertyItem} item + * @return {Boolean} True, if item has the same namespace and id. + */ + equals: function (item) { + return (this.property().equals(item.property()) && + this.name() === item.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; + } +});/* + * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +/* + * All code Copyright 2013 KIS Consultancy all rights reserved + */ + +/** + * Init namespaces + */ +if (!ORYX) { + var ORYX = {}; +} +if (!ORYX.Core) { + ORYX.Core = {}; +} +if (!ORYX.Core.StencilSet) { + ORYX.Core.StencilSet = {}; +} + +/** + * Class Rules uses Prototpye 1.5.0 uses Inheritance + * + * This class implements the API to check the stencil sets' rules. + */ +ORYX.Core.StencilSet.Rules = { + + /** + * Constructor + */ + 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(); + }, + + /** + * Call this method to initialize the rules for a stencil set and all of its + * active extensions. + * + * @param {Object} + * stencilSet + */ + initializeRules: function (stencilSet) { + + var existingSS = this._stencilSets.find(function (ss) { + return (ss.namespace() == stencilSet.namespace()); + }); + if (existingSS) { + // reinitialize all rules + var stencilsets = this._stencilSets.clone(); + stencilsets = stencilsets.without(existingSS); + stencilsets.push(stencilSet); + + 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(); + + stencilsets.each(function (ss) { + this.initializeRules(ss); + }.bind(this)); + return; + } else { + this._stencilSets.push(stencilSet); + + var jsonRules = new Hash(stencilSet.jsonRules()); + var namespace = stencilSet.namespace(); + var stencils = stencilSet.stencils(); + + stencilSet.extensions().values().each(function (extension) { + if (extension.rules) { + if (extension.rules.connectionRules) + jsonRules.connectionRules = jsonRules.connectionRules.concat(extension.rules.connectionRules); + if (extension.rules.cardinalityRules) + jsonRules.cardinalityRules = jsonRules.cardinalityRules.concat(extension.rules.cardinalityRules); + if (extension.rules.containmentRules) + jsonRules.containmentRules = jsonRules.containmentRules.concat(extension.rules.containmentRules); + if (extension.rules.morphingRules) + jsonRules.morphingRules = jsonRules.morphingRules.concat(extension.rules.morphingRules); + } + if (extension.stencils) + stencils = stencils.concat(extension.stencils); + }); + + this._stencils = this._stencils.concat(stencilSet.stencils()); + + // init connection rules + var cr = this._connectionRules; + if (jsonRules.connectionRules) { + jsonRules.connectionRules.each((function (rules) { + if (this._isRoleOfOtherNamespace(rules.role)) { + if (!cr[rules.role]) { + cr[rules.role] = new Hash(); + } + } else { + if (!cr[namespace + rules.role]) + cr[namespace + rules.role] = new Hash(); + } + + rules.connects.each((function (connect) { + var toRoles = []; + if (connect.to) { + if (!(connect.to instanceof Array)) { + connect.to = [connect.to]; + } + connect.to.each((function (to) { + if (this._isRoleOfOtherNamespace(to)) { + toRoles.push(to); + } else { + toRoles.push(namespace + to); + } + }).bind(this)); + } + + var role, from; + if (this._isRoleOfOtherNamespace(rules.role)) + role = rules.role; + else + role = namespace + rules.role; + + if (this._isRoleOfOtherNamespace(connect.from)) + from = connect.from; + else + from = namespace + connect.from; + + if (!cr[role][from]) + cr[role][from] = toRoles; + else + cr[role][from] = cr[role][from].concat(toRoles); + + }).bind(this)); + }).bind(this)); + } + + // init cardinality rules + var cardr = this._cardinalityRules; + if (jsonRules.cardinalityRules) { + jsonRules.cardinalityRules.each((function (rules) { + var cardrKey; + if (this._isRoleOfOtherNamespace(rules.role)) { + cardrKey = rules.role; + } else { + cardrKey = namespace + rules.role; + } + + if (!cardr[cardrKey]) { + cardr[cardrKey] = {}; + for (i in rules) { + cardr[cardrKey][i] = rules[i]; + } + } + + var oe = new Hash(); + if (rules.outgoingEdges) { + rules.outgoingEdges.each((function (rule) { + if (this._isRoleOfOtherNamespace(rule.role)) { + oe[rule.role] = rule; + } else { + oe[namespace + rule.role] = rule; + } + }).bind(this)); + } + cardr[cardrKey].outgoingEdges = oe; + var ie = new Hash(); + if (rules.incomingEdges) { + rules.incomingEdges.each((function (rule) { + if (this._isRoleOfOtherNamespace(rule.role)) { + ie[rule.role] = rule; + } else { + ie[namespace + rule.role] = rule; + } + }).bind(this)); + } + cardr[cardrKey].incomingEdges = ie; + }).bind(this)); + } + + // init containment rules + var conr = this._containmentRules; + if (jsonRules.containmentRules) { + jsonRules.containmentRules.each((function (rules) { + var conrKey; + if (this._isRoleOfOtherNamespace(rules.role)) { + conrKey = rules.role; + } else { + this._containerStencils.push(namespace + rules.role); + conrKey = namespace + rules.role; + } + if (!conr[conrKey]) { + conr[conrKey] = []; + } + (rules.contains || []).each((function (containRole) { + if (this._isRoleOfOtherNamespace(containRole)) { + conr[conrKey].push(containRole); + } else { + conr[conrKey].push(namespace + containRole); + } + }).bind(this)); + }).bind(this)); + } + + // init morphing rules + var morphr = this._morphingRules; + if (jsonRules.morphingRules) { + jsonRules.morphingRules.each((function (rules) { + var morphrKey; + if (this._isRoleOfOtherNamespace(rules.role)) { + morphrKey = rules.role; + } else { + morphrKey = namespace + rules.role; + } + if (!morphr[morphrKey]) { + morphr[morphrKey] = []; + } + if (!rules.preserveBounds) { + rules.preserveBounds = false; + } + rules.baseMorphs.each((function (baseMorphStencilId) { + var morphStencil = this._getStencilById(namespace + baseMorphStencilId); + if (morphStencil) { + morphr[morphrKey].push(morphStencil); + } + }).bind(this)); + }).bind(this)); + } + + // init layouting rules + var layoutRules = this._layoutRules; + if (jsonRules.layoutRules) { + + var getDirections = function (o) { + return { + "edgeRole": o.edgeRole || undefined, + "t": o["t"] || 1, + "r": o["r"] || 1, + "b": o["b"] || 1, + "l": o["l"] || 1 + } + } + + jsonRules.layoutRules.each(function (rules) { + var layoutKey; + if (this._isRoleOfOtherNamespace(rules.role)) { + layoutKey = rules.role; + } else { + layoutKey = namespace + rules.role; + } + if (!layoutRules[layoutKey]) { + layoutRules[layoutKey] = {}; + } + if (rules["in"]) { + layoutRules[layoutKey]["in"] = getDirections(rules["in"]); + } + if (rules["ins"]) { + layoutRules[layoutKey]["ins"] = (rules["ins"] || []).map(function (e) { + return getDirections(e) + }) + } + if (rules["out"]) { + layoutRules[layoutKey]["out"] = getDirections(rules["out"]); + } + if (rules["outs"]) { + layoutRules[layoutKey]["outs"] = (rules["outs"] || []).map(function (e) { + return getDirections(e) + }) + } + }.bind(this)); + } + } + }, + + _getStencilById: function (id) { + return this._stencils.find(function (stencil) { + return stencil.id() == id; + }); + }, + + _cacheConnect: function (args) { + result = this._canConnect(args); + + if (args.sourceStencil && args.targetStencil) { + var source = this._cachedConnectSET[args.sourceStencil.id()]; + + if (!source) { + source = new Hash(); + this._cachedConnectSET[args.sourceStencil.id()] = source; + } + + var edge = source[args.edgeStencil.id()]; + + if (!edge) { + edge = new Hash(); + source[args.edgeStencil.id()] = edge; + } + + edge[args.targetStencil.id()] = result; + + } else if (args.sourceStencil) { + var source = this._cachedConnectSE[args.sourceStencil.id()]; + + if (!source) { + source = new Hash(); + this._cachedConnectSE[args.sourceStencil.id()] = source; + } + + source[args.edgeStencil.id()] = result; + + } else { + var target = this._cachedConnectTE[args.targetStencil.id()]; + + if (!target) { + target = new Hash(); + this._cachedConnectTE[args.targetStencil.id()] = target; + } + + target[args.edgeStencil.id()] = result; + } + + return result; + }, + + _cacheCard: function (args) { + + if (args.sourceStencil) { + var source = this._cachedCardSE[args.sourceStencil.id()] + + if (!source) { + source = new Hash(); + this._cachedCardSE[args.sourceStencil.id()] = source; + } + + var max = this._getMaximumNumberOfOutgoingEdge(args); + if (max == undefined) + max = -1; + + source[args.edgeStencil.id()] = max; + } + + if (args.targetStencil) { + var target = this._cachedCardTE[args.targetStencil.id()] + + if (!target) { + target = new Hash(); + this._cachedCardTE[args.targetStencil.id()] = target; + } + + var max = this._getMaximumNumberOfIncomingEdge(args); + if (max == undefined) + max = -1; + + target[args.edgeStencil.id()] = max; + } + }, + + _cacheContain: function (args) { + + var result = [this._canContain(args), + this._getMaximumOccurrence(args.containingStencil, args.containedStencil)] + + if (result[1] == undefined) + result[1] = -1; + + var children = this._cachedContainPC[args.containingStencil.id()]; + + if (!children) { + children = new Hash(); + this._cachedContainPC[args.containingStencil.id()] = children; + } + + children[args.containedStencil.id()] = result; + + return result; + }, + + /** + * Returns all stencils belonging to a morph group. (calculation result is + * cached) + */ + _cacheMorph: function (role) { + + var morphs = this._cachedMorphRS[role]; + + if (!morphs) { + morphs = []; + + if (this._morphingRules.keys().include(role)) { + morphs = this._stencils.select(function (stencil) { + return stencil.roles().include(role); + }); + } + + this._cachedMorphRS[role] = morphs; + } + return morphs; + }, + + /** Begin connection rules' methods */ + + /** + * + * @param {Object} + * args sourceStencil: ORYX.Core.StencilSet.Stencil | undefined + * sourceShape: ORYX.Core.Shape | undefined + * + * At least sourceStencil or sourceShape has to be specified + * + * @return {Array} Array of stencils of edges that can be outgoing edges of + * the source. + */ + outgoingEdgeStencils: function (args) { + // check arguments + if (!args.sourceShape && !args.sourceStencil) { + return []; + } + + // init arguments + if (args.sourceShape) { + args.sourceStencil = args.sourceShape.getStencil(); + } + + var _edges = []; + + // test each edge, if it can connect to source + this._stencils.each((function (stencil) { + if (stencil.type() === "edge") { + var newArgs = Object.clone(args); + newArgs.edgeStencil = stencil; + if (this.canConnect(newArgs)) { + _edges.push(stencil); + } + } + }).bind(this)); + + return _edges; + }, + + /** + * + * @param {Object} + * args targetStencil: ORYX.Core.StencilSet.Stencil | undefined + * targetShape: ORYX.Core.Shape | undefined + * + * At least targetStencil or targetShape has to be specified + * + * @return {Array} Array of stencils of edges that can be incoming edges of + * the target. + */ + incomingEdgeStencils: function (args) { + // check arguments + if (!args.targetShape && !args.targetStencil) { + return []; + } + + // init arguments + if (args.targetShape) { + args.targetStencil = args.targetShape.getStencil(); + } + + var _edges = []; + + // test each edge, if it can connect to source + this._stencils.each((function (stencil) { + if (stencil.type() === "edge") { + var newArgs = Object.clone(args); + newArgs.edgeStencil = stencil; + if (this.canConnect(newArgs)) { + _edges.push(stencil); + } + } + }).bind(this)); + + return _edges; + }, + + /** + * + * @param {Object} + * args edgeStencil: ORYX.Core.StencilSet.Stencil | undefined + * edgeShape: ORYX.Core.Edge | undefined targetStencil: + * ORYX.Core.StencilSet.Stencil | undefined targetShape: + * ORYX.Core.Node | undefined + * + * At least edgeStencil or edgeShape has to be specified!!! + * + * @return {Array} Returns an array of stencils that can be source of the + * specified edge. + */ + sourceStencils: function (args) { + // check arguments + if (!args || + !args.edgeShape && !args.edgeStencil) { + return []; + } + + // init arguments + if (args.targetShape) { + args.targetStencil = args.targetShape.getStencil(); + } + + if (args.edgeShape) { + args.edgeStencil = args.edgeShape.getStencil(); + } + + var _sources = []; + + // check each stencil, if it can be a source + this._stencils.each((function (stencil) { + var newArgs = Object.clone(args); + newArgs.sourceStencil = stencil; + if (this.canConnect(newArgs)) { + _sources.push(stencil); + } + }).bind(this)); + + return _sources; + }, + + /** + * + * @param {Object} + * args edgeStencil: ORYX.Core.StencilSet.Stencil | undefined + * edgeShape: ORYX.Core.Edge | undefined sourceStencil: + * ORYX.Core.StencilSet.Stencil | undefined sourceShape: + * ORYX.Core.Node | undefined + * + * At least edgeStencil or edgeShape has to be specified!!! + * + * @return {Array} Returns an array of stencils that can be target of the + * specified edge. + */ + targetStencils: function (args) { + // check arguments + if (!args || + !args.edgeShape && !args.edgeStencil) { + return []; + } + + // init arguments + if (args.sourceShape) { + args.sourceStencil = args.sourceShape.getStencil(); + } + + if (args.edgeShape) { + args.edgeStencil = args.edgeShape.getStencil(); + } + + var _targets = []; + + // check stencil, if it can be a target + this._stencils.each((function (stencil) { + var newArgs = Object.clone(args); + newArgs.targetStencil = stencil; + if (this.canConnect(newArgs)) { + _targets.push(stencil); + } + }).bind(this)); + + return _targets; + }, + + /** + * + * @param {Object} + * args edgeStencil: ORYX.Core.StencilSet.Stencil edgeShape: + * ORYX.Core.Edge |undefined sourceStencil: + * ORYX.Core.StencilSet.Stencil | undefined sourceShape: + * ORYX.Core.Node |undefined targetStencil: + * ORYX.Core.StencilSet.Stencil | undefined targetShape: + * ORYX.Core.Node |undefined + * + * At least source or target has to be specified!!! + * + * @return {Boolean} Returns, if the edge can connect source and target. + */ + canConnect: function (args) { + // check arguments + if (!args || + (!args.sourceShape && !args.sourceStencil && + !args.targetShape && !args.targetStencil) || + !args.edgeShape && !args.edgeStencil) { + return false; + } + + // init arguments + if (args.sourceShape) { + args.sourceStencil = args.sourceShape.getStencil(); + } + if (args.targetShape) { + args.targetStencil = args.targetShape.getStencil(); + } + if (args.edgeShape) { + args.edgeStencil = args.edgeShape.getStencil(); + } + + var result; + + if (args.sourceStencil && args.targetStencil) { + var source = this._cachedConnectSET[args.sourceStencil.id()]; + + if (!source) + result = this._cacheConnect(args); + else { + var edge = source[args.edgeStencil.id()]; + + if (!edge) + result = this._cacheConnect(args); + else { + var target = edge[args.targetStencil.id()]; + + if (target == undefined) + result = this._cacheConnect(args); + else + result = target; + } + } + } else if (args.sourceStencil) { + var source = this._cachedConnectSE[args.sourceStencil.id()]; + + if (!source) + result = this._cacheConnect(args); + else { + var edge = source[args.edgeStencil.id()]; + + if (edge == undefined) + result = this._cacheConnect(args); + else + result = edge; + } + } else { // args.targetStencil + var target = this._cachedConnectTE[args.targetStencil.id()]; + + if (!target) + result = this._cacheConnect(args); + else { + var edge = target[args.edgeStencil.id()]; + + if (edge == undefined) + result = this._cacheConnect(args); + else + result = edge; + } + } + + // check cardinality + if (result) { + if (args.sourceShape) { + var source = this._cachedCardSE[args.sourceStencil.id()]; + + if (!source) { + this._cacheCard(args); + source = this._cachedCardSE[args.sourceStencil.id()]; + } + + var max = source[args.edgeStencil.id()]; + + if (max == undefined) { + this._cacheCard(args); + } + + max = source[args.edgeStencil.id()]; + + if (max != -1) { + result = args.sourceShape.getOutgoingShapes().all(function (cs) { + if ((cs.getStencil().id() === args.edgeStencil.id()) && + ((args.edgeShape) ? cs !== args.edgeShape : true)) { + max--; + return (max > 0) ? true : false; + } else { + return true; + } + }); + } + } + + if (args.targetShape) { + var target = this._cachedCardTE[args.targetStencil.id()]; + + if (!target) { + this._cacheCard(args); + target = this._cachedCardTE[args.targetStencil.id()]; + } + + var max = target[args.edgeStencil.id()]; + + if (max == undefined) { + this._cacheCard(args); + } + + max = target[args.edgeStencil.id()]; + + if (max != -1) { + result = args.targetShape.getIncomingShapes().all(function (cs) { + if ((cs.getStencil().id() === args.edgeStencil.id()) && + ((args.edgeShape) ? cs !== args.edgeShape : true)) { + max--; + return (max > 0) ? true : false; + } else { + return true; + } + }); + } + } + } + + return result; + }, + + /** + * + * @param {Object} + * args edgeStencil: ORYX.Core.StencilSet.Stencil edgeShape: + * ORYX.Core.Edge |undefined sourceStencil: + * ORYX.Core.StencilSet.Stencil | undefined sourceShape: + * ORYX.Core.Node |undefined targetStencil: + * ORYX.Core.StencilSet.Stencil | undefined targetShape: + * ORYX.Core.Node |undefined + * + * At least source or target has to be specified!!! + * + * @return {Boolean} Returns, if the edge can connect source and target. + */ + _canConnect: function (args) { + // check arguments + if (!args || + (!args.sourceShape && !args.sourceStencil && + !args.targetShape && !args.targetStencil) || + !args.edgeShape && !args.edgeStencil) { + return false; + } + + // init arguments + if (args.sourceShape) { + args.sourceStencil = args.sourceShape.getStencil(); + } + if (args.targetShape) { + args.targetStencil = args.targetShape.getStencil(); + } + if (args.edgeShape) { + args.edgeStencil = args.edgeShape.getStencil(); + } + + // 1. check connection rules + var resultCR; + + // get all connection rules for this edge + var edgeRules = this._getConnectionRulesOfEdgeStencil(args.edgeStencil); + + // check connection rules, if the source can be connected to the target + // with the specified edge. + if (edgeRules.keys().length === 0) { + resultCR = false; + } else { + if (args.sourceStencil) { + resultCR = args.sourceStencil.roles().any(function (sourceRole) { + var targetRoles = edgeRules[sourceRole]; + + if (!targetRoles) { + return false; + } + + if (args.targetStencil) { + return (targetRoles.any(function (targetRole) { + return args.targetStencil.roles().member(targetRole); + })); + } else { + return true; + } + }); + } else { // !args.sourceStencil -> there is args.targetStencil + resultCR = edgeRules.values().any(function (targetRoles) { + return args.targetStencil.roles().any(function (targetRole) { + return targetRoles.member(targetRole); + }); + }); + } + } + + return resultCR; + }, + + /** End connection rules' methods */ + + + /** Begin containment rules' methods */ + + isContainer: function (shape) { + return this._containerStencils.member(shape.getStencil().id()); + }, + + /** + * + * @param {Object} + * args containingStencil: ORYX.Core.StencilSet.Stencil + * containingShape: ORYX.Core.AbstractShape containedStencil: + * ORYX.Core.StencilSet.Stencil containedShape: ORYX.Core.Shape + */ + canContain: function (args) { + if (!args || + !args.containingStencil && !args.containingShape || + !args.containedStencil && !args.containedShape) { + return false; + } + + // init arguments + if (args.containedShape) { + args.containedStencil = args.containedShape.getStencil(); + } + + if (args.containingShape) { + args.containingStencil = args.containingShape.getStencil(); + } + + //if(args.containingStencil.type() == 'edge' || args.containedStencil.type() == 'edge') + // return false; + if (args.containedStencil.type() == 'edge') + return false; + + var childValues; + + var parent = this._cachedContainPC[args.containingStencil.id()]; + + if (!parent) + childValues = this._cacheContain(args); + else { + childValues = parent[args.containedStencil.id()]; + + if (!childValues) + childValues = this._cacheContain(args); + } + + if (!childValues[0]) + return false; + else if (childValues[1] == -1) + return true; + else { + if (args.containingShape) { + var max = childValues[1]; + return args.containingShape.getChildShapes(false).all(function (as) { + if (as.getStencil().id() === args.containedStencil.id()) { + max--; + return (max > 0) ? true : false; + } else { + return true; + } + }); + } else { + return true; + } + } + }, + + /** + * + * @param {Object} + * args containingStencil: ORYX.Core.StencilSet.Stencil + * containingShape: ORYX.Core.AbstractShape containedStencil: + * ORYX.Core.StencilSet.Stencil containedShape: ORYX.Core.Shape + */ + _canContain: function (args) { + if (!args || + !args.containingStencil && !args.containingShape || + !args.containedStencil && !args.containedShape) { + return false; + } + + // init arguments + if (args.containedShape) { + args.containedStencil = args.containedShape.getStencil(); + } + + if (args.containingShape) { + args.containingStencil = args.containingShape.getStencil(); + } + +// if(args.containingShape) { +// if(args.containingShape instanceof ORYX.Core.Edge) { +// // edges cannot contain other shapes +// return false; +// } +// } + + + var result; + + // check containment rules + result = args.containingStencil.roles().any((function (role) { + var roles = this._containmentRules[role]; + if (roles) { + return roles.any(function (role) { + return args.containedStencil.roles().member(role); + }); + } else { + return false; + } + }).bind(this)); + + return result; + }, + + /** End containment rules' methods */ + + + /** Begin morphing rules' methods */ + + /** + * + * @param {Object} + * args + * stencil: ORYX.Core.StencilSet.Stencil | undefined + * shape: ORYX.Core.Shape | undefined + * + * At least stencil or shape has to be specified + * + * @return {Array} Array of stencils that the passed stencil/shape can be + * transformed to (including the current stencil itself) + */ + morphStencils: function (args) { + // check arguments + if (!args.stencil && !args.shape) { + return []; + } + + // init arguments + if (args.shape) { + args.stencil = args.shape.getStencil(); + } + + var _morphStencils = []; + args.stencil.roles().each(function (role) { + this._cacheMorph(role).each(function (stencil) { + _morphStencils.push(stencil); + }) + }.bind(this)); + + + var baseMorphs = this.baseMorphs(); + // BaseMorphs should be in the front of the array + _morphStencils = _morphStencils.uniq().sort(function (a, b) { + return baseMorphs.include(a) && !baseMorphs.include(b) ? -1 : (baseMorphs.include(b) && !baseMorphs.include(a) ? 1 : 0) + }) + return _morphStencils; + }, + + /** + * @return {Array} An array of all base morph stencils + */ + baseMorphs: function () { + var _baseMorphs = []; + this._morphingRules.each(function (pair) { + pair.value.each(function (baseMorph) { + _baseMorphs.push(baseMorph); + }); + }); + return _baseMorphs; + }, + + /** + * Returns true if there are morphing rules defines + * @return {boolean} + */ + containsMorphingRules: function () { + return this._stencilSets.any(function (ss) { + return !!ss.jsonRules().morphingRules + }); + }, + + /** + * + * @param {Object} + * args + * sourceStencil: + * ORYX.Core.StencilSet.Stencil | undefined + * sourceShape: + * ORYX.Core.Node |undefined + * targetStencil: + * ORYX.Core.StencilSet.Stencil | undefined + * targetShape: + * ORYX.Core.Node |undefined + * + * + * @return {Stencil} Returns, the stencil for the connecting edge + * or null if connection is not possible + */ + connectMorph: function (args) { + // check arguments + if (!args || + (!args.sourceShape && !args.sourceStencil && + !args.targetShape && !args.targetStencil)) { + return false; + } + + // init arguments + if (args.sourceShape) { + args.sourceStencil = args.sourceShape.getStencil(); + } + if (args.targetShape) { + args.targetStencil = args.targetShape.getStencil(); + } + + var incoming = this.incomingEdgeStencils(args); + var outgoing = this.outgoingEdgeStencils(args); + + var edgeStencils = incoming.select(function (e) { + return outgoing.member(e); + }); // intersection of sets + var baseEdgeStencils = this.baseMorphs().select(function (e) { + return edgeStencils.member(e); + }); // again: intersection of sets + + if (baseEdgeStencils.size() > 0) + return baseEdgeStencils[0]; // return any of the possible base morphs + else if (edgeStencils.size() > 0) + return edgeStencils[0]; // return any of the possible stencils + + return null; //connection not possible + }, + + /** + * Return true if the stencil should be located in the shape menu + * @param {ORYX.Core.StencilSet.Stencil} morph + * @return {Boolean} Returns true if the morphs in the morph group of the + * specified morph shall be displayed in the shape menu + */ + showInShapeMenu: function (stencil) { + return this._stencilSets.any(function (ss) { + return ss.jsonRules().morphingRules + .any(function (r) { + return stencil.roles().include(ss.namespace() + r.role) + && r.showInShapeMenu !== false; + }) + }); + }, + + preserveBounds: function (stencil) { + return this._stencilSets.any(function (ss) { + return ss.jsonRules().morphingRules.any(function (r) { + + + return stencil.roles().include(ss.namespace() + r.role) + && r.preserveBounds; + }) + }) + }, + + /** End morphing rules' methods */ + + + /** Begin layouting rules' methods */ + + /** + * Returns a set on "in" and "out" layouting rules for a given shape + * @param {Object} shape + * @param {Object} edgeShape (Optional) + * @return {Object} "in" and "out" with a default value of {"t":1, "r":1, "b":1, "r":1} if not specified in the json + */ + getLayoutingRules: function (shape, edgeShape) { + + if (!shape || !(shape instanceof ORYX.Core.Shape)) { + return + } + + var layout = {"in": {}, "out": {}}; + + var parseValues = function (o, v) { + if (o && o[v]) { + ["t", "r", "b", "l"].each(function (d) { + layout[v][d] = Math.max(o[v][d], layout[v][d] || 0); + }); + } + if (o && o[v + "s"] instanceof Array) { + ["t", "r", "b", "l"].each(function (d) { + var defaultRule = o[v + "s"].find(function (e) { + return !e.edgeRole + }); + var edgeRule; + if (edgeShape instanceof ORYX.Core.Edge) { + edgeRule = o[v + "s"].find(function (e) { + return this._hasRole(edgeShape, e.edgeRole) + }.bind(this)); + } + layout[v][d] = Math.max(edgeRule ? edgeRule[d] : defaultRule[d], layout[v][d] || 0); + }.bind(this)); + } + }.bind(this) + + // For each role + shape.getStencil().roles().each(function (role) { + // check if there are layout information + if (this._layoutRules[role]) { + // if so, parse those information to the 'layout' variable + parseValues(this._layoutRules[role], "in"); + parseValues(this._layoutRules[role], "out"); + } + }.bind(this)); + + // Make sure, that every attribute has an value, + // otherwise set 1 + ["in", "out"].each(function (v) { + ["t", "r", "b", "l"].each(function (d) { + layout[v][d] = layout[v][d] !== undefined ? layout[v][d] : 1; + }); + }) + + return layout; + }, + + /** End layouting rules' methods */ + + /** Helper methods */ + + /** + * Checks wether a shape contains the given role or the role is equal the stencil id + * @param {ORYX.Core.Shape} shape + * @param {String} role + */ + _hasRole: function (shape, role) { + if (!(shape instanceof ORYX.Core.Shape) || !role) { + return + } + var isRole = shape.getStencil().roles().any(function (r) { + return r == role + }); + + return isRole || shape.getStencil().id() == (shape.getStencil().namespace() + role); + }, + + /** + * + * @param {String} + * role + * + * @return {Array} Returns an array of stencils that can act as role. + */ + _stencilsWithRole: function (role) { + return this._stencils.findAll(function (stencil) { + return (stencil.roles().member(role)) ? true : false; + }); + }, + + /** + * + * @param {String} + * role + * + * @return {Array} Returns an array of stencils that can act as role and + * have the type 'edge'. + */ + _edgesWithRole: function (role) { + return this._stencils.findAll(function (stencil) { + return (stencil.roles().member(role) && stencil.type() === "edge") ? true : false; + }); + }, + + /** + * + * @param {String} + * role + * + * @return {Array} Returns an array of stencils that can act as role and + * have the type 'node'. + */ + _nodesWithRole: function (role) { + return this._stencils.findAll(function (stencil) { + return (stencil.roles().member(role) && stencil.type() === "node") ? true : false; + }); + }, + + /** + * + * @param {ORYX.Core.StencilSet.Stencil} + * parent + * @param {ORYX.Core.StencilSet.Stencil} + * child + * + * @returns {Boolean} Returns the maximum occurrence of shapes of the + * stencil's type inside the parent. + */ + _getMaximumOccurrence: function (parent, child) { + var max; + child.roles().each((function (role) { + var cardRule = this._cardinalityRules[role]; + if (cardRule && cardRule.maximumOccurrence) { + if (max) { + max = Math.min(max, cardRule.maximumOccurrence); + } else { + max = cardRule.maximumOccurrence; + } + } + }).bind(this)); + + return max; + }, + + + /** + * + * @param {Object} + * args sourceStencil: ORYX.Core.Node edgeStencil: + * ORYX.Core.StencilSet.Stencil + * + * @return {Boolean} Returns, the maximum number of outgoing edges of the + * type specified by edgeStencil of the sourceShape. + */ + _getMaximumNumberOfOutgoingEdge: function (args) { + if (!args || + !args.sourceStencil || + !args.edgeStencil) { + return false; + } + + var max; + args.sourceStencil.roles().each((function (role) { + var cardRule = this._cardinalityRules[role]; + + if (cardRule && cardRule.outgoingEdges) { + args.edgeStencil.roles().each(function (edgeRole) { + var oe = cardRule.outgoingEdges[edgeRole]; + + if (oe && oe.maximum) { + if (max) { + max = Math.min(max, oe.maximum); + } else { + max = oe.maximum; + } + } + }); + } + }).bind(this)); + + return max; + }, + + /** + * + * @param {Object} + * args targetStencil: ORYX.Core.StencilSet.Stencil edgeStencil: + * ORYX.Core.StencilSet.Stencil + * + * @return {Boolean} Returns the maximum number of incoming edges of the + * type specified by edgeStencil of the targetShape. + */ + _getMaximumNumberOfIncomingEdge: function (args) { + if (!args || + !args.targetStencil || + !args.edgeStencil) { + return false; + } + + var max; + args.targetStencil.roles().each((function (role) { + var cardRule = this._cardinalityRules[role]; + if (cardRule && cardRule.incomingEdges) { + args.edgeStencil.roles().each(function (edgeRole) { + var ie = cardRule.incomingEdges[edgeRole]; + if (ie && ie.maximum) { + if (max) { + max = Math.min(max, ie.maximum); + } else { + max = ie.maximum; + } + } + }); + } + }).bind(this)); + + return max; + }, + + /** + * + * @param {ORYX.Core.StencilSet.Stencil} + * edgeStencil + * + * @return {Hash} Returns a hash map of all connection rules for + * edgeStencil. + */ + _getConnectionRulesOfEdgeStencil: function (edgeStencil) { + var edgeRules = new Hash(); + edgeStencil.roles().each((function (role) { + if (this._connectionRules[role]) { + this._connectionRules[role].each(function (cr) { + if (edgeRules[cr.key]) { + edgeRules[cr.key] = edgeRules[cr.key].concat(cr.value); + } else { + edgeRules[cr.key] = cr.value; + } + }); + } + }).bind(this)); + + return edgeRules; + }, + + _isRoleOfOtherNamespace: function (role) { + return (role.indexOf("#") > 0); + }, + + toString: function () { + return "Rules"; + } +} +ORYX.Core.StencilSet.Rules = Clazz.extend(ORYX.Core.StencilSet.Rules); +/* + * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +/* + * All code Copyright 2013 KIS Consultancy all rights reserved + */ + +/** + * Init namespace + */ +if (!ORYX) { + var ORYX = {}; +} +if (!ORYX.Core) { + ORYX.Core = {}; +} +if (!ORYX.Core.StencilSet) { + ORYX.Core.StencilSet = {}; +} + +/** + * This class represents a stencil set. It offers methods for accessing + * the attributes of the stencil set description JSON file and the stencil set's + * stencils. + */ +ORYX.Core.StencilSet.StencilSet = Clazz.extend({ + + /** + * Constructor + * @param source {URL} A reference to the stencil set specification. + * + */ + construct: function (source, modelMetaData, editorId) { + arguments.callee.$.construct.apply(this, arguments); + + if (!source) { + throw "ORYX.Core.StencilSet.StencilSet(construct): Parameter 'source' is not defined."; + } + + if (source.endsWith("/")) { + source = source.substr(0, source.length - 1); + } + + this._extensions = new Hash(); + + this._source = source; + this._baseUrl = source.substring(0, source.lastIndexOf("/") + 1); + + this._jsonObject = {}; + + this._stencils = new Hash(); + this._availableStencils = new Hash(); + + if (ORYX.CONFIG.BACKEND_SWITCH) { + this._baseUrl = "editor/stencilsets/bpmn2.0/"; + this._source = "stencilsets/bpmn2.0/bpmn2.0.json"; + + new Ajax.Request(ACTIVITI.CONFIG.contextRoot + '/editor/stencilset?version=' + Date.now(), { + asynchronous: false, + method: 'get', + onSuccess: this._init.bind(this), + onFailure: this._cancelInit.bind(this) + }); + + } else { + new Ajax.Request(source, { + asynchronous: false, + method: 'get', + onSuccess: this._init.bind(this), + onFailure: this._cancelInit.bind(this) + }); + } + + if (this.errornous) + throw "Loading stencil set " + source + " failed."; + }, + + /** + * Finds a root stencil in this stencil set. There may be many of these. If + * there are, the first one found will be used. In Firefox, this is the + * topmost definition in the stencil set description file. + */ + findRootStencilName: function () { + + // find any stencil that may be root. + var rootStencil = this._stencils.values().find(function (stencil) { + return stencil._jsonStencil.mayBeRoot + }); + + // if there is none, just guess the first. + if (!rootStencil) { + ORYX.Log.warn("Did not find any stencil that may be root. Taking a guess."); + rootStencil = this._stencils.values()[0]; + } + + // return its id. + return rootStencil.id(); + }, + + /** + * @param {ORYX.Core.StencilSet.StencilSet} stencilSet + * @return {Boolean} True, if stencil set has the same namespace. + */ + equals: function (stencilSet) { + return (this.namespace() === stencilSet.namespace()); + }, + + /** + * + * @param {Oryx.Core.StencilSet.Stencil} rootStencil If rootStencil is defined, it only returns stencils + * that could be (in)direct child of that stencil. + */ + stencils: function (rootStencil, rules, sortByGroup) { + if (rootStencil && rules) { + var stencils = this._availableStencils.values(); + var containers = [rootStencil]; + var checkedContainers = []; + + var result = []; + + while (containers.size() > 0) { + var container = containers.pop(); + checkedContainers.push(container); + var children = stencils.findAll(function (stencil) { + var args = { + containingStencil: container, + containedStencil: stencil + }; + return rules.canContain(args); + }); + for (var i = 0; i < children.size(); i++) { + if (!checkedContainers.member(children[i])) { + containers.push(children[i]); + } + } + result = result.concat(children).uniq(); + } + + // Sort the result to the origin order + result = result.sortBy(function (stencil) { + return stencils.indexOf(stencil); + }); + + + if (sortByGroup) { + result = result.sortBy(function (stencil) { + return stencil.groups().first(); + }); + } + + var edges = stencils.findAll(function (stencil) { + return stencil.type() == "edge"; + }); + result = result.concat(edges); + + return result; + + } else { + if (sortByGroup) { + return this._availableStencils.values().sortBy(function (stencil) { + return stencil.groups().first(); + }); + } else { + return this._availableStencils.values(); + } + } + }, + + nodes: function () { + return this._availableStencils.values().findAll(function (stencil) { + return (stencil.type() === 'node') + }); + }, + + edges: function () { + return this._availableStencils.values().findAll(function (stencil) { + return (stencil.type() === 'edge') + }); + }, + + stencil: function (id) { + return this._stencils[id]; + }, + + 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 (url) { + + new Ajax.Request(url, { + method: 'GET', + asynchronous: false, + onSuccess: (function (transport) { + this.addExtensionDirectly(transport.responseText); + }).bind(this), + onFailure: (function (transport) { + ORYX.Log.debug("Loading stencil set extension file failed. The request returned an error." + transport); + }).bind(this), + onException: (function (transport) { + ORYX.Log.debug("Loading stencil set extension file failed. The request returned an error." + transport); + }).bind(this) + + }); + }, + + addExtensionDirectly: function (str) { + + try { + eval("var jsonExtension = " + str); + + if (!(jsonExtension["extends"].endsWith("#"))) + jsonExtension["extends"] += "#"; + + if (jsonExtension["extends"] == this.namespace()) { + this._extensions[jsonExtension.namespace] = jsonExtension; + + var defaultPosition = this._stencils.keys().size(); + //load new stencils + if (jsonExtension.stencils) { + $A(jsonExtension.stencils).each(function (stencil) { + defaultPosition++; + var oStencil = new ORYX.Core.StencilSet.Stencil(stencil, this.namespace(), this._baseUrl, this, undefined, defaultPosition); + this._stencils[oStencil.id()] = oStencil; + this._availableStencils[oStencil.id()] = oStencil; + }.bind(this)); + } + + //load additional properties + 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)); + } + + //remove stencil properties + 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)); + } + + //remove stencils + 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 (namespace) { + var jsonExtension = this._extensions[namespace]; + if (jsonExtension) { + + //unload extension's stencils + if (jsonExtension.stencils) { + $A(jsonExtension.stencils).each(function (stencil) { + var oStencil = new ORYX.Core.StencilSet.Stencil(stencil, this.namespace(), this._baseUrl, this); + delete this._stencils[oStencil.id()]; // maybe not ?? + delete this._availableStencils[oStencil.id()]; + }.bind(this)); + } + + //unload extension's properties + 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.removeProperty(property.id); + }); + + return true; + } else + return false; + }) + }) + }.bind(this)); + } + + //restore removed stencil properties + if (jsonExtension.removeproperties) { + jsonExtension.removeproperties.each(function (remprop) { + var stencil = this.stencil(jsonExtension["extends"] + remprop.stencil); + if (stencil) { + var stencilJson = $A(this._jsonObject.stencils).find(function (s) { + return s.id == stencil.id() + }); + remprop.properties.each(function (propId) { + var propertyJson = $A(stencilJson.properties).find(function (p) { + return p.id == propId + }); + stencil.addProperty(propertyJson, this.namespace()); + }.bind(this)); + } + }.bind(this)); + } + + //restore removed stencils + if (jsonExtension.removestencils) { + $A(jsonExtension.removestencils).each(function (remstencil) { + var sId = jsonExtension["extends"] + remstencil; + this._availableStencils[sId] = this._stencils[sId]; + }.bind(this)); + } + } + delete this._extensions[namespace]; + }, + + __handleStencilset: function (response) { + + try { + // using eval instead of prototype's parsing, + // since there are functions in this JSON. + eval("this._jsonObject =" + response.responseText); + } catch (e) { + throw "Stenciset corrupt: " + e; + } + + // assert it was parsed. + if (!this._jsonObject) { + throw "Error evaluating stencilset. It may be corrupt."; + } + + with (this._jsonObject) { + + // assert there is a namespace. + if (!namespace || namespace === "") + throw "Namespace definition missing in stencilset."; + + if (!(stencils instanceof Array)) + throw "Stencilset corrupt."; + + // assert namespace ends with '#'. + if (!namespace.endsWith("#")) + namespace = namespace + "#"; + + // assert title and description are strings. + if (!title) + title = ""; + if (!description) + description = ""; + } + }, + + /** + * This method is called when the HTTP request to get the requested stencil + * set succeeds. The response is supposed to be a JSON representation + * according to the stencil set specification. + * @param {Object} response The JSON representation according to the + * stencil set specification. + */ + _init: function (response) { + + // init and check consistency. + this.__handleStencilset(response); + + var pps = new Hash(); + + // init property packages + if (this._jsonObject.propertyPackages) { + $A(this._jsonObject.propertyPackages).each((function (pp) { + pps[pp.name] = pp.properties; + }).bind(this)); + } + + var defaultPosition = 0; + + // init each stencil + $A(this._jsonObject.stencils).each((function (stencil) { + defaultPosition++; + + // instantiate normally. + var oStencil = new ORYX.Core.StencilSet.Stencil(stencil, this.namespace(), this._baseUrl, this, pps, defaultPosition); + this._stencils[oStencil.id()] = oStencil; + this._availableStencils[oStencil.id()] = oStencil; + + }).bind(this)); + }, + + _cancelInit: function (response) { + this.errornous = true; + }, + + toString: function () { + return "StencilSet " + this.title() + " (" + this.namespace() + ")"; + } +}); +/* + * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +/* + * All code Copyright 2013 KIS Consultancy all rights reserved + */ + +/** + * Init namespace + */ +if (!ORYX) { + var ORYX = {}; +} +if (!ORYX.Core) { + ORYX.Core = {}; +} +if (!ORYX.Core.StencilSet) { + ORYX.Core.StencilSet = {}; +} + +/** + * Class StencilSets + * uses Prototpye 1.5.0 + * uses Inheritance + * + * Singleton + */ +//storage for loaded stencil sets by namespace +ORYX.Core.StencilSet._stencilSetsByNamespace = new Hash(); + +//storage for stencil sets by url +ORYX.Core.StencilSet._stencilSetsByUrl = new Hash(); + +//storage for stencil set namespaces by editor instances +ORYX.Core.StencilSet._StencilSetNSByEditorInstance = new Hash(); + +//storage for rules by editor instances +ORYX.Core.StencilSet._rulesByEditorInstance = new Hash(); + +/** + * + * @param {String} editorId + * + * @return {Hash} Returns a hash map with all stencil sets that are loaded by + * the editor with the editorId. + */ +ORYX.Core.StencilSet.stencilSets = function (editorId) { + var stencilSetNSs = ORYX.Core.StencilSet._StencilSetNSByEditorInstance[editorId]; + var stencilSets = new Hash(); + if (stencilSetNSs) { + stencilSetNSs.each(function (stencilSetNS) { + var stencilSet = ORYX.Core.StencilSet.stencilSet(stencilSetNS) + stencilSets[stencilSet.namespace()] = stencilSet; + }); + } + return stencilSets; +}; + +/** + * + * @param {String} namespace + * + * @return {ORYX.Core.StencilSet.StencilSet} Returns the stencil set with the specified + * namespace. + * + * The method can handle namespace strings like + * http://www.example.org/stencilset + * http://www.example.org/stencilset# + * http://www.example.org/stencilset#ANode + */ +ORYX.Core.StencilSet.stencilSet = function (namespace) { + ORYX.Log.trace("Getting stencil set %0", namespace); + var splitted = namespace.split("#", 1); + if (splitted.length === 1) { + ORYX.Log.trace("Getting stencil set %0", splitted[0]); + return ORYX.Core.StencilSet._stencilSetsByNamespace[splitted[0] + "#"]; + } else { + return undefined; + } +}; + +/** + * + * @param {String} id + * + * @return {ORYX.Core.StencilSet.Stencil} Returns the stencil specified by the id. + * + * The id must be unique and contains the namespace of the stencil's stencil set. + * e.g. http://www.example.org/stencilset#ANode + */ +ORYX.Core.StencilSet.stencil = function (id) { + ORYX.Log.trace("Getting stencil for %0", id); + var ss = ORYX.Core.StencilSet.stencilSet(id); + if (ss) { + return ss.stencil(id); + } else { + + ORYX.Log.trace("Cannot fild stencil for %0", id); + return undefined; + } +}; + +/** + * + * @param {String} editorId + * + * @return {ORYX.Core.StencilSet.Rules} Returns the rules object for the editor + * specified by its editor id. + */ +ORYX.Core.StencilSet.rules = function (editorId) { + if (!ORYX.Core.StencilSet._rulesByEditorInstance[editorId]) { + ORYX.Core.StencilSet._rulesByEditorInstance[editorId] = new ORYX.Core.StencilSet.Rules(); + } + return ORYX.Core.StencilSet._rulesByEditorInstance[editorId]; +}; + +/** + * + * @param {String} url + * @param {String} editorId + * + * Loads a stencil set from url, if it is not already loaded. + * It also stores which editor instance loads the stencil set and + * initializes the Rules object for the editor instance. + */ +ORYX.Core.StencilSet.loadStencilSet = function (url, modelMetaData, editorId) { + + // Alfresco: disable cache, because stencil sets are now flexible + + //var stencilSet = ORYX.Core.StencilSet._stencilSetsByUrl[url]; + + //if(!stencilSet) { + //load stencil set + stencilSet = new ORYX.Core.StencilSet.StencilSet(url, modelMetaData, editorId); + + //store stencil set + ORYX.Core.StencilSet._stencilSetsByNamespace[stencilSet.namespace()] = stencilSet; + + //store stencil set by url + ORYX.Core.StencilSet._stencilSetsByUrl[url] = stencilSet; + //} + + var namespace = stencilSet.namespace(); + + //store which editorInstance loads the stencil set + if (ORYX.Core.StencilSet._StencilSetNSByEditorInstance[editorId]) { + ORYX.Core.StencilSet._StencilSetNSByEditorInstance[editorId].push(namespace); + } else { + ORYX.Core.StencilSet._StencilSetNSByEditorInstance[editorId] = [namespace]; + } + + //store the rules for the editor instance + if (ORYX.Core.StencilSet._rulesByEditorInstance[editorId]) { + ORYX.Core.StencilSet._rulesByEditorInstance[editorId].initializeRules(stencilSet); + } else { + var rules = new ORYX.Core.StencilSet.Rules(); + rules.initializeRules(stencilSet); + ORYX.Core.StencilSet._rulesByEditorInstance[editorId] = rules; + } +}; + +/** + * Returns the translation of an attribute in jsonObject specified by its name + * according to navigator.language + */ +ORYX.Core.StencilSet.getTranslation = function (jsonObject, name) { + var lang = ORYX.I18N.Language.toLowerCase(); + + var result = jsonObject[name + "_" + lang]; + + if (result) + return result; + + result = jsonObject[name + "_" + lang.substr(0, 2)]; + + if (result) + return result; + + return jsonObject[name]; +}; +/* + * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +/* + * All code Copyright 2013 KIS Consultancy all rights reserved + */ + +/** + * Init namespaces + */ +if (!ORYX) { + var ORYX = {}; +} +if (!ORYX.Core) { + ORYX.Core = {}; +} + + +/** + * @classDescription With Bounds you can set and get position and size of UIObjects. + */ +ORYX.Core.Command = Clazz.extend({ + + /** + * Constructor + */ + construct: function () { + + }, + + execute: function () { + throw "Command.execute() has to be implemented!" + }, + + rollback: function () { + throw "Command.rollback() has to be implemented!" + } + + +});/* + * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +/* + * All code Copyright 2013 KIS Consultancy all rights reserved + */ + +/** + * Init namespaces + */ +if (!ORYX) { + var ORYX = {}; +} +if (!ORYX.Core) { + ORYX.Core = {}; +} + + +/** + * @classDescription With Bounds you can set and get position and size of UIObjects. + */ +ORYX.Core.Bounds = { + + /** + * Constructor + */ + construct: function () { + this._changedCallbacks = []; //register a callback with changedCallacks.push(this.method.bind(this)); + this.a = {}; + this.b = {}; + this.set.apply(this, arguments); + this.suspendChange = false; + this.changedWhileSuspend = false; + }, + + /** + * Calls all registered callbacks. + */ + _changed: function (sizeChanged) { + if (!this.suspendChange) { + this._changedCallbacks.each(function (callback) { + callback(this, sizeChanged); + }.bind(this)); + this.changedWhileSuspend = false; + } else + this.changedWhileSuspend = true; + }, + + /** + * Registers a callback that is called, if the bounds changes. + * @param callback {Function} The callback function. + */ + registerCallback: function (callback) { + if (!this._changedCallbacks.member(callback)) { + this._changedCallbacks.push(callback); + } + }, + + /** + * Unregisters a callback. + * @param callback {Function} The callback function. + */ + unregisterCallback: function (callback) { + this._changedCallbacks = this._changedCallbacks.without(callback); + }, + + /** + * Sets position and size of the shape dependent of four coordinates + * (set(ax, ay, bx, by);), two points (set({x: ax, y: ay}, {x: bx, y: by});) + * or one bound (set({a: {x: ax, y: ay}, b: {x: bx, y: by}});). + */ + set: function () { + + var changed = false; + + switch (arguments.length) { + + case 1: + if (this.a.x !== arguments[0].a.x) { + changed = true; + this.a.x = arguments[0].a.x; + } + if (this.a.y !== arguments[0].a.y) { + changed = true; + this.a.y = arguments[0].a.y; + } + if (this.b.x !== arguments[0].b.x) { + changed = true; + this.b.x = arguments[0].b.x; + } + if (this.b.y !== arguments[0].b.y) { + changed = true; + this.b.y = arguments[0].b.y; + } + break; + + case 2: + var ax = Math.min(arguments[0].x, arguments[1].x); + var ay = Math.min(arguments[0].y, arguments[1].y); + var bx = Math.max(arguments[0].x, arguments[1].x); + var by = Math.max(arguments[0].y, arguments[1].y); + if (this.a.x !== ax) { + changed = true; + this.a.x = ax; + } + if (this.a.y !== ay) { + changed = true; + this.a.y = ay; + } + if (this.b.x !== bx) { + changed = true; + this.b.x = bx; + } + if (this.b.y !== by) { + changed = true; + this.b.y = by; + } + break; + + case 4: + var ax = Math.min(arguments[0], arguments[2]); + var ay = Math.min(arguments[1], arguments[3]); + var bx = Math.max(arguments[0], arguments[2]); + var by = Math.max(arguments[1], arguments[3]); + if (this.a.x !== ax) { + changed = true; + this.a.x = ax; + } + if (this.a.y !== ay) { + changed = true; + this.a.y = ay; + } + if (this.b.x !== bx) { + changed = true; + this.b.x = bx; + } + if (this.b.y !== by) { + changed = true; + this.b.y = by; + } + break; + } + + if (changed) { + this._changed(true); + } + }, + + /** + * Moves the bounds so that the point p will be the new upper left corner. + * @param {Point} p + * or + * @param {Number} x + * @param {Number} y + */ + moveTo: function () { + + var currentPosition = this.upperLeft(); + switch (arguments.length) { + case 1: + this.moveBy({ + x: arguments[0].x - currentPosition.x, + y: arguments[0].y - currentPosition.y + }); + break; + case 2: + this.moveBy({ + x: arguments[0] - currentPosition.x, + y: arguments[1] - currentPosition.y + }); + break; + default: + //TODO error + } + + }, + + /** + * Moves the bounds relatively by p. + * @param {Point} p + * or + * @param {Number} x + * @param {Number} y + * + */ + moveBy: function () { + var changed = false; + + switch (arguments.length) { + case 1: + var p = arguments[0]; + if (p.x !== 0 || p.y !== 0) { + changed = true; + this.a.x += p.x; + this.b.x += p.x; + this.a.y += p.y; + this.b.y += p.y; + } + break; + case 2: + var x = arguments[0]; + var y = arguments[1]; + if (x !== 0 || y !== 0) { + changed = true; + this.a.x += x; + this.b.x += x; + this.a.y += y; + this.b.y += y; + } + break; + default: + //TODO error + } + + if (changed) { + this._changed(); + } + }, + + /*** + * Includes the bounds b into the current bounds. + * @param {Bounds} b + */ + include: function (b) { + + if ((this.a.x === undefined) && (this.a.y === undefined) && + (this.b.x === undefined) && (this.b.y === undefined)) { + return b; + } + ; + + var cx = Math.min(this.a.x, b.a.x); + var cy = Math.min(this.a.y, b.a.y); + + var dx = Math.max(this.b.x, b.b.x); + var dy = Math.max(this.b.y, b.b.y); + + + this.set(cx, cy, dx, dy); + }, + + /** + * Relatively extends the bounds by p. + * @param {Point} p + */ + extend: function (p) { + + if (p.x !== 0 || p.y !== 0) { + // this is over cross for the case that a and b have same coordinates. + //((this.a.x > this.b.x) ? this.a : this.b).x += p.x; + //((this.b.y > this.a.y) ? this.b : this.a).y += p.y; + this.b.x += p.x; + this.b.y += p.y; + + this._changed(true); + } + }, + + /** + * Widens the scope of the bounds by x. + * @param {Number} x + */ + widen: function (x) { + if (x !== 0) { + this.suspendChange = true; + this.moveBy({x: -x, y: -x}); + this.extend({x: 2 * x, y: 2 * x}); + this.suspendChange = false; + if (this.changedWhileSuspend) { + this._changed(true); + } + } + }, + + /** + * Returns the upper left corner's point regardless of the + * bound delimiter points. + */ + upperLeft: function () { + var result = {}; + result.x = this.a.x; + result.y = this.a.y; + return result; + }, + + /** + * Returns the lower Right left corner's point regardless of the + * bound delimiter points. + */ + lowerRight: function () { + var result = {}; + result.x = this.b.x; + result.y = this.b.y; + return result; + }, + + /** + * @return {Number} Width of bounds. + */ + width: function () { + return this.b.x - this.a.x; + }, + + /** + * @return {Number} Height of bounds. + */ + height: function () { + return this.b.y - this.a.y; + }, + + /** + * @return {Point} The center point of this bounds. + */ + center: function () { + var center = {}; + center.x = (this.a.x + this.b.x) / 2.0; + center.y = (this.a.y + this.b.y) / 2.0; + return center; + }, + + + /** + * @return {Point} The center point of this bounds relative to upperLeft. + */ + midPoint: function () { + + var midpoint = {}; + midpoint.x = (this.b.x - this.a.x) / 2.0; + midpoint.y = (this.b.y - this.a.y) / 2.0; + return midpoint; + }, + + /** + * Moves the center point of this bounds to the new position. + * @param p {Point} + * or + * @param x {Number} + * @param y {Number} + */ + centerMoveTo: function () { + var currentPosition = this.center(); + + switch (arguments.length) { + + case 1: + this.moveBy(arguments[0].x - currentPosition.x, + arguments[0].y - currentPosition.y); + break; + + case 2: + this.moveBy(arguments[0] - currentPosition.x, + arguments[1] - currentPosition.y); + break; + } + }, + + isIncluded: function (point, offset) { + + var pointX, pointY, offset; + + // Get the the two Points + switch (arguments.length) { + case 1: + pointX = arguments[0].x; + pointY = arguments[0].y; + offset = 0; + + break; + case 2: + if (arguments[0].x && arguments[0].y) { + pointX = arguments[0].x; + pointY = arguments[0].y; + offset = Math.abs(arguments[1]); + } else { + pointX = arguments[0]; + pointY = arguments[1]; + offset = 0; + } + break; + case 3: + pointX = arguments[0]; + pointY = arguments[1]; + offset = Math.abs(arguments[2]); + break; + default: + throw "isIncluded needs one, two or three arguments"; + } + + var ul = this.upperLeft(); + var lr = this.lowerRight(); + + if (pointX >= ul.x - offset + && pointX <= lr.x + offset && pointY >= ul.y - offset + && pointY <= lr.y + offset) + return true; + else + return false; + }, + + /** + * @return {Bounds} A copy of this bounds. + */ + clone: function () { + + //Returns a new bounds object without the callback + // references of the original bounds + 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);/* + * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +/* + * All code Copyright 2013 KIS Consultancy all rights reserved + */ + +/** + * Init namespaces + */ +if (!ORYX) { + var ORYX = {}; +} +if (!ORYX.Core) { + ORYX.Core = {}; +} + + +/** + * @classDescription Abstract base class for all objects that have a graphical representation + * within the editor. + * @extends Clazz + */ +ORYX.Core.UIObject = { + /** + * Constructor of the UIObject class. + */ + construct: function (options) { + + this.isChanged = true; //Flag, if UIObject has been changed since last update. + this.isResized = true; + this.isVisible = true; //Flag, if UIObject's display attribute is set to 'inherit' or 'none' + this.isSelectable = false; //Flag, if UIObject is selectable. + this.isResizable = false; //Flag, if UIObject is resizable. + this.isMovable = false; //Flag, if UIObject is movable. + + this.id = ORYX.Editor.provideId(); //get unique id + this.parent = undefined; //parent is defined, if this object is added to another uiObject. + this.node = undefined; //this is a reference to the SVG representation, either locally or in DOM. + this.children = []; //array for all add uiObjects + + this.bounds = new ORYX.Core.Bounds(); //bounds with undefined values + + this._changedCallback = this._changed.bind(this); //callback reference for calling _changed + this.bounds.registerCallback(this._changedCallback); //set callback in bounds + + if (options && options.eventHandlerCallback) { + this.eventHandlerCallback = options.eventHandlerCallback; + } + }, + + /** + * Sets isChanged flag to true. Callback for the bounds object. + */ + _changed: function (bounds, isResized) { + this.isChanged = true; + if (this.bounds == bounds) + this.isResized = isResized || this.isResized; + }, + + /** + * If something changed, this method calls the refresh method that must be implemented by subclasses. + */ + update: function () { + if (this.isChanged) { + this.refresh(); + this.isChanged = false; + + //call update of all children + this.children.each(function (value) { + value.update(); + }); + } + }, + + /** + * Is called in update method, if isChanged is set to true. Sub classes should call the super class method. + */ + refresh: function () { + + }, + + /** + * @return {Array} Array of all child UIObjects. + */ + getChildren: function () { + return this.children.clone(); + }, + + /** + * @return {Array} Array of all parent UIObjects. + */ + getParents: function () { + var parents = []; + var parent = this.parent; + while (parent) { + parents.push(parent); + parent = parent.parent; + } + return parents; + }, + + /** + * Returns TRUE if the given parent is one of the UIObjects parents or the UIObject themselves, otherwise FALSE. + * @param {UIObject} parent + * @return {Boolean} + */ + isParent: function (parent) { + var cparent = this; + while (cparent) { + if (cparent === parent) { + return true; + } + cparent = cparent.parent; + } + return false; + }, + + /** + * @return {String} Id of this UIObject + */ + getId: function () { + return this.id; + }, + + /** + * Method for accessing child uiObjects by id. + * @param {String} id + * @param {Boolean} deep + * + * @return {UIObject} If found, it returns the UIObject with id. + */ + getChildById: function (id, deep) { + return this.children.find(function (uiObj) { + if (uiObj.getId() === id) { + return uiObj; + } else { + if (deep) { + var obj = uiObj.getChildById(id, deep); + if (obj) { + return obj; + } + } + } + }); + }, + + /** + * Adds an UIObject to this UIObject and sets the parent of the + * added UIObject. It is also added to the SVG representation of this + * UIObject. + * @param {UIObject} uiObject + */ + add: function (uiObject) { + //add uiObject, if it is not already a child of this object + if (!(this.children.member(uiObject))) { + //if uiObject is child of another parent, remove it from that parent. + if (uiObject.parent) { + uiObject.remove(uiObject); + } + + //add uiObject to children + this.children.push(uiObject); + + //set parent reference + uiObject.parent = this; + + //add uiObject.node to this.node + uiObject.node = this.node.appendChild(uiObject.node); + + //register callback to get informed, if child is changed + uiObject.bounds.registerCallback(this._changedCallback); + + //uiObject.update(); + } else { + ORYX.Log.info("add: ORYX.Core.UIObject is already a child of this object."); + } + }, + + /** + * Removes UIObject from this UIObject. The SVG representation will also + * be removed from this UIObject's SVG representation. + * @param {UIObject} uiObject + */ + remove: function (uiObject) { + //if uiObject is a child of this object, remove it. + if (this.children.member(uiObject)) { + //remove uiObject from children + this.children = this._uiObjects.without(uiObject); + + //delete parent reference of uiObject + uiObject.parent = undefined; + + //delete uiObject.node from this.node + uiObject.node = this.node.removeChild(uiObject.node); + + //unregister callback to get informed, if child is changed + uiObject.bounds.unregisterCallback(this._changedCallback); + } else { + ORYX.Log.info("remove: ORYX.Core.UIObject is not a child of this object."); + } + + }, + + /** + * Calculates absolute bounds of this UIObject. + */ + absoluteBounds: function () { + if (this.parent) { + var absUL = this.absoluteXY(); + return new ORYX.Core.Bounds(absUL.x, absUL.y, + absUL.x + this.bounds.width(), + absUL.y + this.bounds.height()); + } else { + return this.bounds.clone(); + } + }, + + /** + * @return {Point} The absolute position of this UIObject. + */ + absoluteXY: function () { + if (this.parent) { + var pXY = this.parent.absoluteXY(); + var result = {}; + result.x = pXY.x + this.bounds.upperLeft().x; + result.y = pXY.y + this.bounds.upperLeft().y; + return result; + } else { + var result = {}; + result.x = this.bounds.upperLeft().x; + result.y = this.bounds.upperLeft().y; + return result; + } + }, + + /** + * @return {Point} The absolute position from the Center of this UIObject. + */ + absoluteCenterXY: function () { + if (this.parent) { + var pXY = this.parent.absoluteXY(); + var result = {}; + result.x = pXY.x + this.bounds.center().x; + result.y = pXY.y + this.bounds.center().y; + return result; + + } else { + var result = {}; + result.x = this.bounds.center().x; + result.y = this.bounds.center().y; + return result; + } + }, + + /** + * Hides this UIObject and all its children. + */ + hide: function () { + this.node.setAttributeNS(null, 'display', 'none'); + this.isVisible = false; + this.children.each(function (uiObj) { + uiObj.hide(); + }); + }, + + /** + * Enables visibility of this UIObject and all its children. + */ + show: function () { + this.node.setAttributeNS(null, 'display', 'inherit'); + this.isVisible = true; + this.children.each(function (uiObj) { + uiObj.show(); + }); + }, + + addEventHandlers: function (node) { + + node.addEventListener(ORYX.CONFIG.EVENT_MOUSEDOWN, this._delegateEvent.bind(this), false); + node.addEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, this._delegateEvent.bind(this), false); + node.addEventListener(ORYX.CONFIG.EVENT_MOUSEUP, this._delegateEvent.bind(this), false); + node.addEventListener(ORYX.CONFIG.EVENT_MOUSEOVER, this._delegateEvent.bind(this), false); + node.addEventListener(ORYX.CONFIG.EVENT_MOUSEOUT, this._delegateEvent.bind(this), false); + node.addEventListener('click', this._delegateEvent.bind(this), false); + node.addEventListener(ORYX.CONFIG.EVENT_DBLCLICK, this._delegateEvent.bind(this), false); + + }, + + _delegateEvent: function (event) { + if (this.eventHandlerCallback) { + this.eventHandlerCallback(event, this); + } + }, + + toString: function () { + return "UIObject " + this.id + } +}; +ORYX.Core.UIObject = Clazz.extend(ORYX.Core.UIObject);/* + * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +/* + * All code Copyright 2013 KIS Consultancy all rights reserved + */ + +/** + * Init namespaces + */ +if (!ORYX) { + var ORYX = {}; +} +if (!ORYX.Core) { + ORYX.Core = {}; +} + +/** + * Top Level uiobject. + * @class ORYX.Core.AbstractShape + * @extends ORYX.Core.UIObject + */ +ORYX.Core.AbstractShape = ORYX.Core.UIObject.extend( + /** @lends ORYX.Core.AbstractShape.prototype */ + { + + /** + * Constructor + */ + construct: function (options, stencil, facade) { + + arguments.callee.$.construct.apply(this, arguments); + + this.resourceId = ORYX.Editor.provideId(); //Id of resource in DOM + + // stencil reference + this._stencil = stencil; + // if the stencil defines a super stencil that should be used for its instances, set it. + if (this._stencil._jsonStencil.superId) { + stencilId = this._stencil.id() + superStencilId = stencilId.substring(0, stencilId.indexOf("#") + 1) + stencil._jsonStencil.superId; + stencilSet = this._stencil.stencilSet(); + this._stencil = stencilSet.stencil(superStencilId); + } + + //Hash map for all properties. Only stores the values of the properties. + this.properties = new Hash(); + this.propertiesChanged = new Hash(); + + // List of properties which are not included in the stencilset, + // but which gets (de)serialized + this.hiddenProperties = new Hash(); + + + //Initialization of property map and initial value. + this._stencil.properties().each((function (property) { + var key = property.prefix() + "-" + property.id(); + this.properties[key] = property.value(); + this.propertiesChanged[key] = true; + }).bind(this)); + + // if super stencil was defined, also regard stencil's properties: + if (stencil._jsonStencil.superId) { + stencil.properties().each((function (property) { + var key = property.prefix() + "-" + property.id(); + var value = property.value(); + var oldValue = this.properties[key]; + this.properties[key] = value; + this.propertiesChanged[key] = true; + + // Raise an event, to show that the property has changed + // required for plugins like processLink.js + //window.setTimeout( function(){ + + this._delegateEvent({ + type: ORYX.CONFIG.EVENT_PROPERTY_CHANGED, + name: key, + value: value, + oldValue: oldValue + }); + + //}.bind(this), 10) + + }).bind(this)); + } + + }, + + layout: function () { + + }, + + /** + * Returns the stencil object specifiing the type of the shape. + */ + getStencil: function () { + return this._stencil; + }, + + /** + * + * @param {Object} resourceId + */ + getChildShapeByResourceId: function (resourceId) { + + resourceId = ERDF.__stripHashes(resourceId); + + return this.getChildShapes(true).find(function (shape) { + return shape.resourceId == resourceId + }); + }, + /** + * + * @param {Object} deep + * @param {Object} iterator + */ + getChildShapes: function (deep, iterator) { + var result = []; + + this.children.each(function (uiObject) { + if (uiObject instanceof ORYX.Core.Shape && uiObject.isVisible) { + if (iterator) { + iterator(uiObject); + } + result.push(uiObject); + if (deep) { + result = result.concat(uiObject.getChildShapes(deep, iterator)); + } + } + }); + + return result; + }, + + /** + * @param {Object} shape + * @return {boolean} true if any of shape's childs is given shape + */ + hasChildShape: function (shape) { + return this.getChildShapes().any(function (child) { + return (child === shape) || child.hasChildShape(shape); + }); + }, + + /** + * + * @param {Object} deep + * @param {Object} iterator + */ + getChildNodes: function (deep, iterator) { + var result = []; + + this.children.each(function (uiObject) { + if (uiObject instanceof ORYX.Core.Node && uiObject.isVisible) { + if (iterator) { + iterator(uiObject); + } + result.push(uiObject); + } + if (uiObject instanceof ORYX.Core.Shape) { + if (deep) { + result = result.concat(uiObject.getChildNodes(deep, iterator)); + } + } + }); + + return result; + }, + + /** + * + * @param {Object} deep + * @param {Object} iterator + */ + getChildEdges: function (deep, iterator) { + var result = []; + + this.children.each(function (uiObject) { + if (uiObject instanceof ORYX.Core.Edge && uiObject.isVisible) { + if (iterator) { + iterator(uiObject); + } + result.push(uiObject); + } + if (uiObject instanceof ORYX.Core.Shape) { + if (deep) { + result = result.concat(uiObject.getChildEdges(deep, iterator)); + } + } + }); + + return result; + }, + + /** + * Returns a sorted array of ORYX.Core.Node objects. + * Ordered in z Order, the last object has the highest z Order. + */ + //TODO deep iterator + getAbstractShapesAtPosition: function () { + var x, y; + switch (arguments.length) { + case 1: + x = arguments[0].x; + y = arguments[0].y; + break; + case 2: //two or more arguments + x = arguments[0]; + y = arguments[1]; + break; + default: + throw "getAbstractShapesAtPosition needs 1 or 2 arguments!" + } + + if (this.isPointIncluded(x, y)) { + + var result = []; + result.push(this); + + //check, if one child is at that position + + + var childNodes = this.getChildNodes(); + var childEdges = this.getChildEdges(); + + [childNodes, childEdges].each(function (ne) { + var nodesAtPosition = new Hash(); + + ne.each(function (node) { + if (!node.isVisible) { + return + } + var candidates = node.getAbstractShapesAtPosition(x, y); + if (candidates.length > 0) { + var nodesInZOrder = $A(node.node.parentNode.childNodes); + var zOrderIndex = nodesInZOrder.indexOf(node.node); + nodesAtPosition[zOrderIndex] = candidates; + } + }); + + nodesAtPosition.keys().sort().each(function (key) { + result = result.concat(nodesAtPosition[key]); + }); + }); + + return result; + + } else { + return []; + } + }, + + /** + * + * @param key {String} Must be 'prefix-id' of property + * @param value {Object} Can be of type String or Number according to property type. + */ + setProperty: function (key, value, force) { + var oldValue = this.properties[key]; + if (oldValue !== value || force === true) { + this.properties[key] = value; + this.propertiesChanged[key] = true; + this._changed(); + + // Raise an event, to show that the property has changed + //window.setTimeout( function(){ + + if (!this._isInSetProperty) { + this._isInSetProperty = true; + + this._delegateEvent({ + type: ORYX.CONFIG.EVENT_PROPERTY_CHANGED, + elements: [this], + name: key, + value: value, + oldValue: oldValue + }); + + delete this._isInSetProperty; + } + //}.bind(this), 10) + } + }, + + /** + * Returns TRUE if one of the properties is flagged as dirty + * @return {boolean} + */ + isPropertyChanged: function () { + return this.propertiesChanged.any(function (property) { + return property.value + }); + }, + + /** + * + * @param {String} Must be 'prefix-id' of property + * @param {Object} Can be of type String or Number according to property type. + */ + setHiddenProperty: function (key, value) { + // IF undefined, Delete + if (value === undefined) { + delete this.hiddenProperties[key]; + return; + } + var oldValue = this.hiddenProperties[key]; + if (oldValue !== value) { + this.hiddenProperties[key] = value; + } + }, + /** + * Calculate if the point is inside the Shape + * @param {Point} + */ + isPointIncluded: function (pointX, pointY, absoluteBounds) { + var absBounds = absoluteBounds ? absoluteBounds : this.absoluteBounds(); + return absBounds.isIncluded(pointX, pointY); + + }, + + /** + * Get the serialized object + * return Array with hash-entrees (prefix, name, value) + * Following values will given: + * Type + * Properties + */ + serialize: function () { + var serializedObject = []; + + // Add the type + serializedObject.push({name: 'type', prefix: 'oryx', value: this.getStencil().id(), type: 'literal'}); + + // Add hidden properties + this.hiddenProperties.each(function (prop) { + serializedObject.push({ + name: prop.key.replace("oryx-", ""), + prefix: "oryx", + value: prop.value, + type: 'literal' + }); + }.bind(this)); + + // Add all properties + this.getStencil().properties().each((function (property) { + + var prefix = property.prefix(); // Get prefix + var name = property.id(); // Get name + + //if(typeof this.properties[prefix+'-'+name] == 'boolean' || this.properties[prefix+'-'+name] != "") + serializedObject.push({ + name: name, + prefix: prefix, + value: this.properties[prefix + '-' + name], + type: 'literal' + }); + + }).bind(this)); + + return serializedObject; + }, + + + deserialize: function (serialize) { + // Search in Serialize + var initializedDocker = 0; + + // Sort properties so that the hidden properties are first in the list + serialize = 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)); + + serialize.each((function (obj) { + + var name = obj.name; + var prefix = obj.prefix; + var value = obj.value; + + // Complex properties can be real json objects, encode them to a string + if (Object.prototype.toString.call(value) === "Object") value = JSON.stringify(value); + + switch (prefix + "-" + name) { + case 'raziel-parent': + // Set parent + if (!this.parent) { + break + } + ; + + // Set outgoing Shape + var parent = this.getCanvas().getChildShapeByResourceId(value); + if (parent) { + parent.add(this); + } + + break; + default: + // If list, eval as an array + var prop = this.getStencil().property(prefix + "-" + name); + if (prop && prop.isList() && typeof value === "string") { + if ((value || "").strip() && !value.startsWith("[") && !value.startsWith("]")) + value = "[\"" + value.strip() + "\"]"; + value = ((value || "").strip() || "[]").evalJSON(); + } + + // Set property + if (this.properties.keys().member(prefix + "-" + name)) { + this.setProperty(prefix + "-" + name, value); + } else if (!(name === "bounds" || name === "parent" || name === "target" || name === "dockers" || name === "docker" || name === "outgoing" || name === "incoming")) { + this.setHiddenProperty(prefix + "-" + name, value); + } + + } + }).bind(this)); + }, + + toString: function () { + return "ORYX.Core.AbstractShape " + this.id + }, + + /** + * Converts the shape to a JSON representation. + * @return {Object} A JSON object with included ORYX.Core.AbstractShape.JSONHelper and getShape() method. + */ + toJSON: function () { + var json = { + resourceId: this.resourceId, + properties: jQuery.extend({}, this.properties, this.hiddenProperties).inject({}, function (props, prop) { + var key = prop[0]; + var value = prop[1]; + + //If complex property, value should be a json object + if (this.getStencil().property(key) + && this.getStencil().property(key).type() === ORYX.CONFIG.TYPE_COMPLEX + && Object.prototype.toString.call(value) === "String") { + + try { + value = JSON.parse(value); + } catch (error) { + } + //try {value = JSON.parse(value);} catch(error){} + + // Parse date + } else if (value instanceof Date && this.getStencil().property(key)) { + try { + value = value.format(this.getStencil().property(key).dateFormat()); + } catch (e) { + } + } + + //Takes "my_property" instead of "oryx-my_property" as key + key = key.replace(/^[\w_]+-/, ""); + props[key] = value; + + return props; + }.bind(this)), + stencil: { + id: this.getStencil().idWithoutNs() + }, + childShapes: this.getChildShapes().map(function (shape) { + return shape.toJSON(); + }) + }; + + if (this.getOutgoingShapes) { + json.outgoing = this.getOutgoingShapes().map(function (shape) { + return { + resourceId: shape.resourceId + }; + }); + } + + if (this.bounds) { + json.bounds = { + lowerRight: this.bounds.lowerRight(), + upperLeft: this.bounds.upperLeft() + }; + } + + if (this.dockers) { + json.dockers = this.dockers.map(function (docker) { + var d = docker.getDockedShape() && docker.referencePoint ? docker.referencePoint : docker.bounds.center(); + d.getDocker = function () { + return docker; + }; + return d; + }); + } + + jQuery.extend(json, ORYX.Core.AbstractShape.JSONHelper); + + // do not pollute the json attributes (for serialization), so put the corresponding + // shape is encapsulated in a method + json.getShape = function () { + return this; + }.bind(this); + + return json; + } + }); + +/** + * @namespace Collection of methods which can be used on a shape json object (ORYX.Core.AbstractShape#toJSON()). + * @example + * jQuery.extend(shapeAsJson, ORYX.Core.AbstractShape.JSONHelper); + */ +ORYX.Core.AbstractShape.JSONHelper = { + /** + * Iterates over each child shape. + * @param {Object} iterator Iterator function getting a child shape and his parent as arguments. + * @param {boolean} [deep=false] Iterate recursively (childShapes of childShapes) + * @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. + * @example + * // Increases the lowerRight x value of each direct child shape by one. + * myShapeAsJson.eachChild(function(shape, parentShape){ + * shape.bounds.lowerRight.x = shape.bounds.lowerRight.x + 1; + * return shape; + * }, false, true); + */ + eachChild: function (iterator, deep, modify) { + if (!this.childShapes) return; + + var newChildShapes = []; //needed if modify = true + + this.childShapes.each(function (shape) { + if (!(shape.eachChild instanceof Function)) { + jQuery.extend(shape, ORYX.Core.AbstractShape.JSONHelper); + } + var res = iterator(shape, this); + if (res) newChildShapes.push(res); //if false is returned, and modify = true, current shape is deleted. + + if (deep) shape.eachChild(iterator, deep, modify); + }.bind(this)); + + if (modify) this.childShapes = newChildShapes; + }, + + getShape: function () { + return null; + }, + getChildShapes: function (deep) { + var allShapes = this.childShapes; + + if (deep) { + this.eachChild(function (shape) { + if (!(shape.getChildShapes instanceof Function)) { + jQuery.extend(shape, ORYX.Core.AbstractShape.JSONHelper); + } + allShapes = allShapes.concat(shape.getChildShapes(deep)); + }, true); + } + + return allShapes; + }, + + /** + * @return {String} Serialized JSON object + */ + serialize: function () { + return JSON.stringify(this); + } +} +/* + * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +/* + * All code Copyright 2013 KIS Consultancy all rights reserved + */ + +/** + * Init namespaces + */ +if (!ORYX) { + var ORYX = {}; +} + +/** + @namespace Namespace for the Oryx core elements. + @name ORYX.Core + */ +if (!ORYX.Core) { + ORYX.Core = {}; +} + +/** + * @class Oryx canvas. + * @extends ORYX.Core.AbstractShape + * + */ +ORYX.Core.Canvas = ORYX.Core.AbstractShape.extend({ + /** @lends ORYX.Core.Canvas.prototype */ + + /** + * Defines the current zoom level + */ + zoomLevel: 1, + + /** + * Constructor + */ + construct: function (options, stencil, facade) { + arguments.callee.$.construct.apply(this, arguments); + + if (!(options && options.width && options.height)) { + + ORYX.Log.fatal("Canvas is missing mandatory parameters options.width and options.height."); + return; + } + this.facade = facade; + //TODO: set document resource id + this.resourceId = options.id; + + this.nodes = []; + + this.edges = []; + + // Row highlighting states + this.colHighlightState = 0; + + this.colHighlightEnabled = false; + + //init svg document + this.rootNode = ORYX.Editor.graft("http://www.w3.org/2000/svg", options.parentNode, + ['svg', {id: this.id, width: options.width, height: options.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", options.parentNode, + ['div', {id: "oryx_canvas_htmlContainer", style: "position:absolute; top:5px"}]); + + // Additional SVG-node BELOW the stencils to allow underlays (if that is even a word) by plugins + this.underlayNode = ORYX.Editor.graft("http://www.w3.org/2000/svg", this.rootNode, + ['svg', {id: "underlay-container"}]); + + // Create 2 svg-elements in the svg-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"}] + ]); + + /* + var off = 2 * ORYX.CONFIG.GRID_DISTANCE; + var size = 3; + var d = ""; + for(var i = 0; i <= options.width; i += off) + for(var j = 0; j <= options.height; j += off) + d = d + "M" + (i - size) + " " + j + " l" + (2*size) + " 0 m" + (-size) + " " + (-size) + " l0 " + (2*size) + " m0" + (-size) + " "; + + ORYX.Editor.graft("http://www.w3.org/2000/svg", this.node.firstChild.firstChild, + ['path', {d:d , stroke:'#000000', 'stroke-width':'0.15px'},]); + */ + + //Global definition of default font for shapes + //Definitions in the SVG definition of a stencil will overwrite these settings for + // that stencil. + /*if(navigator.platform.indexOf("Mac") > -1) { + this.node.setAttributeNS(null, 'stroke', 'black'); + this.node.setAttributeNS(null, 'stroke-width', '0.5px'); + this.node.setAttributeNS(null, 'font-family', 'Skia'); + //this.node.setAttributeNS(null, 'letter-spacing', '2px'); + this.node.setAttributeNS(null, 'font-size', ORYX.CONFIG.LABEL_DEFAULT_LINE_HEIGHT); + } else { + this.node.setAttributeNS(null, 'stroke', 'none'); + this.node.setAttributeNS(null, 'font-family', 'Verdana'); + this.node.setAttributeNS(null, 'font-size', ORYX.CONFIG.LABEL_DEFAULT_LINE_HEIGHT); + }*/ + + 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, options.width, options.height); + + this.addEventHandlers(this.rootNode.parentNode); + + //disable context menu + this.rootNode.oncontextmenu = function () { + return false; + }; + }, + + focus: function () { + + try { + // Get a href + if (!this.focusEl) { + this.focusEl = jQuery('body').append(jQuery('')); + this.focusEl.swallowEvent("click", true); + } + + // Focus it + this.focusEl.focus.defer(1, this.focusEl); + this.focusEl.blur.defer(3, this.focusEl); + + } catch (e) { + } + }, + + setHightlightState: function (state) { + if (this.colHighlightEnabled && this.colHighlightState != state) { + if (state == 0) { + this.columnHightlight1.setAttribute("visibility", "hidden"); + this.columnHightlight2.setAttribute("visibility", "hidden"); + } else if (state == 1) { + this.columnHightlight1.setAttribute("visibility", "visible"); + this.columnHightlight2.setAttribute("visibility", "hidden"); + } else if (state == 2) { + this.columnHightlight1.setAttribute("visibility", "hidden"); + this.columnHightlight2.setAttribute("visibility", "visible"); + } else if (state == 3) { + this.columnHightlight1.setAttribute("visibility", "visible"); + this.columnHightlight2.setAttribute("visibility", "visible"); + } + this.colHighlightState = state; + } + }, + + setHightlightStateBasedOnX: function (x) { + if (x > ORYX.CONFIG.FORM_ROW_WIDTH + 30) { + this.setHightlightState(2); + } else { + this.setHightlightState(1); + } + }, + + update: function () { + + this.nodes.each(function (node) { + this._traverseForUpdate(node); + }.bind(this)); + + // call stencil's layout callback + // (needed for row layouting of xforms) + //this.getStencil().layout(this); + + var layoutEvents = this.getStencil().layout(); + + if (layoutEvents) { + layoutEvents.each(function (event) { + + // setup additional attributes + event.shape = this; + event.forceExecution = true; + event.target = this.rootNode; + + // do layouting + + this._delegateEvent(event); + }.bind(this)) + } + + this.nodes.invoke("_update"); + + this.edges.invoke("_update", true); + + /*this.children.each(function(child) { + child._update(); + });*/ + }, + + _traverseForUpdate: function (shape) { + var childRet = shape.isChanged; + shape.getChildNodes(false, function (child) { + if (this._traverseForUpdate(child)) { + childRet = true; + } + }.bind(this)); + + if (childRet) { + shape.layout(); + return true; + } else { + return false; + } + }, + + layout: function () { + + + }, + + /** + * + * @param {Object} deep + * @param {Object} iterator + */ + getChildNodes: function (deep, iterator) { + if (!deep && !iterator) { + return this.nodes.clone(); + } else { + var result = []; + this.nodes.each(function (uiObject) { + if (iterator) { + iterator(uiObject); + } + result.push(uiObject); + + if (deep && uiObject instanceof ORYX.Core.Shape) { + result = result.concat(uiObject.getChildNodes(deep, iterator)); + } + }); + + return result; + } + }, + + /** + * buggy crap! use base class impl instead! + * @param {Object} iterator + */ + /* getChildEdges: function(iterator) { + if(iterator) { + this.edges.each(function(edge) { + iterator(edge); + }); + } + + return this.edges.clone(); + }, +*/ + /** + * Overrides the UIObject.add method. Adds uiObject to the correct sub node. + * @param {UIObject} uiObject + */ + add: function (uiObject, index, silent) { + //if uiObject is child of another UIObject, remove it. + if (uiObject instanceof ORYX.Core.UIObject) { + if (!(this.children.member(uiObject))) { + //if uiObject is child of another parent, remove it from that parent. + if (uiObject.parent) { + uiObject.parent.remove(uiObject, true); + } + + //add uiObject to the Canvas + //add uiObject to this Shape + if (index != undefined) + this.children.splice(index, 0, uiObject); + else + this.children.push(uiObject); + + //set parent reference + uiObject.parent = this; + + //add uiObject.node to this.node depending on the type of uiObject + if (uiObject instanceof ORYX.Core.Shape) { + if (uiObject instanceof ORYX.Core.Edge) { + uiObject.addMarkers(this.rootNode.getElementsByTagNameNS(NAMESPACE_SVG, "defs")[0]); + uiObject.node = this.node.childNodes[0].childNodes[2].appendChild(uiObject.node); + this.edges.push(uiObject); + } else { + uiObject.node = this.node.childNodes[0].childNodes[1].appendChild(uiObject.node); + this.nodes.push(uiObject); + } + } else { //UIObject + uiObject.node = this.node.appendChild(uiObject.node); + } + + uiObject.bounds.registerCallback(this._changedCallback); + + if (this.eventHandlerCallback && silent !== true) + this.eventHandlerCallback({type: ORYX.CONFIG.EVENT_SHAPEADDED, shape: uiObject}) + } 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."); + } + }, + + /** + * Overrides the UIObject.remove method. Removes uiObject. + * @param {UIObject} uiObject + */ + remove: function (uiObject, silent) { + //if uiObject is a child of this object, remove it. + if (this.children.member(uiObject)) { + //remove uiObject from children + var parent = uiObject.parent; + + this.children = this.children.without(uiObject); + + //delete parent reference of uiObject + uiObject.parent = undefined; + + //delete uiObject.node from this.node + if (uiObject instanceof ORYX.Core.Shape) { + if (uiObject instanceof ORYX.Core.Edge) { + uiObject.removeMarkers(); + uiObject.node = this.node.childNodes[0].childNodes[2].removeChild(uiObject.node); + this.edges = this.edges.without(uiObject); + } else { + uiObject.node = this.node.childNodes[0].childNodes[1].removeChild(uiObject.node); + this.nodes = this.nodes.without(uiObject); + } + } else { //UIObject + uiObject.node = this.node.removeChild(uiObject.node); + } + + if (this.eventHandlerCallback && silent !== true) + this.eventHandlerCallback({type: ORYX.CONFIG.EVENT_SHAPEREMOVED, shape: uiObject, parent: parent}); + + uiObject.bounds.unregisterCallback(this._changedCallback); + } else { + + ORYX.Log.warn("remove: ORYX.Core.UIObject is not a child of this object."); + } + }, + + /** + * Creates shapes out of the given collection of shape objects and adds them to the canvas. + * @example + * canvas.addShapeObjects({ + bounds:{ lowerRight:{ y:510, x:633 }, upperLeft:{ y:146, x:210 } }, + resourceId:"oryx_F0715955-50F2-403D-9851-C08CFE70F8BD", + childShapes:[], + properties:{}, + stencil:{ + id:"Subprocess" + }, + outgoing:[{resourceId: 'aShape'}], + target: {resourceId: 'aShape'} + }); + * @param {Object} shapeObjects + * @param {Function} [eventHandler] An event handler passed to each newly created shape (as eventHandlerCallback) + * @return {Array} A collection of ORYX.Core.Shape + * @methodOf ORYX.Core.Canvas.prototype + */ + addShapeObjects: function (shapeObjects, eventHandler) { + if (!shapeObjects) return; + + this.initializingShapes = true; + + /*FIXME This implementation is very evil! At first, all shapes are created on + canvas. In a second step, the attributes are applied. There must be a distinction + between the configuration phase (where the outgoings, for example, are just named), + and the creation phase (where the outgoings are evaluated). This must be reflected + in code to provide a nicer API/ implementation!!! */ + + var addShape = function (shape, parent) { + // Create a new Stencil + var stencil = ORYX.Core.StencilSet.stencil(this.getStencil().namespace() + shape.stencil.id); + + // Create a new Shape + var ShapeClass = (stencil.type() == "node") ? ORYX.Core.Node : ORYX.Core.Edge; + var newShape = new ShapeClass( + {'eventHandlerCallback': eventHandler}, + stencil, this.facade); + + // Set the resource id + newShape.resourceId = shape.resourceId; + newShape.node.id = "svg-" + shape.resourceId; + + // Set parent to json object to be used later + // Due to the nested json structure, normally shape.parent is not set/ must not be set. + // In special cases, it can be easier to set this directly instead of a nested structure. + shape.parent = "#" + ((shape.parent && shape.parent.resourceId) || parent.resourceId); + + // Add the shape to the canvas + this.add(newShape); + + return { + json: shape, + object: newShape + }; + }.bind(this); + + /** Builds up recursively a flatted array of shapes, including a javascript object and json representation + * @param {Object} shape Any object that has Object#childShapes + */ + var addChildShapesRecursively = function (shape) { + var addedShapes = []; + + if (shape.childShapes && shape.childShapes.constructor == String) { + shape.childShapes = JSON.parse(shape.childShapes); + } + + shape.childShapes.each(function (childShape) { + addedShapes.push(addShape(childShape, shape)); + addedShapes = addedShapes.concat(addChildShapesRecursively(childShape)); + }); + + return addedShapes; + }.bind(this); + + var shapes = addChildShapesRecursively({ + childShapes: shapeObjects, + resourceId: this.resourceId + }); + + + // prepare deserialisation parameter + shapes.each( + function (shape) { + var properties = []; + for (field in shape.json.properties) { + properties.push({ + prefix: 'oryx', + name: field, + value: shape.json.properties[field] + }); + } + + // Outgoings + shape.json.outgoing.each(function (out) { + properties.push({ + prefix: 'raziel', + name: 'outgoing', + value: "#" + out.resourceId + }); + }); + + // Target + // (because of a bug, the first outgoing is taken when there is no target, + // can be removed after some time) + if (shape.object instanceof ORYX.Core.Edge) { + var target = shape.json.target || shape.json.outgoing[0]; + if (target) { + properties.push({ + prefix: 'raziel', + name: 'target', + value: "#" + target.resourceId + }); + } + } + + // Bounds + if (shape.json.bounds) { + properties.push({ + prefix: 'oryx', + name: 'bounds', + value: shape.json.bounds.upperLeft.x + "," + shape.json.bounds.upperLeft.y + "," + shape.json.bounds.lowerRight.x + "," + shape.json.bounds.lowerRight.y + }); + } + + //Dockers [{x:40, y:50}, {x:30, y:60}] => "40 50 30 60 #" + if (shape.json.dockers) { + properties.push({ + prefix: 'oryx', + name: 'dockers', + value: shape.json.dockers.inject("", function (dockersStr, docker) { + return dockersStr + docker.x + " " + docker.y + " "; + }) + " #" + }); + } + + //Parent + properties.push({ + prefix: 'raziel', + name: 'parent', + value: shape.json.parent + }); + + shape.__properties = properties; + }.bind(this) + ); + + // Deserialize the properties from the shapes + // This can't be done earlier because Shape#deserialize expects that all referenced nodes are already there + + // first, deserialize all nodes + shapes.each(function (shape) { + if (shape.object instanceof ORYX.Core.Node) { + shape.object.deserialize(shape.__properties, shape.json); + } + }); + + // second, deserialize all edges + shapes.each(function (shape) { + if (shape.object instanceof ORYX.Core.Edge) { + shape.object.deserialize(shape.__properties, shape.json); + shape.object._oldBounds = shape.object.bounds.clone(); + shape.object._update(); + } + }); + + delete this.initializingShapes; + return shapes.pluck("object"); + }, + + /** + * Updates the size of the canvas, regarding to the containg shapes. + */ + updateSize: function () { + // Check the size for the canvas + var maxWidth = 0; + var maxHeight = 0; + var offset = 100; + this.getChildShapes(true, function (shape) { + var b = shape.bounds; + maxWidth = Math.max(maxWidth, b.lowerRight().x + offset) + maxHeight = Math.max(maxHeight, b.lowerRight().y + offset) + }); + + if (this.bounds.width() < maxWidth || this.bounds.height() < maxHeight) { + this.setSize({ + width: Math.max(this.bounds.width(), maxWidth), + height: Math.max(this.bounds.height(), maxHeight) + }) + } + }, + + getRootNode: function () { + return this.rootNode; + }, + + getUnderlayNode: function () { + return this.underlayNode; + }, + + getSvgContainer: function () { + return this.node.childNodes[1]; + }, + + getHTMLContainer: function () { + return this._htmlContainer; + }, + + /** + * Return all elements of the same highest level + * @param {Object} elements + */ + getShapesWithSharedParent: function (elements) { + + // If there is no elements, return [] + if (!elements || elements.length < 1) { + return []; + } + // If there is one element, return this element + if (elements.length == 1) { + return elements; + } + + return elements.findAll(function (value) { + var parentShape = value.parent; + while (parentShape) { + if (elements.member(parentShape)) return false; + parentShape = parentShape.parent; + } + return true; + }); + + }, + + setSize: function (size, dontSetBounds) { + if (!size || !size.width || !size.height) { + return; + } + ; + + if (this.rootNode.parentNode) { + this.rootNode.parentNode.style.width = size.width + 'px'; + this.rootNode.parentNode.style.height = size.height + 'px'; + } + + this.rootNode.setAttributeNS(null, 'width', size.width); + this.rootNode.setAttributeNS(null, 'height', size.height); + + //this._htmlContainer.style.top = "-" + (size.height + 4) + 'px'; + if (!dontSetBounds) { + this.bounds.set({a: {x: 0, y: 0}, b: {x: size.width / this.zoomLevel, y: size.height / this.zoomLevel}}); + } + }, + + /** + * Returns an SVG document of the current process. + * @param {Boolean} escapeText Use true, if you want to parse it with an XmlParser, + * false, if you want to use the SVG document in browser on client side. + */ + getSVGRepresentation: function (escapeText) { + // Get the serialized svg image source + var svgClone = this.getRootNode().cloneNode(true); + + this._removeInvisibleElements(svgClone); + + var x1, y1, x2, y2; + this.getChildShapes(true).each(function (shape) { + var absBounds = shape.absoluteBounds(); + var ul = absBounds.upperLeft(); + var lr = absBounds.lowerRight(); + if (x1 == undefined) { + x1 = ul.x; + y1 = ul.y; + x2 = lr.x; + y2 = lr.y; + } else { + x1 = Math.min(x1, ul.x); + y1 = Math.min(y1, ul.y); + x2 = Math.max(x2, lr.x); + y2 = Math.max(y2, lr.y); + } + }); + + var margin = 50; + var width, height, tx, ty; + if (x1 == undefined) { + width = 0; + height = 0; + tx = 0; + ty = 0; + } else { + width = x2; + height = y2; + tx = -x1 + margin / 2; + ty = -y1 + margin / 2; + } + + // Set the width and height + svgClone.setAttributeNS(null, 'width', width + margin); + svgClone.setAttributeNS(null, 'height', height + margin); + + //remove scale factor + svgClone.childNodes[1].removeAttributeNS(null, 'transform'); + + try { + var svgCont = svgClone.childNodes[1].childNodes[1]; + svgCont.parentNode.removeChild(svgCont); + } catch (e) { + } + + if (escapeText) { + $A(svgClone.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'tspan')).each(function (elem) { + elem.textContent = elem.textContent.escapeHTML(); + }); + + $A(svgClone.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'text')).each(function (elem) { + if (elem.childNodes.length == 0) + elem.textContent = elem.textContent.escapeHTML(); + }); + } + + // generating absolute urls for the pdf-exporter + $A(svgClone.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'image')).each(function (elem) { + var href = elem.getAttributeNS("http://www.w3.org/1999/xlink", "href"); + + if (!href.match("^(http|https)://")) { + href = window.location.protocol + "//" + window.location.host + href; + elem.setAttributeNS("http://www.w3.org/1999/xlink", "href", href); + } + }); + + + // escape all links + $A(svgClone.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'a')).each(function (elem) { + elem.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", (elem.getAttributeNS("http://www.w3.org/1999/xlink", "href") || "").escapeHTML()); + }); + + return svgClone; + }, + + /** + * Removes all nodes (and its children) that has the + * attribute visibility set to "hidden" + */ + _removeInvisibleElements: function (element) { + var index = 0; + while (index < element.childNodes.length) { + var child = element.childNodes[index]; + if (child.getAttributeNS && + child.getAttributeNS(null, "visibility") === "hidden") { + element.removeChild(child); + } else { + this._removeInvisibleElements(child); + index++; + } + } + + }, + + /** + * This method checks all shapes on the canvas and removes all shapes that + * contain invalid bounds values or dockers values(NaN) + */ + /*cleanUp: function(parent) { + if (!parent) { + parent = this; + } + parent.getChildShapes().each(function(shape){ + var a = shape.bounds.a; + var b = shape.bounds.b; + if (isNaN(a.x) || isNaN(a.y) || isNaN(b.x) || isNaN(b.y)) { + parent.remove(shape); + } + else { + shape.getDockers().any(function(docker) { + a = docker.bounds.a; + b = docker.bounds.b; + if (isNaN(a.x) || isNaN(a.y) || isNaN(b.x) || isNaN(b.y)) { + parent.remove(shape); + return true; + } + return false; + }); + shape.getMagnets().any(function(magnet) { + a = magnet.bounds.a; + b = magnet.bounds.b; + if (isNaN(a.x) || isNaN(a.y) || isNaN(b.x) || isNaN(b.y)) { + parent.remove(shape); + return true; + } + return false; + }); + this.cleanUp(shape); + } + }.bind(this)); + },*/ + + _delegateEvent: function (event) { + if (this.eventHandlerCallback && (event.target == this.rootNode || event.target == this.rootNode.parentNode)) { + this.eventHandlerCallback(event, this); + } + }, + + toString: function () { + return "Canvas " + this.id + }, + + /** + * Calls {@link ORYX.Core.AbstractShape#toJSON} and adds some stencil set information. + */ + toJSON: function () { + var json = arguments.callee.$.toJSON.apply(this, arguments); + +// if(ORYX.CONFIG.STENCILSET_HANDLER.length > 0) { +// json.stencilset = { +// url: this.getStencil().stencilSet().namespace() +// }; +// } else { + json.stencilset = { + url: this.getStencil().stencilSet().source(), + namespace: this.getStencil().stencilSet().namespace() + }; +// } + + + return json; + } +});/* + * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +var idCounter = 0; +var ID_PREFIX = "resource"; + +/** + * Main initialization method. To be called when loading + * of the document, including all scripts, is completed. + */ +function init() { + + ORYX.Log.debug("Querying editor instances"); + + // Hack for WebKit to set the SVGElement-Classes + ORYX.Editor.setMissingClasses(); + + // If someone wants to create the editor instance himself + if (window.onOryxResourcesLoaded) { + window.onOryxResourcesLoaded(); + } + // Else fetch the model from server and display editor + else { + var modelId = window.location.search.substring(4); + var modelUrl = "./service/model/" + modelId + "/json"; + + ORYX.Editor.createByUrl(modelUrl); + } +} + +/** + @namespace Global Oryx name space + @name ORYX + */ +if (!ORYX) { + var ORYX = {}; +} + +/** + * The Editor class. + * @class ORYX.Editor + * @extends Clazz + * @param {Object} config An editor object, passed to {@link ORYX.Editor#loadSerialized} + * @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. + * @param {boolean} [config.fullscreen=true] Render editor in fullscreen mode or not. + * @param {String} config.stencilset.url Stencil set URL. + * @param {String} [config.stencil.id] Stencil type used for creating the canvas. + * @param {Object} config.properties Any properties applied to the canvas. + */ +ORYX.Editor = { + /** @lends ORYX.Editor.prototype */ + // Defines the global dom event listener + DOMEventListeners: new Hash(), + + // Defines the selection + selection: [], + + // Defines the current zoom level + zoomLevel: 1.0, + + construct: function (config) { + + // initialization. + this._eventsQueue = []; + this.loadedPlugins = []; + this.pluginsData = []; + + + //meta data about the model for the signavio warehouse + //directory, new, name, description, revision, model (the model data) + + this.modelMetaData = config; + + var model = config; + + this.id = model.modelId; + + if (config.model) { + model = config.model; + } + + if (!this.id) { + this.id = model.id; + if (!this.id) { + this.id = ORYX.Editor.provideId(); + } + } + + // Defines if the editor should be fullscreen or not + this.fullscreen = config.fullscreen !== false; + + // Initialize the eventlistener + this._initEventListener(); + + // Load particular stencilset + if (ORYX.CONFIG.BACKEND_SWITCH) { + var ssUrl = (model.stencilset.namespace || model.stencilset.url).replace("#", "%23"); + ORYX.Core.StencilSet.loadStencilSet(ssUrl, this.modelMetaData, this.id); + } else { + var ssUrl = model.stencilset.url; + ORYX.Core.StencilSet.loadStencilSet(ssUrl, this.modelMetaData, this.id); + } + + // CREATES the canvas + this._createCanvas(model.stencil ? model.stencil.id : null, model.properties); + + // GENERATES the whole EXT.VIEWPORT + this._generateGUI(); + + // Initializing of a callback to check loading ends + var loadPluginFinished = false; + var loadContentFinished = false; + var initFinished = function () { + if (!loadPluginFinished || !loadContentFinished) { + return + } + this._finishedLoading(); + }.bind(this) + + // LOAD the plugins + window.setTimeout(function () { + this.loadPlugins(); + loadPluginFinished = true; + initFinished(); + }.bind(this), 100); + + // LOAD the content of the current editor instance + window.setTimeout(function () { + this.loadSerialized(model, true); // Request the meta data as well + this.getCanvas().update(); + loadContentFinished = true; + initFinished(); + }.bind(this), 200); + }, + + _finishedLoading: function () { + // Raise Loaded Event + this.handleEvents({type: ORYX.CONFIG.EVENT_LOADED}) + }, + + _initEventListener: function () { + + // Register on Events + + document.documentElement.addEventListener(ORYX.CONFIG.EVENT_KEYDOWN, this.catchKeyDownEvents.bind(this), false); + document.documentElement.addEventListener(ORYX.CONFIG.EVENT_KEYUP, this.catchKeyUpEvents.bind(this), false); + + // Enable Key up and down Event + this._keydownEnabled = true; + this._keyupEnabled = true; + + this.DOMEventListeners[ORYX.CONFIG.EVENT_MOUSEDOWN] = []; + this.DOMEventListeners[ORYX.CONFIG.EVENT_MOUSEUP] = []; + this.DOMEventListeners[ORYX.CONFIG.EVENT_MOUSEOVER] = []; + this.DOMEventListeners[ORYX.CONFIG.EVENT_MOUSEOUT] = []; + this.DOMEventListeners[ORYX.CONFIG.EVENT_SELECTION_CHANGED] = []; + this.DOMEventListeners[ORYX.CONFIG.EVENT_MOUSEMOVE] = []; + + }, + + /** + * Generate the whole viewport of the + * Editor and initialized the Ext-Framework + * + */ + _generateGUI: function () { + + // Defines the layout height if it's NOT fullscreen + var layoutHeight = ORYX.CONFIG.WINDOW_HEIGHT; + var canvasParent = this.getCanvas().rootNode.parentNode; + + jQuery("#canvasSection").append(canvasParent); + + // Set the editor to the center, and refresh the size + canvasParent.parentNode.setAttributeNS(null, 'align', 'center'); + canvasParent.setAttributeNS(null, 'align', 'left'); + this.getCanvas().setSize({ + width: ORYX.CONFIG.CANVAS_WIDTH, + height: ORYX.CONFIG.CANVAS_HEIGHT + }); + + }, + + getAvailablePlugins: function () { + var curAvailablePlugins = ORYX.availablePlugins.clone(); + curAvailablePlugins.each(function (plugin) { + if (this.loadedPlugins.find(function (loadedPlugin) { + return loadedPlugin.type == this.name; + }.bind(plugin))) { + plugin.engaged = true; + } else { + plugin.engaged = false; + } + }.bind(this)); + return curAvailablePlugins; + }, + + loadScript: function (url, callback) { + var script = document.createElement("script") + script.type = "text/javascript"; + if (script.readyState) { //IE + script.onreadystatechange = function () { + if (script.readyState == "loaded" || script.readyState == "complete") { + script.onreadystatechange = null; + callback(); + } + }; + } else { //Others + script.onload = function () { + callback(); + }; + } + script.src = url; + document.getElementsByTagName("head")[0].appendChild(script); + }, + /** + * activate Plugin + * + * @param {String} name + * @param {Function} callback + * callback(sucess, [errorCode]) + * errorCodes: NOTUSEINSTENCILSET, REQUIRESTENCILSET, NOTFOUND, YETACTIVATED + */ + 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 there is an GUI-Plugin, they get all Plugins-Offer-Meta-Data + if (newPlugin.registryChanged) + newPlugin.registryChanged(me.pluginsData); + + // If there have an onSelection-Method it will pushed to the Editor Event-Handler + 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"); + //TODO error handling + } + }, + + /** + * Laden der Plugins + */ + loadPlugins: function () { + + // if there should be plugins but still are none, try again. + // TODO this should wait for every plugin respectively. + /*if (!ORYX.Plugins && ORYX.availablePlugins.length > 0) { + window.setTimeout(this.loadPlugins.bind(this), 100); + return; + }*/ + + var me = this; + var newPlugins = []; + + + var loadedStencilSetsNamespaces = this.getStencilSets().keys(); + + // Available Plugins will be initalize + var facade = this._getPluginFacade(); + + // If there is an Array where all plugins are described, than only take those + // (that comes from the usage of oryx with a mashup api) + if (ORYX.MashupAPI && ORYX.MashupAPI.loadablePlugins && ORYX.MashupAPI.loadablePlugins instanceof Array) { + + // Get the plugins from the available plugins (those who are in the plugins.xml) + ORYX.availablePlugins = $A(ORYX.availablePlugins).findAll(function (value) { + return ORYX.MashupAPI.loadablePlugins.include(value.name) + }) + + // Add those plugins to the list, which are only in the loadablePlugins list + ORYX.MashupAPI.loadablePlugins.each(function (className) { + if (!(ORYX.availablePlugins.find(function (val) { + return val.name == className + }))) { + ORYX.availablePlugins.push({name: className}); + } + }) + } + + + ORYX.availablePlugins.each(function (value) { + ORYX.Log.debug("Initializing plugin '%0'", value.name); + if ((!value.requires || !value.requires.namespaces || value.requires.namespaces.any(function (req) { + return loadedStencilSetsNamespaces.indexOf(req) >= 0 + })) && + (!value.notUsesIn || !value.notUsesIn.namespaces || !value.notUsesIn.namespaces.any(function (req) { + return loadedStencilSetsNamespaces.indexOf(req) >= 0 + })) && + /*only load activated plugins or undefined */ + (value.engaged || (value.engaged === undefined))) { + + try { + var className = eval(value.name); + if (className) { + var plugin = new className(facade, value); + plugin.type = value.name; + newPlugins.push(plugin); + plugin.engaged = true; + } + } catch (e) { + ORYX.Log.warn("Plugin %0 is not available %1", value.name, e); + } + + } else { + ORYX.Log.info("Plugin need a stencilset which is not loaded'", value.name); + } + + }); + + newPlugins.each(function (value) { + // If there is an GUI-Plugin, they get all Plugins-Offer-Meta-Data + if (value.registryChanged) + value.registryChanged(me.pluginsData); + + // If there have an onSelection-Method it will pushed to the Editor Event-Handler + if (value.onSelectionChanged) + me.registerOnEvent(ORYX.CONFIG.EVENT_SELECTION_CHANGED, value.onSelectionChanged.bind(value)); + }); + + this.loadedPlugins = newPlugins; + + this.registerPluginsOnKeyEvents(); + + this.setSelection(); + + }, + + /** + * Creates the Canvas + * @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. + * @param {Object} [canvasConfig] Any canvas properties (like language). + */ + _createCanvas: function (stencilType, canvasConfig) { + if (stencilType) { + // Add namespace to stencilType + if (stencilType.search(/^http/) === -1) { + stencilType = this.getStencilSets().values()[0].namespace() + stencilType; + } + } else { + // Get any root stencil type + stencilType = this.getStencilSets().values()[0].findRootStencilName(); + } + + // get the stencil associated with the type + var canvasStencil = ORYX.Core.StencilSet.stencil(stencilType); + + if (!canvasStencil) + ORYX.Log.fatal("Initialisation failed, because the stencil with the type %0 is not part of one of the loaded stencil sets.", stencilType); + + // create all dom + // TODO fix border, so the visible canvas has a double border and some spacing to the scrollbars + var div = ORYX.Editor.graft("http://www.w3.org/1999/xhtml", null, ['div']); + // set class for custom styling + div.addClassName("ORYX_Editor"); + + // create the canvas + 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: div + }, canvasStencil, this._getPluginFacade()); + + if (canvasConfig) { + // Migrate canvasConfig to an RDF-like structure + //FIXME this isn't nice at all because we don't want rdf any longer + var properties = []; + for (field in canvasConfig) { + properties.push({ + prefix: 'oryx', + name: field, + value: canvasConfig[field] + }); + } + + this._canvas.deserialize(properties); + } + + }, + + /** + * Returns a per-editor singleton plugin facade. + * To be used in plugin initialization. + */ + _getPluginFacade: function () { + + // if there is no pluginfacade already created: + if (!(this._pluginFacade)) + + // create it. + this._pluginFacade = { + + activatePluginByName: this.activatePluginByName.bind(this), + //deactivatePluginByName: this.deactivatePluginByName.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 it. + return this._pluginFacade; + }, + + isExecutingCommands: function () { + return !!this.commandExecuting; + }, + + /** + * Implementes the command pattern + * (The real usage of the command pattern + * is implemented and shown in the Plugins/undo.js) + * + * @param [] Array of commands + */ + executeCommands: function (commands) { + + if (!this.commandStack) { + this.commandStack = []; + } + if (!this.commandStackExecuted) { + this.commandStackExecuted = []; + } + + + this.commandStack = [].concat(this.commandStack) + .concat(commands); + + // Check if already executes + if (this.commandExecuting) { + return; + } + + // Start execution + this.commandExecuting = true; + + // Iterate over all commands + while (this.commandStack.length > 0) { + var command = this.commandStack.shift(); + // and execute it + command.execute(); + this.commandStackExecuted.push(command); + } + + // Raise event for executing commands + this.handleEvents({ + type: ORYX.CONFIG.EVENT_EXECUTE_COMMANDS, + commands: this.commandStackExecuted + }); + + // Remove temporary vars + delete this.commandStack; + delete this.commandStackExecuted; + delete this.commandExecuting; + + + this.updateSelection(); + + }, + + /** + * Returns JSON of underlying canvas (calls ORYX.Canvas#toJSON()). + * @return {Object} Returns JSON representation as JSON object. + */ + getJSON: function () { + delete Array.prototype.toJSON; + var canvasJSON = this.getCanvas().toJSON(); + canvasJSON.ssextensions = this.getStencilSets().values()[0].extensions().keys().findAll(function (sse) { + return !sse.endsWith('/meta#') + }); + return canvasJSON; + }, + + /** + * Serializes a call to toJSON(). + * @return {String} Returns JSON representation as string. + */ + getSerializedJSON: function () { + return JSON.stringify(this.getJSON()); + }, + + /** + * Imports shapes in JSON as expected by {@link ORYX.Editor#loadSerialized} + * @param {Object|String} jsonObject The (serialized) json object to be imported + * @param {boolean } [noSelectionAfterImport=false] Set to true if no shapes should be selected after import + * @throws {SyntaxError} If the serialized json object contains syntax errors + */ + importJSON: function (jsonObject, noSelectionAfterImport) { + + try { + jsonObject = this.renewResourceIds(jsonObject); + } catch (error) { + throw error; + } + //check, if the imported json model can be loaded in this editor + // (stencil set has to fit) + if (jsonObject.stencilset.namespace && jsonObject.stencilset.namespace !== this.getCanvas().getStencil().stencilSet().namespace()) { + alert(String.format(ORYX.I18N.JSONImport.wrongSS, jsonObject.stencilset.namespace, this.getCanvas().getStencil().stencilSet().namespace())); + return null; + } else { + var commandClass = ORYX.Core.Command.extend({ + construct: function (jsonObject, loadSerializedCB, noSelectionAfterImport, facade) { + this.jsonObject = jsonObject; + this.noSelection = noSelectionAfterImport; + this.facade = facade; + this.shapes; + this.connections = []; + this.parents = new Hash(); + this.selection = this.facade.getSelection(); + this.loadSerialized = loadSerializedCB; + }, + execute: function () { + + if (!this.shapes) { + // Import the shapes out of the serialization + this.shapes = this.loadSerialized(this.jsonObject); + + //store all connections + this.shapes.each(function (shape) { + + if (shape.getDockers) { + var dockers = shape.getDockers(); + if (dockers) { + if (dockers.length > 0) { + this.connections.push([dockers.first(), dockers.first().getDockedShape(), dockers.first().referencePoint]); + } + if (dockers.length > 1) { + this.connections.push([dockers.last(), dockers.last().getDockedShape(), dockers.last().referencePoint]); + } + } + } + + //store parents + this.parents[shape.id] = shape.parent; + }.bind(this)); + } else { + this.shapes.each(function (shape) { + this.parents[shape.id].add(shape); + }.bind(this)); + + this.connections.each(function (con) { + con[0].setDockedShape(con[1]); + con[0].setReferencePoint(con[2]); + con[0].update(); + }); + } + + //this.parents.values().uniq().invoke("update"); + this.facade.getCanvas().update(); + + if (!this.noSelection) + this.facade.setSelection(this.shapes); + else + this.facade.updateSelection(); + + // call updateSize again, because during loadSerialized the edges' bounds + // are not yet initialized properly + this.facade.getCanvas().updateSize(); + + }, + rollback: function () { + var selection = this.facade.getSelection(); + + this.shapes.each(function (shape) { + selection = selection.without(shape); + this.facade.deleteShape(shape); + }.bind(this)); + + /*this.parents.values().uniq().each(function(parent) { + if(!this.shapes.member(parent)) + parent.update(); + }.bind(this));*/ + + this.facade.getCanvas().update(); + + this.facade.setSelection(selection); + } + }) + + var command = new commandClass(jsonObject, + this.loadSerialized.bind(this), + noSelectionAfterImport, + this._getPluginFacade()); + + this.executeCommands([command]); + + return command.shapes.clone(); + } + }, + + /** + * This method renew all resource Ids and according references. + * Warning: The implementation performs a substitution on the serialized object for + * easier implementation. This results in a low performance which is acceptable if this + * is only used when importing models. + * @param {Object|String} jsonObject + * @throws {SyntaxError} If the serialized json object contains syntax errors. + * @return {Object} The jsonObject with renewed ids. + * @private + */ + renewResourceIds: function (jsonObject) { + // For renewing resource ids, a serialized and object version is needed + if (Object.prototype.toString.call(jsonObject) === "String") { + try { + var serJsonObject = jsonObject; + jsonObject = JSON.parse(jsonObject); + } catch (error) { + throw new SyntaxError(error.message); + } + } else { + var serJsonObject = JSON.stringify(jsonObject); + } + + // collect all resourceIds recursively + var collectResourceIds = function (shapes) { + if (!shapes) return []; + + return shapes.map(function (shape) { + return collectResourceIds(shape.childShapes).concat(shape.resourceId); + }).flatten(); + } + var resourceIds = collectResourceIds(jsonObject.childShapes); + + // Replace each resource id by a new one + resourceIds.each(function (oldResourceId) { + var newResourceId = ORYX.Editor.provideId(); + serJsonObject = serJsonObject.replace(new RegExp(oldResourceId, 'g'), newResourceId); + }); + + return JSON.parse(serJsonObject); + }, + + /** + * Loads serialized model to the oryx. + * @example + * editor.loadSerialized({ + * resourceId: "mymodel1", + * childShapes: [ + * { + * stencil:{ id:"Subprocess" }, + * outgoing:[{resourceId: 'aShape'}], + * target: {resourceId: 'aShape'}, + * bounds:{ lowerRight:{ y:510, x:633 }, upperLeft:{ y:146, x:210 } }, + * resourceId: "myshape1", + * childShapes:[], + * properties:{}, + * } + * ], + * properties:{ + * language: "English" + * }, + * stencilset:{ + * url:"http://localhost:8080/oryx/stencilsets/bpmn1.1/bpmn1.1.json" + * }, + * stencil:{ + * id:"BPMNDiagram" + * } + * }); + * @param {Object} model Description of the model to load. + * @param {Array} [model.ssextensions] List of stenctil set extensions. + * @param {String} model.stencilset.url + * @param {String} model.stencil.id + * @param {Array} model.childShapes + * @param {Array} [model.properties] + * @param {String} model.resourceId + * @return {ORYX.Core.Shape[]} List of created shapes + * @methodOf ORYX.Editor.prototype + */ + loadSerialized: function (model, requestMeta) { + var canvas = this.getCanvas(); + + // Bugfix (cf. http://code.google.com/p/oryx-editor/issues/detail?id=240) + // Deserialize the canvas' stencil set extensions properties first! + this.loadSSExtensions(model.ssextensions); + + // Load Meta Data Extension if available + // #Signavio + if (requestMeta === true) { + var metaDataExtension = this.getExtensionForMetaData(); + if (metaDataExtension) { + this.loadSSExtension(metaDataExtension); + } + } + + var shapes = this.getCanvas().addShapeObjects(model.childShapes, this.handleEvents.bind(this)); + + if (model.properties) { + for (key in model.properties) { + var value = model.properties[key]; + var prop = this.getCanvas().getStencil().property("oryx-" + key); + if (!(typeof value === "string") && (!prop || !prop.isList())) { + value = JSON.stringify(value); + } + this.getCanvas().setProperty("oryx-" + key, value); + } + } + + + this.getCanvas().updateSize(); + + // Force to update the selection + this.selection = [null]; + this.setSelection([]); + + return shapes; + }, + + /** + * Return the namespace of the extension which + * provided all the self defined meta data + * @return {String} Returns null if no extension is defined, otherwise the namespace + * + */ + getExtensionForMetaData: function () { + if (!this.ss_extensions_def || !(this.ss_extensions_def.extensions instanceof Array)) { + return null; + } + + var stencilsets = this.getStencilSets(); + var extension = this.ss_extensions_def.extensions.find(function (ex) { + return !!stencilsets[ex["extends"]] && ex.namespace.endsWith("/meta#"); + }); + + return extension ? extension.namespace || null : null; + }, + + /** + * Calls ORYX.Editor.prototype.ss_extension_namespace for each element + * @param {Array} ss_extension_namespaces An array of stencil set extension namespaces. + */ + loadSSExtensions: function (ss_extension_namespaces) { + if (!ss_extension_namespaces) return; + + ss_extension_namespaces.each(function (ss_extension_namespace) { + this.loadSSExtension(ss_extension_namespace); + }.bind(this)); + }, + + /** + * Loads a stencil set extension. + * The stencil set extensions definiton file must already + * be loaded when the editor is initialized. + */ + loadSSExtension: function (ss_extension_namespace) { + + if (this.ss_extensions_def) { + var extension = this.ss_extensions_def.extensions.find(function (ex) { + return (ex.namespace == ss_extension_namespace); + }); + + if (!extension) { + return; + } + + var stencilset = this.getStencilSets()[extension["extends"]]; + + if (!stencilset) { + return; + } + + // Check if absolute or relative url + if ((extension["definition"] || "").startsWith("/")) { + stencilset.addExtension(extension["definition"]) + } else { + stencilset.addExtension(ORYX.CONFIG.SS_EXTENSIONS_FOLDER + extension["definition"]) + } + + //stencilset.addExtension("/oryx/build/stencilsets/extensions/" + extension["definition"]) + this.getRules().initializeRules(stencilset); + + this._getPluginFacade().raiseEvent({ + type: ORYX.CONFIG.EVENT_STENCIL_SET_LOADED + }); + } + + }, + + disableEvent: function (eventType) { + if (eventType == ORYX.CONFIG.EVENT_KEYDOWN) { + this._keydownEnabled = false; + } + if (eventType == ORYX.CONFIG.EVENT_KEYUP) { + this._keyupEnabled = false; + } + if (this.DOMEventListeners.keys().member(eventType)) { + var value = this.DOMEventListeners.remove(eventType); + this.DOMEventListeners['disable_' + eventType] = value; + } + }, + + enableEvent: function (eventType) { + if (eventType == ORYX.CONFIG.EVENT_KEYDOWN) { + this._keydownEnabled = true; + } + + if (eventType == ORYX.CONFIG.EVENT_KEYUP) { + this._keyupEnabled = true; + } + + if (this.DOMEventListeners.keys().member("disable_" + eventType)) { + var value = this.DOMEventListeners.remove("disable_" + eventType); + this.DOMEventListeners[eventType] = value; + } + }, + + /** + * Methods for the PluginFacade + */ + registerOnEvent: function (eventType, callback) { + if (!(this.DOMEventListeners.keys().member(eventType))) { + this.DOMEventListeners[eventType] = []; + } + + this.DOMEventListeners[eventType].push(callback); + }, + + unregisterOnEvent: function (eventType, callback) { + if (this.DOMEventListeners.keys().member(eventType)) { + this.DOMEventListeners[eventType] = this.DOMEventListeners[eventType].without(callback); + } else { + // Event is not supported + // TODO: Error Handling + } + }, + + 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 (source) { + try { + ORYX.Core.StencilSet.loadStencilSet(source, this.modelMetaData, this.id); + this.handleEvents({type: ORYX.CONFIG.EVENT_STENCIL_SET_LOADED}); + } catch (e) { + ORYX.Log.warn("Requesting stencil set file failed. (" + e + ")"); + } + }, + + offer: function (pluginData) { + if (!this.pluginsData.member(pluginData)) { + this.pluginsData.push(pluginData); + } + }, + + /** + * It creates an new event or adds the callback, if already existing, + * for the key combination that the plugin passes in keyCodes attribute + * of the offer method. + * + * The new key down event fits the schema: + * key.event[.metactrl][.alt][.shift].'thekeyCode' + */ + registerPluginsOnKeyEvents: function () { + this.pluginsData.each(function (pluginData) { + + if (pluginData.keyCodes) { + + pluginData.keyCodes.each(function (keyComb) { + var eventName = "key.event"; + + /* Include key action */ + eventName += '.' + keyComb.keyAction; + + if (keyComb.metaKeys) { + /* Register on ctrl or apple meta key as meta key */ + if (keyComb.metaKeys.indexOf(ORYX.CONFIG.META_KEY_META_CTRL) > -1) { + eventName += "." + ORYX.CONFIG.META_KEY_META_CTRL; + } + + /* Register on alt key as meta key */ + if (keyComb.metaKeys.indexOf(ORYX.CONFIG.META_KEY_ALT) > -1) { + eventName += '.' + ORYX.CONFIG.META_KEY_ALT; + } + + /* Register on shift key as meta key */ + if (keyComb.metaKeys.indexOf(ORYX.CONFIG.META_KEY_SHIFT) > -1) { + eventName += '.' + ORYX.CONFIG.META_KEY_SHIFT; + } + } + + /* Register on the actual key */ + if (keyComb.keyCode) { + eventName += '.' + keyComb.keyCode; + } + + /* Register the event */ + ORYX.Log.debug("Register Plugin on Key Event: %0", eventName); + if (pluginData.toggle === true && pluginData.buttonInstance) { + this.registerOnEvent(eventName, function () { + pluginData.buttonInstance.toggle(!pluginData.buttonInstance.pressed); // Toggle + pluginData.functionality.call(pluginData, pluginData.buttonInstance, pluginData.buttonInstance.pressed); // Call function + }); + } else { + this.registerOnEvent(eventName, pluginData.functionality) + } + + }.bind(this)); + } + }.bind(this)); + }, + + isEqual: function (a, b) { + return a === b || (a.length === b.length && a.all(function (r) { + return b.include(r) + })) + }, + + isDirty: function (a) { + return a.any(function (shape) { + return shape.isPropertyChanged() + }) + }, + + setSelection: function (elements, subSelectionElement, force) { + + if (!elements) { + elements = []; + } + if (!(elements instanceof Array)) { + elements = [elements]; + } + + elements = elements.findAll(function (n) { + return n && n instanceof ORYX.Core.Shape + }); + + if (elements[0] instanceof ORYX.Core.Canvas) { + elements = []; + } + + if (!force && this.isEqual(this.selection, elements) && !this.isDirty(elements)) { + return; + } + + this.selection = elements; + this._subSelection = subSelectionElement; + + this.handleEvents({ + type: ORYX.CONFIG.EVENT_SELECTION_CHANGED, + elements: elements, + subSelection: subSelectionElement, + force: !!force + }) + }, + + updateSelection: function () { + this.setSelection(this.selection, this._subSelection, true); + /*var s = this.selection; + this.setSelection(); + this.setSelection(s);*/ + }, + + getCanvas: function () { + return this._canvas; + }, + + + /** + * option = { + * type: string, + * position: {x:int, y:int}, + * connectingType: uiObj-Class + * connectedShape: uiObj + * draggin: bool + * namespace: url + * parent: ORYX.Core.AbstractShape + * template: a template shape that the newly created inherits properties from. + * } + */ + createShape: function (option) { + + if (option && option.serialize && option.serialize instanceof Array) { + + var type = option.serialize.find(function (obj) { + return (obj.prefix + "-" + obj.name) == "oryx-type" + }); + var stencil = ORYX.Core.StencilSet.stencil(type.value); + + if (stencil.type() == 'node') { + var newShapeObject = new ORYX.Core.Node({'eventHandlerCallback': this.handleEvents.bind(this)}, stencil, this._getPluginFacade()); + } else { + var newShapeObject = new ORYX.Core.Edge({'eventHandlerCallback': this.handleEvents.bind(this)}, stencil, this._getPluginFacade()); + } + + this.getCanvas().add(newShapeObject); + newShapeObject.deserialize(option.serialize); + + return newShapeObject; + } + + // If there is no argument, throw an exception + if (!option || !option.type || !option.namespace) { + throw "To create a new shape you have to give an argument with type and namespace"; + } + + var canvas = this.getCanvas(); + var newShapeObject; + + // Get the shape type + var shapetype = option.type; + + // Get the stencil set + var sset = ORYX.Core.StencilSet.stencilSet(option.namespace); + // Create an New Shape, dependents on an Edge or a Node + if (sset.stencil(shapetype).type() == "node") { + newShapeObject = new ORYX.Core.Node({'eventHandlerCallback': this.handleEvents.bind(this)}, sset.stencil(shapetype), this._getPluginFacade()) + } else { + newShapeObject = new ORYX.Core.Edge({'eventHandlerCallback': this.handleEvents.bind(this)}, sset.stencil(shapetype), this._getPluginFacade()) + } + + // when there is a template, inherit the properties. + if (option.template) { + + newShapeObject._jsonStencil.properties = option.template._jsonStencil.properties; + newShapeObject.postProcessProperties(); + } + + // Add to the canvas + if (option.parent && newShapeObject instanceof ORYX.Core.Node) { + option.parent.add(newShapeObject); + } else { + canvas.add(newShapeObject); + } + + + // Set the position + var point = option.position ? option.position : {x: 100, y: 200}; + + + var con; + // If there is create a shape and in the argument there is given an ConnectingType and is instance of an edge + if (option.connectingType && option.connectedShape && !(newShapeObject instanceof ORYX.Core.Edge)) { + + // there will be create a new Edge + con = new ORYX.Core.Edge({'eventHandlerCallback': this.handleEvents.bind(this)}, sset.stencil(option.connectingType)); + + // And both endings dockers will be referenced to the both shapes + con.dockers.first().setDockedShape(option.connectedShape); + + var magnet = option.connectedShape.getDefaultMagnet() + var cPoint = magnet ? magnet.bounds.center() : option.connectedShape.bounds.midPoint(); + con.dockers.first().setReferencePoint(cPoint); + con.dockers.last().setDockedShape(newShapeObject); + con.dockers.last().setReferencePoint(newShapeObject.getDefaultMagnet().bounds.center()); + + // The Edge will be added to the canvas and be updated + canvas.add(con); + //con.update(); + + } + + // Move the new Shape to the position + if (newShapeObject instanceof ORYX.Core.Edge && option.connectedShape) { + + newShapeObject.dockers.first().setDockedShape(option.connectedShape); + + if (option.connectedShape instanceof ORYX.Core.Node) { + newShapeObject.dockers.first().setReferencePoint(option.connectedShape.getDefaultMagnet().bounds.center()); + newShapeObject.dockers.last().bounds.centerMoveTo(point); + } else { + newShapeObject.dockers.first().setReferencePoint(option.connectedShape.bounds.midPoint()); + } + + var start = newShapeObject.dockers.first(); + var end = newShapeObject.dockers.last(); + + if (start.getDockedShape() && end.getDockedShape()) { + var startPoint = start.getAbsoluteReferencePoint(); + var endPoint = end.getAbsoluteReferencePoint(); + + var docker = newShapeObject.createDocker(); + docker.bounds.centerMoveTo({ + x: startPoint.x + (endPont.x - startPoint.x) / 2, + y: startPoint.y + (endPont.y - startPoint.y) / 2 + }); + } + + } else { + + var b = newShapeObject.bounds + if (newShapeObject instanceof ORYX.Core.Node && newShapeObject.dockers.length == 1) { + b = newShapeObject.dockers.first().bounds + } + + b.centerMoveTo(point); + + var upL = b.upperLeft(); + b.moveBy(-Math.min(upL.x, 0), -Math.min(upL.y, 0)) + + var lwR = b.lowerRight(); + b.moveBy(-Math.max(lwR.x - canvas.bounds.width(), 0), -Math.max(lwR.y - canvas.bounds.height(), 0)) + + } + + // Update the shape + if (newShapeObject instanceof ORYX.Core.Edge) { + newShapeObject._update(false); + } + + // And refresh the selection + if (!(newShapeObject instanceof ORYX.Core.Edge) && !(option.dontUpdateSelection)) { + this.setSelection([newShapeObject]); + } + + if (con && con.alignDockers) { + //con.alignDockers(); + } + if (newShapeObject.alignDockers) { + newShapeObject.alignDockers(); + } + + return newShapeObject; + }, + + deleteShape: function (shape) { + + if (!shape || !shape.parent) { + return + } + + //remove shape from parent + // this also removes it from DOM + shape.parent.remove(shape); + + //delete references to outgoing edges + shape.getOutgoingShapes().each(function (os) { + var docker = os.getDockers().first(); + if (docker && docker.getDockedShape() == shape) { + docker.setDockedShape(undefined); + } + }); + + //delete references to incoming edges + shape.getIncomingShapes().each(function (is) { + var docker = is.getDockers().last(); + if (docker && docker.getDockedShape() == shape) { + docker.setDockedShape(undefined); + } + }); + + //delete references of the shape's dockers + shape.getDockers().each(function (docker) { + docker.setDockedShape(undefined); + }); + }, + + /** + * Returns an object with meta data about the model. + * Like name, description, ... + * + * Empty object with the current backend. + * + * @return {Object} Meta data about the model + */ + getModelMetaData: function () { + return this.modelMetaData; + }, + + /* Event-Handler Methods */ + + /** + * Helper method to execute an event immediately. The event is not + * scheduled in the _eventsQueue. Needed to handle Layout-Callbacks. + */ + _executeEventImmediately: function (eventObj) { + if (this.DOMEventListeners.keys().member(eventObj.event.type)) { + this.DOMEventListeners[eventObj.event.type].each((function (value) { + value(eventObj.event, eventObj.arg); + }).bind(this)); + } + }, + + _executeEvents: function () { + this._queueRunning = true; + while (this._eventsQueue.length > 0) { + var val = this._eventsQueue.shift(); + this._executeEventImmediately(val); + } + this._queueRunning = false; + }, + + /** + * Leitet die Events an die Editor-Spezifischen Event-Methoden weiter + * @param {Object} event Event , welches gefeuert wurde + * @param {Object} uiObj Target-UiObj + */ + handleEvents: function (event, uiObj) { + + ORYX.Log.trace("Dispatching event type %0 on %1", event.type, uiObj); + + switch (event.type) { + case ORYX.CONFIG.EVENT_MOUSEDOWN: + this._handleMouseDown(event, uiObj); + break; + case ORYX.CONFIG.EVENT_MOUSEMOVE: + this._handleMouseMove(event, uiObj); + break; + case ORYX.CONFIG.EVENT_MOUSEUP: + this._handleMouseUp(event, uiObj); + break; + case ORYX.CONFIG.EVENT_MOUSEOVER: + this._handleMouseHover(event, uiObj); + break; + case ORYX.CONFIG.EVENT_MOUSEOUT: + this._handleMouseOut(event, uiObj); + break; + } + /* Force execution if necessary. Used while handle Layout-Callbacks. */ + if (event.forceExecution) { + this._executeEventImmediately({event: event, arg: uiObj}); + } else { + this._eventsQueue.push({event: event, arg: uiObj}); + } + + if (!this._queueRunning) { + this._executeEvents(); + } + + // TODO: Make this return whether no listener returned false. + // So that, when one considers bubbling undesireable, it won't happen. + return false; + }, + + isValidEvent: function (e) { + try { + var isInput = ["INPUT", "TEXTAREA"].include(e.target.tagName.toUpperCase()); + var gridHasFocus = e.target.className.include("x-grid3-focus") && !e.target.className.include("x-grid3-focus-canvas"); + return !isInput && !gridHasFocus; + } catch (e) { + return false; + } + }, + + catchKeyUpEvents: function (event) { + if (!this._keyupEnabled) { + return; + } + /* assure we have the current event. */ + if (!event) + event = window.event; + + // Checks if the event comes from some input field + if (!this.isValidEvent(event)) { + return; + } + + /* Create key up event type */ + var keyUpEvent = this.createKeyCombEvent(event, ORYX.CONFIG.KEY_ACTION_UP); + + ORYX.Log.debug("Key Event to handle: %0", keyUpEvent); + + /* forward to dispatching. */ + this.handleEvents({type: keyUpEvent, event: event}); + }, + + /** + * Catches all key down events and forward the appropriated event to + * dispatching concerning to the pressed keys. + * + * @param {Event} + * The key down event to handle + */ + catchKeyDownEvents: function (event) { + if (!this._keydownEnabled) { + return; + } + /* Assure we have the current event. */ + if (!event) + event = window.event; + + /* Fixed in FF3 */ + // This is a mac-specific fix. The mozilla event object has no knowledge + // of meta key modifier on osx, however, it is needed for certain + // shortcuts. This fix adds the metaKey field to the event object, so + // that all listeners that registered per Oryx plugin facade profit from + // this. The original bug is filed in + // https://bugzilla.mozilla.org/show_bug.cgi?id=418334 + //if (this.__currentKey == ORYX.CONFIG.KEY_CODE_META) { + // event.appleMetaKey = true; + //} + //this.__currentKey = pressedKey; + + // Checks if the event comes from some input field + if (!this.isValidEvent(event)) { + return; + } + + /* Create key up event type */ + var keyDownEvent = this.createKeyCombEvent(event, ORYX.CONFIG.KEY_ACTION_DOWN); + + ORYX.Log.debug("Key Event to handle: %0", keyDownEvent); + + /* Forward to dispatching. */ + this.handleEvents({type: keyDownEvent, event: event}); + }, + + /** + * Creates the event type name concerning to the pressed keys. + * + * @param {Event} keyDownEvent + * The source keyDownEvent to build up the event name + */ + createKeyCombEvent: function (keyEvent, keyAction) { + + /* Get the currently pressed key code. */ + var pressedKey = keyEvent.which || keyEvent.keyCode; + //this.__currentKey = pressedKey; + + /* Event name */ + var eventName = "key.event"; + + /* Key action */ + if (keyAction) { + eventName += "." + keyAction; + } + + /* Ctrl or apple meta key is pressed */ + if (keyEvent.ctrlKey || keyEvent.metaKey) { + eventName += "." + ORYX.CONFIG.META_KEY_META_CTRL; + } + + /* Alt key is pressed */ + if (keyEvent.altKey) { + eventName += "." + ORYX.CONFIG.META_KEY_ALT; + } + + /* Alt key is pressed */ + if (keyEvent.shiftKey) { + eventName += "." + ORYX.CONFIG.META_KEY_SHIFT; + } + + /* Return the composed event name */ + return eventName + "." + pressedKey; + }, + + _handleMouseDown: function (event, uiObj) { + + // get canvas. + var canvas = this.getCanvas(); + // Try to get the focus + canvas.focus() + + // find the shape that is responsible for this element's id. + var element = event.currentTarget; + var elementController = uiObj; + + // gather information on selection. + var currentIsSelectable = (elementController !== null) && + (elementController !== undefined) && (elementController.isSelectable); + var currentIsMovable = (elementController !== null) && + (elementController !== undefined) && (elementController.isMovable); + var modifierKeyPressed = event.shiftKey || event.ctrlKey; + var noObjectsSelected = this.selection.length === 0; + var currentIsSelected = this.selection.member(elementController); + + + // Rule #1: When there is nothing selected, select the clicked object. + if (currentIsSelectable && noObjectsSelected) { + + this.setSelection([elementController]); + + ORYX.Log.trace("Rule #1 applied for mouse down on %0", element.id); + + // Rule #3: When at least one element is selected, and there is no + // control key pressed, and the clicked object is not selected, select + // the clicked object. + } else if (currentIsSelectable && !noObjectsSelected && + !modifierKeyPressed && !currentIsSelected) { + + this.setSelection([elementController]); + + //var objectType = elementController.readAttributes(); + //alert(objectType[0] + ": " + objectType[1]); + + ORYX.Log.trace("Rule #3 applied for mouse down on %0", element.id); + + // Rule #4: When the control key is pressed, and the current object is + // not selected, add it to the selection. + } else if (currentIsSelectable && modifierKeyPressed + && !currentIsSelected) { + + var newSelection = this.selection.clone(); + newSelection.push(elementController) + this.setSelection(newSelection) + + ORYX.Log.trace("Rule #4 applied for mouse down on %0", element.id); + + // Rule #6 + } else if (currentIsSelectable && currentIsSelected && + modifierKeyPressed) { + + var newSelection = this.selection.clone(); + this.setSelection(newSelection.without(elementController)) + + ORYX.Log.trace("Rule #6 applied for mouse down on %0", elementController.id); + + // Rule #5: When there is at least one object selected and no control + // key pressed, we're dragging. + /*} else if(currentIsSelectable && !noObjectsSelected + && !modifierKeyPressed) { + + if(this.log.isTraceEnabled()) + this.log.trace("Rule #5 applied for mouse down on "+element.id); +*/ + // Rule #2: When clicked on something that is neither + // selectable nor movable, clear the selection, and return. + } else if (!currentIsSelectable && !currentIsMovable) { + + this.setSelection([]); + + ORYX.Log.trace("Rule #2 applied for mouse down on %0", element.id); + + return; + + // Rule #7: When the current object is not selectable but movable, + // it is probably a control. Leave the selection unchanged but set + // the movedObject to the current one and enable Drag. Dockers will + // be processed in the dragDocker plugin. + } else if (!currentIsSelectable && currentIsMovable && !(elementController instanceof ORYX.Core.Controls.Docker)) { + + // TODO: If there is any moveable elements, do this in a plugin + //ORYX.Core.UIEnableDrag(event, elementController); + + ORYX.Log.trace("Rule #7 applied for mouse down on %0", element.id); + + // Rule #8: When the element is selectable and is currently selected and no + // modifier key is pressed + } else if (currentIsSelectable && currentIsSelected && + !modifierKeyPressed) { + + this._subSelection = this._subSelection != elementController ? elementController : undefined; + + this.setSelection(this.selection, this._subSelection); + + ORYX.Log.trace("Rule #8 applied for mouse down on %0", element.id); + } + + + // prevent event from bubbling, return. + //Event.stop(event); + return; + }, + + _handleMouseMove: function (event, uiObj) { + return; + }, + + _handleMouseUp: function (event, uiObj) { + // get canvas. + var canvas = this.getCanvas(); + + // find the shape that is responsible for this elemement's id. + var elementController = uiObj; + + //get event position + var evPos = this.eventCoordinates(event); + + //Event.stop(event); + }, + + _handleMouseHover: function (event, uiObj) { + return; + }, + + _handleMouseOut: function (event, uiObj) { + return; + }, + + /** + * Calculates the event coordinates to SVG document coordinates. + * @param {Event} event + * @return {SVGPoint} The event coordinates in the SVG document + */ + eventCoordinates: function (event) { + + var canvas = this.getCanvas(); + + var svgPoint = canvas.node.ownerSVGElement.createSVGPoint(); + svgPoint.x = event.clientX; + svgPoint.y = event.clientY; + + var additionalIEZoom = 1; + if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) { + var ua = navigator.userAgent; + if (ua.indexOf('MSIE') >= 0) { + //IE 10 and below + var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100); + if (zoom !== 100) { + additionalIEZoom = zoom / 100 + } + } + } + + if (additionalIEZoom !== 1) { + svgPoint.x = svgPoint.x * additionalIEZoom; + svgPoint.y = svgPoint.y * additionalIEZoom; + } + + var matrix = canvas.node.getScreenCTM(); + return svgPoint.matrixTransform(matrix.inverse()); + }, + + eventCoordinatesXY: function (x, y) { + + var canvas = this.getCanvas(); + + var svgPoint = canvas.node.ownerSVGElement.createSVGPoint(); + svgPoint.x = x; + svgPoint.y = y; + + var additionalIEZoom = 1; + if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) { + var ua = navigator.userAgent; + if (ua.indexOf('MSIE') >= 0) { + //IE 10 and below + var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100); + if (zoom !== 100) { + additionalIEZoom = zoom / 100 + } + } + } + + if (additionalIEZoom !== 1) { + svgPoint.x = svgPoint.x * additionalIEZoom; + svgPoint.y = svgPoint.y * additionalIEZoom; + } + + var matrix = canvas.node.getScreenCTM(); + return svgPoint.matrixTransform(matrix.inverse()); + } +}; +ORYX.Editor = Clazz.extend(ORYX.Editor); + +/** + * Creates a new ORYX.Editor instance by fetching a model from given url and passing it to the constructur + * @param {String} modelUrl The JSON URL of a model. + * @param {Object} config Editor config passed to the constructur, merged with the response of the request to modelUrl + */ +ORYX.Editor.createByUrl = function (modelUrl) { + new Ajax.Request(modelUrl, { + method: 'GET', + onSuccess: function (transport) { + var editorConfig = JSON.parse(transport.responseText); + new ORYX.Editor(editorConfig); + }.bind(this) + }); +} + +// TODO Implement namespace awareness on attribute level. +/** + * graft() function + * Originally by Sean M. Burke from interglacial.com, altered for usage with + * SVG and namespace (xmlns) support. Be sure you understand xmlns before + * using this funtion, as it creates all grafted elements in the xmlns + * provided by you and all element's attribures in default xmlns. If you + * need to graft elements in a certain xmlns and wish to assign attributes + * in both that and another xmlns, you will need to do stepwise grafting, + * adding non-default attributes yourself or you'll have to enhance this + * function. Latter, I would appreciate: martin???apfelfabrik.de + * @param {Object} namespace The namespace in which + * elements should be grafted. + * @param {Object} parent The element that should contain the grafted + * structure after the function returned. + * @param {Object} t the crafting structure. + * @param {Object} doc the document in which grafting is performed. + */ +ORYX.Editor.graft = function (namespace, parent, t, doc) { + + doc = (doc || (parent && parent.ownerDocument) || document); + var e; + if (t === undefined) { + throw "Can't graft an undefined value"; + } else if (t.constructor == String) { + e = doc.createTextNode(t); + } else { + for (var i = 0; i < t.length; i++) { + if (i === 0 && t[i].constructor == String) { + var snared; + snared = t[i].match(/^([a-z][a-z0-9]*)\.([^\s\.]+)$/i); + if (snared) { + e = doc.createElementNS(namespace, snared[1]); + e.setAttributeNS(null, 'class', snared[2]); + continue; + } + snared = t[i].match(/^([a-z][a-z0-9]*)$/i); + if (snared) { + e = doc.createElementNS(namespace, snared[1]); // but no class + continue; + } + + // Otherwise: + e = doc.createElementNS(namespace, "span"); + e.setAttribute(null, "class", "namelessFromLOL"); + } + + if (t[i] === undefined) { + throw "Can't graft an undefined value in a list!"; + } else if (t[i].constructor == String || t[i].constructor == Array) { + this.graft(namespace, e, t[i], doc); + } else if (t[i].constructor == Number) { + this.graft(namespace, e, t[i].toString(), doc); + } else if (t[i].constructor == Object) { + // hash's properties => element's attributes + for (var k in t[i]) { + e.setAttributeNS(null, k, t[i][k]); + } + } else { + + } + } + } + if (parent && parent.appendChild) { + parent.appendChild(e); + } else { + + } + return e; // return the topmost created node +}; + +ORYX.Editor.provideId = function () { + var res = [], hex = '0123456789ABCDEF'; + + for (var i = 0; i < 36; i++) res[i] = Math.floor(Math.random() * 0x10); + + res[14] = 4; + res[19] = (res[19] & 0x3) | 0x8; + + for (var i = 0; i < 36; i++) res[i] = hex[res[i]]; + + res[8] = res[13] = res[18] = res[23] = '-'; + + return "oryx_" + res.join(''); +}; + +/** + * When working with Ext, conditionally the window needs to be resized. To do + * so, use this class method. Resize is deferred until 100ms, and all subsequent + * resizeBugFix calls are ignored until the initially requested resize is + * performed. + */ +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 (callback, interval) { + + this.callbacks.push(callback); + this.start(interval) + + }, + + start: function (interval) { + + if (this.pe) { + return; + } + + var currentString = document.cookie; + + this.pe = new PeriodicalExecuter(function () { + + if (currentString != document.cookie) { + currentString = document.cookie; + this.callbacks.each(function (callback) { + callback(this.getParams()) + }.bind(this)); + } + + }.bind(this), (interval || 10000) / 1000); + }, + + stop: function () { + + if (this.pe) { + this.pe.stop(); + this.pe = null; + } + }, + + getParams: function () { + var res = {}; + + var p = document.cookie; + p.split("; ").each(function (param) { + res[param.split("=")[0]] = param.split("=")[1]; + }); + + return res; + }, + + toString: function () { + return document.cookie; + } +}; + +/** + * Workaround for SAFARI/Webkit, because + * when trying to check SVGSVGElement of instanceof there is + * raising an error + * + */ +ORYX.Editor.SVGClassElementsAreAvailable = true; +ORYX.Editor.setMissingClasses = function () { + + try { + SVGElement; + } catch (e) { + 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(); + //SVGMarkerElement = document.createElementNS('http://www.w3.org/2000/svg', 'marker').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 (classInst, classType) { + + if (ORYX.Editor.SVGClassElementsAreAvailable) { + return classInst instanceof classType + } else { + return classInst == classType + } +}; +/* + * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +/* + * All code Copyright 2013 KIS Consultancy all rights reserved + */ + +/** + * Init namespaces + */ +if (!ORYX) { + var ORYX = {}; +} +if (!ORYX.Core) { + ORYX.Core = {}; +} + + +new function () { + + ORYX.Core.UIEnableDrag = function (event, uiObj, option) { + + this.uiObj = uiObj; + var upL = uiObj.bounds.upperLeft(); + + var a = uiObj.node.getScreenCTM(); + this.faktorXY = {x: a.a, y: a.d}; + + this.scrollNode = uiObj.node.ownerSVGElement.parentNode.parentNode; + + this.offSetPosition = { + x: Event.pointerX(event) - (upL.x * this.faktorXY.x), + y: Event.pointerY(event) - (upL.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 = option ? option.movedCallback : undefined; + this.upCallback = option ? option.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 (event) { + + var position = { + x: Event.pointerX(event) - this.offSetPosition.x, + y: Event.pointerY(event) - this.offSetPosition.y + } + + position.x -= this.offsetScroll.x - this.scrollNode.scrollLeft; + position.y -= this.offsetScroll.y - this.scrollNode.scrollTop; + + position.x /= this.faktorXY.x; + position.y /= this.faktorXY.y; + + this.uiObj.bounds.moveTo(position); + //this.uiObj.update(); + + if (this.movedCallback) + this.movedCallback(event); + + //Event.stop(event); + + }; + + ORYX.Core.UIDisableDrag = function (event) { + 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(event); + + this.upCallback = undefined; + this.movedCallback = undefined; + + Event.stop(event); + }; + + + /** + * Implements a command to move docker by an offset. + * + * @class ORYX.Core.MoveDockersCommand + * @param {Object} object An object with the docker id as key and docker and offset as object value + * + */ + ORYX.Core.MoveDockersCommand = ORYX.Core.Command.extend({ + construct: function (dockers) { + this.dockers = $H(dockers); + this.edges = $H({}); + }, + execute: function () { + if (this.changes) { + this.executeAgain(); + return; + } else { + this.changes = $H({}); + } + + this.dockers.values().each(function (docker) { + var edge = docker.docker.parent; + if (!edge) { + return + } + + if (!this.changes[edge.getId()]) { + this.changes[edge.getId()] = { + edge: edge, + oldDockerPositions: edge.dockers.map(function (r) { + return r.bounds.center() + }) + } + } + docker.docker.bounds.moveBy(docker.offset); + this.edges[edge.getId()] = edge; + docker.docker.update(); + }.bind(this)); + this.edges.each(function (edge) { + this.updateEdge(edge.value); + if (this.changes[edge.value.getId()]) + this.changes[edge.value.getId()].dockerPositions = edge.value.dockers.map(function (r) { + return r.bounds.center() + }) + }.bind(this)); + }, + updateEdge: function (edge) { + edge._update(true); + [edge.getOutgoingShapes(), edge.getIncomingShapes()].flatten().invoke("_update", [true]) + }, + executeAgain: function () { + this.changes.values().each(function (change) { + // Reset the dockers + this.removeAllDocker(change.edge); + change.dockerPositions.each(function (pos, i) { + if (i == 0 || i == change.dockerPositions.length - 1) { + return + } + var docker = change.edge.createDocker(undefined, pos); + docker.bounds.centerMoveTo(pos); + docker.update(); + }.bind(this)); + this.updateEdge(change.edge); + }.bind(this)); + }, + rollback: function () { + this.changes.values().each(function (change) { + // Reset the dockers + this.removeAllDocker(change.edge); + change.oldDockerPositions.each(function (pos, i) { + if (i == 0 || i == change.oldDockerPositions.length - 1) { + return + } + var docker = change.edge.createDocker(undefined, pos); + docker.bounds.centerMoveTo(pos); + docker.update(); + }.bind(this)); + this.updateEdge(change.edge); + }.bind(this)); + }, + removeAllDocker: function (edge) { + edge.dockers.slice(1, edge.dockers.length - 1).each(function (docker) { + edge.removeDocker(docker); + }) + } + }); + +}(); +/* + * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +/* + * All code Copyright 2013 KIS Consultancy all rights reserved + */ + +/** + * Init namespaces + */ +if (!ORYX) { + var ORYX = {}; +} +if (!ORYX.Core) { + ORYX.Core = {}; +} + +/** + * @classDescription Base class for Shapes. + * @extends ORYX.Core.AbstractShape + */ +ORYX.Core.Shape = { + + /** + * Constructor + */ + construct: function (options, stencil, facade) { + // call base class constructor + arguments.callee.$.construct.apply(this, arguments); + + this.facade = facade; + this.dockers = []; + this.magnets = []; + + this._defaultMagnet; + + this.incoming = []; + this.outgoing = []; + + this.nodes = []; + + this._dockerChangedCallback = this._dockerChanged.bind(this); + + //Hash map for all labels. Labels are not treated as children of shapes. + this._labels = new Hash(); + + // create SVG node + 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"}] + ] + ]); + }, + + /** + * If changed flag is set, refresh method is called. + */ + update: function () { + //if(this.isChanged) { + //this.layout(); + //} + }, + + /** + * !!!Not called from any sub class!!! + */ + _update: function () { + + }, + + /** + * Calls the super class refresh method + * and updates the svg elements that are referenced by a property. + */ + refresh: function () { + //call base class refresh method + arguments.callee.$.refresh.apply(this, arguments); + + if (this.node.ownerDocument) { + //adjust SVG to properties' values + var me = this; + this.propertiesChanged.each((function (propChanged) { + if (propChanged.value) { + var prop = this.properties[propChanged.key]; + var property = this.getStencil().property(propChanged.key); + if (property != undefined) { + this.propertiesChanged[propChanged.key] = false; + + //handle choice properties + if (property.type() == ORYX.CONFIG.TYPE_CHOICE) { + //iterate all references to SVG elements + property.refToView().each((function (ref) { + //if property is referencing a label, update the label + if (ref !== "") { + var label = this._labels[this.id + ref]; + if (label && property.item(prop)) { + label.text(property.item(prop).title()); + } + } + }).bind(this)); + + //if the choice's items are referencing SVG elements + // show the selected and hide all other referenced SVG + // elements + var refreshedSvgElements = new Hash(); + property.items().each((function (item) { + item.refToView().each((function (itemRef) { + if (itemRef == "") { + return; + } + + var svgElem = this.node.ownerDocument.getElementById(this.id + itemRef); + + if (!svgElem) { + return; + } + + + /* Do not refresh the same svg element multiple times */ + if (!refreshedSvgElements[svgElem.id] || prop == item.value()) { + svgElem.setAttributeNS(null, 'display', ((prop == item.value()) ? 'inherit' : 'none')); + refreshedSvgElements[svgElem.id] = svgElem; + } + + // Reload the href if there is an image-tag + if (ORYX.Editor.checkClassType(svgElem, SVGImageElement)) { + svgElem.setAttributeNS('http://www.w3.org/1999/xlink', 'href', svgElem.getAttributeNS('http://www.w3.org/1999/xlink', 'href')); + } + }).bind(this)); + }).bind(this)); + + } else { //handle properties that are not of type choice + //iterate all references to SVG elements + property.refToView().each((function (ref) { + //if the property does not reference an SVG element, + // do nothing + + if (ref === "") { + return; + } + + var refId = this.id + ref; + + if (property.type() === ORYX.CONFIG.TYPE_KISBPM_MULTIINSTANCE) { + if (ref === "multiinstance") { + + var svgElemParallel = this.node.ownerDocument.getElementById(this.id + 'parallel'); + if (svgElemParallel) { + if (prop === 'Parallel') { + svgElemParallel.setAttributeNS(null, 'display', 'inherit'); + } else { + svgElemParallel.setAttributeNS(null, 'display', 'none'); + } + } + + var svgElemSequential = this.node.ownerDocument.getElementById(this.id + 'sequential'); + + if (svgElemSequential) { + if (prop === 'Sequential') { + svgElemSequential.setAttributeNS(null, 'display', 'inherit'); + } else { + svgElemSequential.setAttributeNS(null, 'display', 'none'); + } + } + } + return; + + } else if (property.type() === "cancelactivity") { + var svgElemFrame = this.node.ownerDocument.getElementById(this.id + 'frame'); + var svgElemFrame2 = this.node.ownerDocument.getElementById(this.id + 'frame2'); + + if (prop === 'true') { + svgElemFrame.setAttributeNS(null, 'display', 'inherit'); + svgElemFrame2.setAttributeNS(null, 'display', 'inherit'); + } else { + svgElemFrame.setAttributeNS(null, 'display', 'none'); + svgElemFrame2.setAttributeNS(null, 'display', 'none'); + } + } + + //get the SVG element + var svgElem = this.node.ownerDocument.getElementById(refId); + + //if the SVG element can not be found + if (!svgElem || !(svgElem.ownerSVGElement)) { + //if the referenced SVG element is a SVGAElement, it cannot + // be found with getElementById (Firefox bug). + // this is a work around + if (property.type() === ORYX.CONFIG.TYPE_URL || property.type() === ORYX.CONFIG.TYPE_DIAGRAM_LINK) { + var svgElems = this.node.ownerDocument.getElementsByTagNameNS('http://www.w3.org/2000/svg', 'a'); + + svgElem = $A(svgElems).find(function (elem) { + return elem.getAttributeNS(null, 'id') === refId; + }); + + if (!svgElem) { + return; + } + } else { + //this.propertiesChanged[propChanged.key] = true; + return; + } + } + + if (property.complexAttributeToView()) { + var label = this._labels[refId]; + if (label) { + try { + propJson = prop.evalJSON(); + var value = propJson[property.complexAttributeToView()] + label.text(value ? value : prop); + } catch (e) { + label.text(prop); + } + } + + } else { + switch (property.type()) { + case ORYX.CONFIG.TYPE_BOOLEAN: + if (typeof prop == "string") + prop = prop === "true" + + svgElem.setAttributeNS(null, 'display', (!(prop === property.inverseBoolean())) ? 'inherit' : 'none'); + + break; + case ORYX.CONFIG.TYPE_COLOR: + if (property.fill()) { + if (svgElem.tagName.toLowerCase() === "stop") { + if (prop) { + + if (property.lightness() && property.lightness() !== 1) { + prop = ORYX.Utils.adjustLightness(prop, property.lightness()); + } + + svgElem.setAttributeNS(null, "stop-color", prop); + + // Adjust stop color of the others + if (svgElem.parentNode.tagName.toLowerCase() === "radialgradient") { + ORYX.Utils.adjustGradient(svgElem.parentNode, svgElem); + } + } + + // If there is no value, set opaque + if (svgElem.parentNode.tagName.toLowerCase() === "radialgradient") { + $A(svgElem.parentNode.getElementsByTagName('stop')).each(function (stop) { + stop.setAttributeNS(null, "stop-opacity", prop ? stop.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, 'default-stop-opacity') || 1 : 0); + }.bind(this)) + } + } else { + svgElem.setAttributeNS(null, 'fill', prop); + } + } + if (property.stroke()) { + svgElem.setAttributeNS(null, 'stroke', prop); + } + break; + case ORYX.CONFIG.TYPE_STRING: + var label = this._labels[refId]; + if (label) { + label.text(prop); + } + break; + case ORYX.CONFIG.TYPE_EXPRESSION: + var label = this._labels[refId]; + if (label) { + label.text(prop); + } + break; + case ORYX.CONFIG.TYPE_DATASOURCE: + var label = this._labels[refId]; + if (label) { + label.text(prop); + } + break; + case ORYX.CONFIG.TYPE_INTEGER: + var label = this._labels[refId]; + if (label) { + label.text(prop); + } + break; + case ORYX.CONFIG.TYPE_FLOAT: + if (property.fillOpacity()) { + svgElem.setAttributeNS(null, 'fill-opacity', prop); + } + if (property.strokeOpacity()) { + svgElem.setAttributeNS(null, 'stroke-opacity', prop); + } + if (!property.fillOpacity() && !property.strokeOpacity()) { + var label = this._labels[refId]; + if (label) { + label.text(prop); + } + } + break; + + case ORYX.CONFIG.TYPE_FORM_LINK: + if (ref == "pimg") { + var onclickAttr = svgElem.getAttributeNodeNS('', 'onclick'); + if (onclickAttr) { + if (prop && ("" + prop).length > 0) { + onclickAttr.textContent = "window.location = '../service/editor?id=" + prop + "_form'"; + } else { + newFormFacade = this.facade; + onclickAttr.textContent = "displayNewFormDialog('" + this.resourceId + "');"; + } + } + } else if (ref == "linkIndicator") { + if (prop && prop.length > 0) { + svgElem.setAttributeNS(null, 'display', 'inherit'); + } else { + svgElem.setAttributeNS(null, 'display', 'none'); + } + } + break; + case ORYX.CONFIG.TYPE_URL: + case ORYX.CONFIG.TYPE_DIAGRAM_LINK: + //TODO what is the dafault path? + var hrefAttr = svgElem.getAttributeNodeNS('http://www.w3.org/1999/xlink', 'xlink:href'); + if (hrefAttr) { + hrefAttr.textContent = prop; + } else { + svgElem.setAttributeNS('http://www.w3.org/1999/xlink', 'xlink:href', prop); + } + break; + + } + } + }).bind(this)); + + + } + } + + } + }).bind(this)); + + //update labels + this._labels.values().each(function (label) { + label.update(); + }); + } + }, + + layout: function () { + //this.getStencil().layout(this) + var layoutEvents = this.getStencil().layout() + if (layoutEvents) { + layoutEvents.each(function (event) { + + // setup additional attributes + event.shape = this; + event.forceExecution = true; + + // do layouting + this._delegateEvent(event); + }.bind(this)) + + } + }, + + /** + * Returns an array of Label objects. + */ + getLabels: function () { + return this._labels.values(); + }, + + /** + * Returns the label for a given ref + * @return {ORYX.Core.Label} Returns null if there is no label + */ + getLabel: function (ref) { + if (!ref) { + return null; + } + return (this._labels.find(function (o) { + return o.key.endsWith(ref); + }) || {}).value || null; + }, + + /** + * Hides all related labels + * + */ + hideLabels: function () { + this.getLabels().invoke("hide"); + }, + + /** + * Shows all related labels + * + */ + showLabels: function () { + var labels = this.getLabels(); + labels.invoke("show"); + labels.each(function (label) { + label.update(); + }); + }, + + setOpacity: function (value, animate) { + + value = Math.max(Math.min((typeof value == "number" ? value : 1.0), 1.0), 0.0); + + if (value !== 1.0) { + value = String(value); + this.node.setAttributeNS(null, "fill-opacity", value) + this.node.setAttributeNS(null, "stroke-opacity", value) + } else { + this.node.removeAttributeNS(null, "fill-opacity"); + this.node.removeAttributeNS(null, "stroke-opacity"); + } + }, + + /** + * Returns an array of dockers of this object. + */ + 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 (iterator) { + if (iterator) { + this.incoming.each(iterator); + } + return this.incoming; + }, + + getIncomingNodes: function (iterator) { + return this.incoming.select(function (incoming) { + var isNode = (incoming instanceof ORYX.Core.Node); + if (isNode && iterator) iterator(incoming); + return isNode; + }); + }, + + + getOutgoingShapes: function (iterator) { + if (iterator) { + this.outgoing.each(iterator); + } + return this.outgoing; + }, + + getOutgoingNodes: function (iterator) { + return this.outgoing.select(function (out) { + var isNode = (out instanceof ORYX.Core.Node); + if (isNode && iterator) iterator(out); + return isNode; + }); + }, + + getAllDockedShapes: function (iterator) { + var result = this.incoming.concat(this.outgoing); + if (iterator) { + result.each(iterator); + } + return result + }, + + 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; + } + }, + + /** + * + * @param {Object} deep + * @param {Object} iterator + */ + getChildNodes: function (deep, iterator) { + if (!deep && !iterator) { + return this.nodes.clone(); + } else { + var result = []; + this.nodes.each(function (uiObject) { + if (!uiObject.isVisible) { + return + } + if (iterator) { + iterator(uiObject); + } + result.push(uiObject); + + if (deep && uiObject instanceof ORYX.Core.Shape) { + result = result.concat(uiObject.getChildNodes(deep, iterator)); + } + }); + + return result; + } + }, + + /** + * Overrides the UIObject.add method. Adds uiObject to the correct sub node. + * @param {UIObject} uiObject + * @param {Number} index + */ + add: function (uiObject, index, silent) { + //parameter has to be an UIObject, but + // must not be an Edge. + if (uiObject instanceof ORYX.Core.UIObject + && !(uiObject instanceof ORYX.Core.Edge)) { + + if (!(this.children.member(uiObject))) { + //if uiObject is child of another parent, remove it from that parent. + if (uiObject.parent) { + uiObject.parent.remove(uiObject, true); + } + + //add uiObject to this Shape + if (index != undefined) + this.children.splice(index, 0, uiObject); + else + this.children.push(uiObject); + + //set parent reference + uiObject.parent = this; + + //add uiObject.node to this.node depending on the type of uiObject + var parent; + if (uiObject instanceof ORYX.Core.Node) { + parent = this.node.childNodes[0].childNodes[1]; + this.nodes.push(uiObject); + } else if (uiObject instanceof ORYX.Core.Controls.Control) { + var ctrls = this.node.childNodes[1]; + if (uiObject instanceof ORYX.Core.Controls.Docker) { + parent = ctrls.childNodes[0]; + if (this.dockers.length >= 2) { + this.dockers.splice(index !== undefined ? Math.min(index, this.dockers.length - 1) : this.dockers.length - 1, 0, uiObject); + } else { + this.dockers.push(uiObject); + } + } else if (uiObject instanceof ORYX.Core.Controls.Magnet) { + parent = ctrls.childNodes[1]; + this.magnets.push(uiObject); + } else { + parent = ctrls; + } + } else { //UIObject + parent = this.node; + } + + if (index != undefined && index < parent.childNodes.length) + uiObject.node = parent.insertBefore(uiObject.node, parent.childNodes[index]); + else + uiObject.node = parent.appendChild(uiObject.node); + + this._changed(); + //uiObject.bounds.registerCallback(this._changedCallback); + + + if (this.eventHandlerCallback && silent !== true) + this.eventHandlerCallback({type: ORYX.CONFIG.EVENT_SHAPEADDED, shape: uiObject}) + + } 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."); + } + }, + + /** + * Overrides the UIObject.remove method. Removes uiObject. + * @param {UIObject} uiObject + */ + remove: function (uiObject, silent) { + //if uiObject is a child of this object, remove it. + if (this.children.member(uiObject)) { + //remove uiObject from children + var parent = uiObject.parent; + + this.children = this.children.without(uiObject); + + //delete parent reference of uiObject + uiObject.parent = undefined; + + //delete uiObject.node from this.node + if (uiObject instanceof ORYX.Core.Shape) { + if (uiObject instanceof ORYX.Core.Edge) { + uiObject.removeMarkers(); + uiObject.node = this.node.childNodes[0].childNodes[2].removeChild(uiObject.node); + } else { + uiObject.node = this.node.childNodes[0].childNodes[1].removeChild(uiObject.node); + this.nodes = this.nodes.without(uiObject); + } + } else if (uiObject instanceof ORYX.Core.Controls.Control) { + if (uiObject instanceof ORYX.Core.Controls.Docker) { + uiObject.node = this.node.childNodes[1].childNodes[0].removeChild(uiObject.node); + this.dockers = this.dockers.without(uiObject); + } else if (uiObject instanceof ORYX.Core.Controls.Magnet) { + uiObject.node = this.node.childNodes[1].childNodes[1].removeChild(uiObject.node); + this.magnets = this.magnets.without(uiObject); + } else { + uiObject.node = this.node.childNodes[1].removeChild(uiObject.node); + } + } + + if (this.eventHandlerCallback && silent !== true) + this.eventHandlerCallback({type: ORYX.CONFIG.EVENT_SHAPEREMOVED, shape: uiObject, parent: parent}); + + this._changed(); + //uiObject.bounds.unregisterCallback(this._changedCallback); + } else { + + ORYX.Log.warn("remove: ORYX.Core.UIObject is not a child of this object."); + } + }, + + /** + * Calculate the Border Intersection Point between two points + * @param {PointA} + * @param {PointB} + */ + getIntersectionPoint: function () { + + var pointAX, pointAY, pointBX, pointBY; + + // Get the the two Points + switch (arguments.length) { + case 2: + pointAX = arguments[0].x; + pointAY = arguments[0].y; + pointBX = arguments[1].x; + pointBY = arguments[1].y; + break; + case 4: + pointAX = arguments[0]; + pointAY = arguments[1]; + pointBX = arguments[2]; + pointBY = arguments[3]; + break; + default: + throw "getIntersectionPoints needs two or four arguments"; + } + + + // Defined an include and exclude point + var includePointX, includePointY, excludePointX, excludePointY; + + var bounds = this.absoluteBounds(); + + if (this.isPointIncluded(pointAX, pointAY, bounds)) { + includePointX = pointAX; + includePointY = pointAY; + } else { + excludePointX = pointAX; + excludePointY = pointAY; + } + + if (this.isPointIncluded(pointBX, pointBY, bounds)) { + includePointX = pointBX; + includePointY = pointBY; + } else { + excludePointX = pointBX; + excludePointY = pointBY; + } + + // If there is no inclue or exclude Shape, than return + if (!includePointX || !includePointY || !excludePointX || !excludePointY) { + return undefined; + } + + var midPointX = 0; + var midPointY = 0; + + var refPointX, refPointY; + + var minDifferent = 1; + // Get the UpperLeft and LowerRight + //var ul = bounds.upperLeft(); + //var lr = bounds.lowerRight(); + + var i = 0; + + while (true) { + // Calculate the midpoint of the current to points + var midPointX = Math.min(includePointX, excludePointX) + ((Math.max(includePointX, excludePointX) - Math.min(includePointX, excludePointX)) / 2.0); + var midPointY = Math.min(includePointY, excludePointY) + ((Math.max(includePointY, excludePointY) - Math.min(includePointY, excludePointY)) / 2.0); + + + // Set the new midpoint by the means of the include of the bounds + if (this.isPointIncluded(midPointX, midPointY, bounds)) { + includePointX = midPointX; + includePointY = midPointY; + } else { + excludePointX = midPointX; + excludePointY = midPointY; + } + + // Calc the length of the line + var length = Math.sqrt(Math.pow(includePointX - excludePointX, 2) + Math.pow(includePointY - excludePointY, 2)) + // Calc a point one step from the include point + refPointX = includePointX + ((excludePointX - includePointX) / length), + refPointY = includePointY + ((excludePointY - includePointY) / length) + + + // If the reference point not in the bounds, break + if (!this.isPointIncluded(refPointX, refPointY, bounds)) { + break + } + + + } + + // Return the last includepoint + return {x: refPointX, y: refPointY}; + }, + + + /** + * Calculate if the point is inside the Shape + * @param {PointX} + * @param {PointY} + */ + isPointIncluded: function () { + return false + }, + + /** + * Returns TRUE if the given node + * is a child node of the shapes node + * @param {Element} node + * @return {Boolean} + * + */ + containsNode: function (node) { + var me = this.node.firstChild.firstChild; + while (node) { + if (node == me) { + return true; + } + node = node.parentNode; + } + return false + }, + + /** + * Calculate if the point is over an special offset area + * @param {Point} + */ + isPointOverOffset: function () { + return this.isPointIncluded.apply(this, arguments) + }, + + _dockerChanged: function () { + + }, + + /** + * Create a Docker for this Edge + * + */ + createDocker: function (index, position) { + var docker = new ORYX.Core.Controls.Docker({eventHandlerCallback: this.eventHandlerCallback}); + docker.bounds.registerCallback(this._dockerChangedCallback); + if (position) { + docker.bounds.centerMoveTo(position); + } + this.add(docker, index); + + return docker + }, + + /** + * Get the serialized object + * return Array with hash-entrees (prefix, name, value) + * Following values will given: + * Bounds + * Outgoing Shapes + * Parent + */ + serialize: function () { + var serializedObject = arguments.callee.$.serialize.apply(this); + + // Add the bounds + serializedObject.push({name: 'bounds', prefix: 'oryx', value: this.bounds.serializeForERDF(), type: 'literal'}); + + // Add the outgoing shapes + this.getOutgoingShapes().each((function (followingShape) { + serializedObject.push({ + name: 'outgoing', + prefix: 'raziel', + value: '#' + ERDF.__stripHashes(followingShape.resourceId), + type: 'resource' + }); + }).bind(this)); + + // Add the parent shape, if the parent not the canvas + //if(this.parent instanceof ORYX.Core.Shape){ + serializedObject.push({ + name: 'parent', + prefix: 'raziel', + value: '#' + ERDF.__stripHashes(this.parent.resourceId), + type: 'resource' + }); + //} + + return serializedObject; + }, + + + deserialize: function (serialize, json) { + arguments.callee.$.deserialize.apply(this, arguments); + + // Set the Bounds + var bounds = serialize.find(function (ser) { + return 'oryx-bounds' === (ser.prefix + "-" + ser.name) + }); + if (bounds) { + var b = bounds.value.replace(/,/g, " ").split(" ").without(""); + if (this instanceof ORYX.Core.Edge) { + if (!this.dockers.first().isChanged) + this.dockers.first().bounds.centerMoveTo(parseFloat(b[0]), parseFloat(b[1])); + if (!this.dockers.last().isChanged) + this.dockers.last().bounds.centerMoveTo(parseFloat(b[2]), parseFloat(b[3])); + } else { + this.bounds.set(parseFloat(b[0]), parseFloat(b[1]), parseFloat(b[2]), parseFloat(b[3])); + } + } + + if (json && json.labels instanceof Array) { + json.labels.each(function (slabel) { + var label = this.getLabel(slabel.ref); + if (label) { + label.deserialize(slabel, this); + } + }.bind(this)) + } + }, + + toJSON: function () { + var json = arguments.callee.$.toJSON.apply(this, arguments); + + var labels = [], id = this.id; + this._labels.each(function (obj) { + var slabel = obj.value.serialize(); + if (slabel) { + slabel.ref = obj.key.replace(id, ''); + labels.push(slabel); + } + }); + + if (labels.length > 0) { + json.labels = labels; + } + return json; + }, + + + /** + * Private methods. + */ + + /** + * Child classes have to overwrite this method for initializing a loaded + * SVG representation. + * @param {SVGDocument} svgDocument + */ + _init: function (svgDocument) { + //adjust ids + this._adjustIds(svgDocument, 0); + }, + + _adjustIds: function (element, idIndex) { + if (element instanceof Element) { + var eid = element.getAttributeNS(null, 'id'); + if (eid && eid !== "") { + element.setAttributeNS(null, 'id', this.id + eid); + } else { + element.setAttributeNS(null, 'id', this.id + "_" + this.id + "_" + idIndex); + idIndex++; + } + + // Replace URL in fill attribute + var fill = element.getAttributeNS(null, 'fill'); + if (fill && fill.include("url(#")) { + fill = fill.replace(/url\(#/g, 'url(#' + this.id); + element.setAttributeNS(null, 'fill', fill); + } + + if (element.hasChildNodes()) { + for (var i = 0; i < element.childNodes.length; i++) { + idIndex = this._adjustIds(element.childNodes[i], idIndex); + } + } + } + return idIndex; + }, + + toString: function () { + return "ORYX.Core.Shape " + this.getId() + } +}; +ORYX.Core.Shape = ORYX.Core.AbstractShape.extend(ORYX.Core.Shape);/* + * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +/* + * All code Copyright 2013 KIS Consultancy all rights reserved + */ + +/** + * Init namespaces + */ +if (!ORYX) { + var ORYX = {}; +} +if (!ORYX.Core) { + ORYX.Core = {}; +} +if (!ORYX.Core.Controls) { + ORYX.Core.Controls = {}; +} + + +/** + * @classDescription Abstract base class for all Controls. + */ +ORYX.Core.Controls.Control = ORYX.Core.UIObject.extend({ + + toString: function () { + return "Control " + this.id; + } +});/* + * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +/* + * All code Copyright 2013 KIS Consultancy all rights reserved + */ + +/** + * Init namespaces + */ +if (!ORYX) { + var ORYX = {}; +} +if (!ORYX.Core) { + ORYX.Core = {}; +} +if (!ORYX.Core.Controls) { + ORYX.Core.Controls = {}; +} + + +/** + * @classDescription Represents a movable docker that can be bound to a shape. Dockers are used + * for positioning shape objects. + * @extends {Control} + * + * TODO absoluteXY und absoluteCenterXY von einem Docker liefern falsche Werte!!! + */ +ORYX.Core.Controls.Docker = ORYX.Core.Controls.Control.extend({ + /** + * Constructor + */ + construct: function () { + arguments.callee.$.construct.apply(this, arguments); + + this.isMovable = true; // Enables movability + this.bounds.set(0, 0, 16, 16); // Set the bounds + this.referencePoint = undefined; // Refrenzpoint + this._dockedShapeBounds = undefined; + this._dockedShape = undefined; + this._oldRefPoint1 = undefined; + this._oldRefPoint2 = undefined; + + //this.anchors = []; + this.anchorLeft; + this.anchorRight; + this.anchorTop; + this.anchorBottom; + + this.node = ORYX.Editor.graft("http://www.w3.org/2000/svg", + null, + ['g']); + + // The DockerNode reprasentation + 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"}] + ]); + + // The ReferenzNode reprasentation + 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 + }]]); + + // Hide the Docker + this.hide(); + + //Add to the EventHandler + this.addEventHandlers(this._dockerNode); + + // Buffer the Update Callback for un-/register on Event-Handler + this._updateCallback = this._changed.bind(this); + }, + + update: function () { + // If there have an DockedShape + if (this._dockedShape) { + if (this._dockedShapeBounds && this._dockedShape instanceof ORYX.Core.Node) { + // Calc the delta of width and height of the lastBounds and the current Bounds + var dswidth = this._dockedShapeBounds.width(); + var dsheight = this._dockedShapeBounds.height(); + if (!dswidth) + dswidth = 1; + if (!dsheight) + dsheight = 1; + var widthDelta = this._dockedShape.bounds.width() / dswidth; + var heightDelta = this._dockedShape.bounds.height() / dsheight; + + // If there is an different + if (widthDelta !== 1.0 || heightDelta !== 1.0) { + // Set the delta + this.referencePoint.x *= widthDelta; + this.referencePoint.y *= heightDelta; + } + + // Clone these bounds + this._dockedShapeBounds = this._dockedShape.bounds.clone(); + } + + // Get the first and the last Docker of the parent Shape + var dockerIndex = this.parent.dockers.indexOf(this) + var dock1 = this; + var dock2 = this.parent.dockers.length > 1 ? + (dockerIndex === 0 ? // If there is the first element + this.parent.dockers[dockerIndex + 1] : // then take the next docker + this.parent.dockers[dockerIndex - 1]) : // if not, then take the docker before + undefined; + + // Calculate the first absolute Refenzpoint + var absoluteReferenzPoint1 = dock1.getDockedShape() ? + dock1.getAbsoluteReferencePoint() : + dock1.bounds.center(); + + // Calculate the last absolute Refenzpoint + var absoluteReferenzPoint2 = dock2 && dock2.getDockedShape() ? + dock2.getAbsoluteReferencePoint() : + dock2 ? + dock2.bounds.center() : + undefined; + + // If there is no last absolute Referenzpoint + if (!absoluteReferenzPoint2) { + // Calculate from the middle of the DockedShape + var center = this._dockedShape.absoluteCenterXY(); + var minDimension = this._dockedShape.bounds.width() * this._dockedShape.bounds.height(); + absoluteReferenzPoint2 = { + x: absoluteReferenzPoint1.x + (center.x - absoluteReferenzPoint1.x) * -minDimension, + y: absoluteReferenzPoint1.y + (center.y - absoluteReferenzPoint1.y) * -minDimension + } + } + + var newPoint = undefined; + + /*if (!this._oldRefPoint1 || !this._oldRefPoint2 || + absoluteReferenzPoint1.x !== this._oldRefPoint1.x || + absoluteReferenzPoint1.y !== this._oldRefPoint1.y || + absoluteReferenzPoint2.x !== this._oldRefPoint2.x || + absoluteReferenzPoint2.y !== this._oldRefPoint2.y) {*/ + + // Get the new point for the Docker, calucalted by the intersection point of the Shape and the two points + newPoint = this._dockedShape.getIntersectionPoint(absoluteReferenzPoint1, absoluteReferenzPoint2); + + // If there is new point, take the referencepoint as the new point + if (!newPoint) { + newPoint = this.getAbsoluteReferencePoint(); + } + + if (this.parent && this.parent.parent) { + var grandParentPos = this.parent.parent.absoluteXY(); + newPoint.x -= grandParentPos.x; + newPoint.y -= grandParentPos.y; + } + + // Set the bounds to the new point + this.bounds.centerMoveTo(newPoint) + + this._oldRefPoint1 = absoluteReferenzPoint1; + this._oldRefPoint2 = absoluteReferenzPoint2; + } + /*else { + newPoint = this.bounds.center(); + }*/ + + + // } + + // Call the super class + arguments.callee.$.update.apply(this, arguments); + }, + + /** + * Calls the super class refresh method and updates the view of the docker. + */ + refresh: function () { + arguments.callee.$.refresh.apply(this, arguments); + + // Refresh the dockers node + var p = this.bounds.upperLeft(); + this._dockerNode.setAttributeNS(null, 'transform', 'translate(' + p.x + ', ' + p.y + ')'); + + // Refresh the referencepoints node + p = Object.clone(this.referencePoint); + + if (p && this._dockedShape) { + var upL + if (this.parent instanceof ORYX.Core.Edge) { + upL = this._dockedShape.absoluteXY(); + } else { + upL = this._dockedShape.bounds.upperLeft(); + } + p.x += upL.x; + p.y += upL.y; + } else { + p = this.bounds.center(); + } + + this._referencePointNode.setAttributeNS(null, 'transform', 'translate(' + p.x + ', ' + p.y + ')'); + }, + + /** + * Set the reference point + * @param {Object} point + */ + setReferencePoint: function (point) { + // Set the referencepoint + if (this.referencePoint !== point && + (!this.referencePoint || + !point || + this.referencePoint.x !== point.x || + this.referencePoint.y !== point.y)) { + + this.referencePoint = point; + this._changed(); + } + + + // Update directly, because the referencepoint has no influence of the bounds + //this.refresh(); + }, + + /** + * Get the absolute referencepoint + */ + getAbsoluteReferencePoint: function () { + if (!this.referencePoint || !this._dockedShape) { + return undefined; + } else { + var absUL = this._dockedShape.absoluteXY(); + return { + x: this.referencePoint.x + absUL.x, + y: this.referencePoint.y + absUL.y + } + } + }, + + /** + * Set the docked Shape from the docker + * @param {Object} shape + */ + setDockedShape: function (shape) { + + // If there is an old docked Shape + if (this._dockedShape) { + this._dockedShape.bounds.unregisterCallback(this._updateCallback) + + // Delete the Shapes from the incoming and outgoing array + // If this Docker the incoming of the Shape + if (this === this.parent.dockers.first()) { + + this.parent.incoming = this.parent.incoming.without(this._dockedShape); + this._dockedShape.outgoing = this._dockedShape.outgoing.without(this.parent); + + // If this Docker the outgoing of the Shape + } 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); + + } + + } + + + // Set the new Shape + this._dockedShape = shape; + this._dockedShapeBounds = undefined; + var referencePoint = undefined; + + // If there is an Shape, register the updateCallback if there are changes in the shape bounds + if (this._dockedShape) { + + // Add the Shapes to the incoming and outgoing array + // If this Docker the incoming of the Shape + if (this === this.parent.dockers.first()) { + + this.parent.incoming.push(shape); + shape.outgoing.push(this.parent); + + // If this Docker the outgoing of the Shape + } else if (this === this.parent.dockers.last()) { + + this.parent.outgoing.push(shape); + shape.incoming.push(this.parent); + + } + + // Get the bounds and set the new referencepoint + var bounds = this.bounds; + var absUL = shape.absoluteXY(); + + /*if(shape.parent){ + var b = shape.parent.bounds.upperLeft(); + absUL.x -= b.x; + absUL.y -= b.y; + }*/ + + referencePoint = { + x: bounds.center().x - absUL.x, + y: bounds.center().y - absUL.y + } + + this._dockedShapeBounds = this._dockedShape.bounds.clone(); + + this._dockedShape.bounds.registerCallback(this._updateCallback); + + // Set the color of the docker as docked + this.setDockerColor(ORYX.CONFIG.DOCKER_DOCKED_COLOR); + } else { + // Set the color of the docker as undocked + this.setDockerColor(ORYX.CONFIG.DOCKER_UNDOCKED_COLOR); + } + + // Set the referencepoint + this.setReferencePoint(referencePoint); + this._changed(); + //this.update(); + }, + + /** + * Get the docked Shape + */ + getDockedShape: function () { + return this._dockedShape; + }, + + /** + * Returns TRUE if the docker has a docked shape + */ + isDocked: function () { + return !!this._dockedShape; + }, + + /** + * Set the Color of the Docker + * @param {Object} color + */ + setDockerColor: function (color) { + this._dockerNode.lastChild.setAttributeNS(null, "fill", color); + }, + + preventHiding: function (prevent) { + this._preventHiding = Math.max(0, (this._preventHiding || 0) + (prevent ? 1 : -1)); + }, + + /** + * Hides this UIObject and all its children. + */ + hide: function () { + if (this._preventHiding) { + return false; + } + + // Hide docker and reference point + this.node.setAttributeNS(null, 'visibility', 'hidden'); + this._referencePointNode.setAttributeNS(null, 'visibility', 'hidden'); + + this.children.each(function (uiObj) { + uiObj.hide(); + }); + }, + + /** + * Enables visibility of this UIObject and all its children. + */ + show: function () { + // Show docker + this.node.setAttributeNS(null, 'visibility', 'visible'); + + // Hide reference point if the connected shape is an edge + if (this.getDockedShape() instanceof ORYX.Core.Edge) { + this._referencePointNode.setAttributeNS(null, 'visibility', 'hidden'); + } else { + this._referencePointNode.setAttributeNS(null, 'visibility', 'visible'); + } + + this.children.each(function (uiObj) { + uiObj.show(); + }); + }, + + toString: function () { + return "Docker " + this.id + } +});/* + * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +/* + * All code Copyright 2013 KIS Consultancy all rights reserved + */ + +/** + * Init namespaces + */ +if (!ORYX) { + var ORYX = {}; +} +if (!ORYX.Core) { + ORYX.Core = {}; +} +if (!ORYX.Core.Controls) { + ORYX.Core.Controls = {}; +} + + +/** + * @classDescription Represents a magnet that is part of another shape and can + * be attached to dockers. Magnets are used for linking edge objects + * to other Shape objects. + * @extends {Control} + */ +ORYX.Core.Controls.Magnet = ORYX.Core.Controls.Control.extend({ + + /** + * Constructor + */ + construct: function () { + arguments.callee.$.construct.apply(this, arguments); + + //this.anchors = []; + this.anchorLeft; + this.anchorRight; + this.anchorTop; + this.anchorBottom; + + this.bounds.set(0, 0, 16, 16); + + //graft magnet's root node into owner's control group. + 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); + + //this.isChanged = true; + }, + + _update: function () { + arguments.callee.$.update.apply(this, arguments); + + //this.isChanged = true; + }, + + refresh: function () { + arguments.callee.$.refresh.apply(this, arguments); + + var p = this.bounds.upperLeft(); + /*if(this.parent) { + var parentPos = this.parent.bounds.upperLeft(); + p.x += parentPos.x; + p.y += parentPos.y; + }*/ + + this.node.setAttributeNS(null, 'transform', 'translate(' + p.x + ', ' + p.y + ')'); + }, + + show: function () { + //this.refresh(); + arguments.callee.$.show.apply(this, arguments); + }, + + toString: function () { + return "Magnet " + this.id; + } +}); +/* + * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +/* + * All code Copyright 2013 KIS Consultancy all rights reserved + */ + +/** + * Init namespaces + */ +if (!ORYX) { + var ORYX = {}; +} +if (!ORYX.Core) { + ORYX.Core = {}; +} + +/** + * @classDescription Abstract base class for all Nodes. + * @extends ORYX.Core.Shape + */ +ORYX.Core.Node = { + + /** + * Constructor + * @param options {Object} A container for arguments. + * @param stencil {Stencil} + */ + construct: function (options, stencil, facade) { + arguments.callee.$.construct.apply(this, arguments); + + this.isSelectable = true; + this.isMovable = true; + this._dockerUpdated = false; + this.facade = facade; + + this._oldBounds = new ORYX.Core.Bounds(); //init bounds with undefined values + this._svgShapes = []; //array of all SVGShape objects of + // SVG representation + + //TODO vielleicht in shape verschieben? + this.minimumSize = undefined; // {width:..., height:...} + this.maximumSize = undefined; + + //TODO vielleicht in shape oder uiobject verschieben? + // vielleicht sogar isResizable ersetzen? + this.isHorizontallyResizable = false; + this.isVerticallyResizable = false; + + this.dataId = undefined; + + this._init(this._stencil.view()); + this.forcedHeight = -1; + }, + + /** + * This method checks whether the shape is resized correctly and calls the + * super class update method. + */ + _update: function () { + + this.dockers.invoke("update"); + if (this.isChanged) { + + var bounds = this.bounds; + var oldBounds = this._oldBounds; + + if (this.isResized) { + + var widthDelta = bounds.width() / oldBounds.width(); + var heightDelta = bounds.height() / oldBounds.height(); + + //iterate over all relevant svg elements and resize them + this._svgShapes.each(function (svgShape) { + //adjust width + if (svgShape.isHorizontallyResizable) { + svgShape.width = svgShape.oldWidth * widthDelta; + } + //adjust height + if (svgShape.isVerticallyResizable) { + svgShape.height = svgShape.oldHeight * heightDelta; + } + + //check, if anchors are set + var anchorOffset; + var leftIncluded = svgShape.anchorLeft; + var rightIncluded = svgShape.anchorRight; + + if (rightIncluded) { + anchorOffset = oldBounds.width() - (svgShape.oldX + svgShape.oldWidth); + if (leftIncluded) { + svgShape.width = bounds.width() - svgShape.x - anchorOffset; + } else { + svgShape.x = bounds.width() - (anchorOffset + svgShape.width); + } + } else if (!leftIncluded) { + svgShape.x = widthDelta * svgShape.oldX; + if (!svgShape.isHorizontallyResizable) { + svgShape.x = svgShape.x + svgShape.width * widthDelta / 2 - svgShape.width / 2; + } + } + + var topIncluded = svgShape.anchorTop; + var bottomIncluded = svgShape.anchorBottom; + + if (bottomIncluded) { + anchorOffset = oldBounds.height() - (svgShape.oldY + svgShape.oldHeight); + if (topIncluded) { + svgShape.height = bounds.height() - svgShape.y - anchorOffset; + } else { + // Hack for choreography task layouting + if (!svgShape._isYLocked) { + svgShape.y = bounds.height() - (anchorOffset + svgShape.height); + } + } + } else if (!topIncluded) { + svgShape.y = heightDelta * svgShape.oldY; + if (!svgShape.isVerticallyResizable) { + svgShape.y = svgShape.y + svgShape.height * heightDelta / 2 - svgShape.height / 2; + } + } + }); + + //check, if the current bounds is unallowed horizontally or vertically resized + var p = { + x: 0, + y: 0 + }; + if (!this.isHorizontallyResizable && bounds.width() !== oldBounds.width()) { + p.x = oldBounds.width() - bounds.width(); + } + if (!this.isVerticallyResizable && bounds.height() !== oldBounds.height()) { + p.y = oldBounds.height() - bounds.height(); + } + if (p.x !== 0 || p.y !== 0) { + bounds.extend(p); + } + + //check, if the current bounds are between maximum and minimum bounds + p = { + x: 0, + y: 0 + }; + var widthDifference, heightDifference; + if (this.minimumSize) { + + ORYX.Log.debug("Shape (%0)'s min size: (%1x%2)", this, this.minimumSize.width, this.minimumSize.height); + widthDifference = this.minimumSize.width - bounds.width(); + if (widthDifference > 0) { + p.x += widthDifference; + } + heightDifference = this.minimumSize.height - bounds.height(); + if (heightDifference > 0) { + p.y += heightDifference; + } + } + if (this.maximumSize) { + + ORYX.Log.debug("Shape (%0)'s max size: (%1x%2)", this, this.maximumSize.width, this.maximumSize.height); + widthDifference = bounds.width() - this.maximumSize.width; + if (widthDifference > 0) { + p.x -= widthDifference; + } + heightDifference = bounds.height() - this.maximumSize.height; + if (heightDifference > 0) { + p.y -= heightDifference; + } + } + if (p.x !== 0 || p.y !== 0) { + bounds.extend(p); + } + + //update magnets + + var widthDelta = bounds.width() / oldBounds.width(); + var heightDelta = bounds.height() / oldBounds.height(); + + var leftIncluded, rightIncluded, topIncluded, bottomIncluded, center, newX, newY; + + this.magnets.each(function (magnet) { + leftIncluded = magnet.anchorLeft; + rightIncluded = magnet.anchorRight; + topIncluded = magnet.anchorTop; + bottomIncluded = magnet.anchorBottom; + + center = magnet.bounds.center(); + + if (leftIncluded) { + newX = center.x; + } else if (rightIncluded) { + newX = bounds.width() - (oldBounds.width() - center.x) + } else { + newX = center.x * widthDelta; + } + + if (topIncluded) { + newY = center.y; + } else if (bottomIncluded) { + newY = bounds.height() - (oldBounds.height() - center.y); + } else { + newY = center.y * heightDelta; + } + + if (center.x !== newX || center.y !== newY) { + magnet.bounds.centerMoveTo(newX, newY); + } + }); + + //set new position of labels + this.getLabels().each(function (label) { + // Set the position dependings on it anchor + if (!label.isAnchorLeft()) { + if (label.isAnchorRight()) { + label.setX(bounds.width() - (oldBounds.width() - label.oldX)) + } else { + label.setX((label.position ? label.position.x : label.x) * widthDelta); + } + } + if (!label.isAnchorTop()) { + if (label.isAnchorBottom()) { + label.setY(bounds.height() - (oldBounds.height() - label.oldY)); + } else { + label.setY((label.position ? label.position.y : label.y) * heightDelta); + } + } + + // If there is an position, + // set the origin position as well + if (label.position) { + if (!label.isOriginAnchorLeft()) { + if (label.isOriginAnchorRight()) { + label.setOriginX(bounds.width() - (oldBounds.width() - label.oldX)) + } else { + label.setOriginX(label.x * widthDelta); + } + } + if (!label.isOriginAnchorTop()) { + if (label.isOriginAnchorBottom()) { + label.setOriginY(bounds.height() - (oldBounds.height() - label.oldY)); + } else { + label.setOriginY(label.y * heightDelta); + } + } + } + }); + + //update docker + var docker = this.dockers[0]; + if (docker) { + docker.bounds.unregisterCallback(this._dockerChangedCallback); + if (!this._dockerUpdated) { + docker.bounds.centerMoveTo(this.bounds.center()); + this._dockerUpdated = false; + } + + docker.update(); + docker.bounds.registerCallback(this._dockerChangedCallback); + } + this.isResized = false; + } + + this.refresh(); + + this.isChanged = false; + + this._oldBounds = this.bounds.clone(); + } + + this.children.each(function (value) { + if (!(value instanceof ORYX.Core.Controls.Docker)) { + value._update(); + } + }); + + if (this.dockers.length > 0 && !this.dockers.first().getDockedShape()) { + this.dockers.each(function (docker) { + docker.bounds.centerMoveTo(this.bounds.center()) + }.bind(this)) + } + + /*this.incoming.each((function(edge) { + if(!(this.dockers[0] && this.dockers[0].getDockedShape() instanceof ORYX.Core.Node)) + edge._update(true); + }).bind(this)); + + this.outgoing.each((function(edge) { + if(!(this.dockers[0] && this.dockers[0].getDockedShape() instanceof ORYX.Core.Node)) + edge._update(true); + }).bind(this)); */ + }, + + /** + * This method repositions and resizes the SVG representation + * of the shape. + */ + refresh: function () { + arguments.callee.$.refresh.apply(this, arguments); + + /** Movement */ + var x = this.bounds.upperLeft().x; + var y = this.bounds.upperLeft().y; + + // Move owner element + this.node.firstChild.setAttributeNS(null, "transform", "translate(" + x + ", " + y + ")"); + // Move magnets + this.node.childNodes[1].childNodes[1].setAttributeNS(null, "transform", "translate(" + x + ", " + y + ")"); + + /** Resize */ + + //iterate over all relevant svg elements and update them + this._svgShapes.each(function (svgShape) { + svgShape.update(); + }); + }, + + _dockerChanged: function () { + var docker = this.dockers[0]; + + //set the bounds of the the association + this.bounds.centerMoveTo(docker.bounds.center()); + + this._dockerUpdated = true; + //this._update(true); + }, + + /** + * This method traverses a tree of SVGElements and returns + * all SVGShape objects. For each basic shape or path element + * a SVGShape object is initialized. + * + * @param svgNode {SVGElement} + * @return {Array} Array of SVGShape objects + */ + _initSVGShapes: function (svgNode) { + var svgShapes = []; + try { + var svgShape = new ORYX.Core.SVG.SVGShape(svgNode); + svgShapes.push(svgShape); + } catch (e) { + //do nothing + } + + if (svgNode.hasChildNodes()) { + for (var i = 0; i < svgNode.childNodes.length; i++) { + svgShapes = svgShapes.concat(this._initSVGShapes(svgNode.childNodes[i])); + } + } + + return svgShapes; + }, + + /** + * Calculate if the point is inside the Shape + * @param {PointX} + * @param {PointY} + * @param {absoluteBounds} optional: for performance + */ + isPointIncluded: function (pointX, pointY, absoluteBounds) { + // If there is an arguments with the absoluteBounds + var absBounds = absoluteBounds && absoluteBounds instanceof ORYX.Core.Bounds ? absoluteBounds : this.absoluteBounds(); + + if (!absBounds.isIncluded(pointX, pointY)) { + return false; + } else { + + } + + + //point = Object.clone(point); + var ul = absBounds.upperLeft(); + var x = pointX - ul.x; + var y = pointY - ul.y; + + var i = 0; + do { + var isPointIncluded = this._svgShapes[i++].isPointIncluded(x, y); + } while (!isPointIncluded && i < this._svgShapes.length) + + return isPointIncluded; + + /*return this._svgShapes.any(function(svgShape){ + return svgShape.isPointIncluded(point); + });*/ + }, + + + /** + * Calculate if the point is over an special offset area + * @param {Point} + */ + isPointOverOffset: function (pointX, pointY) { + var isOverEl = arguments.callee.$.isPointOverOffset.apply(this, arguments); + + if (isOverEl) { + + // If there is an arguments with the absoluteBounds + var absBounds = this.absoluteBounds(); + absBounds.widen(-ORYX.CONFIG.BORDER_OFFSET); + + if (!absBounds.isIncluded(pointX, pointY)) { + return true; + } + } + + return false; + + }, + + serialize: function () { + var result = arguments.callee.$.serialize.apply(this); + + // Add the docker's bounds + // nodes only have at most one docker! + this.dockers.each((function (docker) { + if (docker.getDockedShape()) { + var center = docker.referencePoint; + center = center ? center : docker.bounds.center(); + result.push({ + name: 'docker', + prefix: 'oryx', + value: $H(center).values().join(','), + type: 'literal' + }); + } + }).bind(this)); + + // Get the spezific serialized object from the stencil + try { + //result = this.getStencil().serialize(this, result); + + var serializeEvent = this.getStencil().serialize(); + + /* + * call serialize callback by reference, result should be found + * in serializeEvent.result + */ + if (serializeEvent.type) { + serializeEvent.shape = this; + serializeEvent.data = result; + serializeEvent.result = undefined; + serializeEvent.forceExecution = true; + + this._delegateEvent(serializeEvent); + + if (serializeEvent.result) { + result = serializeEvent.result; + } + } + } catch (e) { + } + return result; + }, + + deserialize: function (data) { + arguments.callee.$.deserialize.apply(this, arguments); + + try { + //data = this.getStencil().deserialize(this, data); + + var deserializeEvent = this.getStencil().deserialize(); + + /* + * call serialize callback by reference, result should be found + * in serializeEventInfo.result + */ + if (deserializeEvent.type) { + deserializeEvent.shape = this; + deserializeEvent.data = data; + deserializeEvent.result = undefined; + deserializeEvent.forceExecution = true; + + this._delegateEvent(deserializeEvent); + if (deserializeEvent.result) { + data = deserializeEvent.result; + } + } + } catch (e) { + } + + // Set the outgoing shapes + var outgoing = data.findAll(function (ser) { + return (ser.prefix + "-" + ser.name) == 'raziel-outgoing' + }); + outgoing.each((function (obj) { + // TODO: Look at Canvas + if (!this.parent) { + return + } + ; + + // Set outgoing Shape + var next = this.getCanvas().getChildShapeByResourceId(obj.value); + + if (next) { + if (next instanceof ORYX.Core.Edge) { + //Set the first docker of the next shape + next.dockers.first().setDockedShape(this); + next.dockers.first().setReferencePoint(next.dockers.first().bounds.center()); + } else if (next.dockers.length > 0) { //next is a node and next has a docker + next.dockers.first().setDockedShape(this); + //next.dockers.first().setReferencePoint({x: this.bounds.width() / 2.0, y: this.bounds.height() / 2.0}); + } + } + + }).bind(this)); + + if (this.dockers.length === 1) { + var dockerPos; + dockerPos = data.find(function (entry) { + return (entry.prefix + "-" + entry.name === "oryx-dockers"); + }); + + if (dockerPos) { + var points = dockerPos.value.replace(/,/g, " ").split(" ").without("").without("#"); + if (points.length === 2 && this.dockers[0].getDockedShape()) { + this.dockers[0].setReferencePoint({ + x: parseFloat(points[0]), + y: parseFloat(points[1]) + }); + } else { + this.dockers[0].bounds.centerMoveTo(parseFloat(points[0]), parseFloat(points[1])); + } + } + } + }, + + /** + * This method excepts the SVGDoucment that is the SVG representation + * of this shape. + * The bounds of the shape are calculated, the SVG representation's upper left point + * is moved to 0,0 and it the method sets if this shape is resizable. + * + * @param {SVGDocument} svgDocument + */ + _init: function (svgDocument) { + arguments.callee.$._init.apply(this, arguments); + + var svgNode = svgDocument.getElementsByTagName("g")[0]; //outer most g node + // set all required attributes + var attributeTitle = svgDocument.ownerDocument.createAttribute("title"); + attributeTitle.nodeValue = this.getStencil().title(); + svgNode.setAttributeNode(attributeTitle); + + var attributeId = svgDocument.ownerDocument.createAttribute("id"); + attributeId.nodeValue = this.id; + svgNode.setAttributeNode(attributeId); + + // + var stencilTargetNode = this.node.childNodes[0].childNodes[0]; //" + svgNode = stencilTargetNode.appendChild(svgNode); + + // Add to the EventHandler + this.addEventHandlers(svgNode.parentNode); + + /**set minimum and maximum size*/ + var minSizeAttr = svgNode.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, "minimumSize"); + if (minSizeAttr) { + minSizeAttr = minSizeAttr.replace("/,/g", " "); + var minSizeValues = minSizeAttr.split(" "); + minSizeValues = minSizeValues.without(""); + + if (minSizeValues.length > 1) { + this.minimumSize = { + width: parseFloat(minSizeValues[0]), + height: parseFloat(minSizeValues[1]) + }; + } else { + //set minimumSize to (1,1), so that width and height of the stencil can never be (0,0) + this.minimumSize = { + width: 1, + height: 1 + }; + } + } + + var maxSizeAttr = svgNode.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, "maximumSize"); + if (maxSizeAttr) { + maxSizeAttr = maxSizeAttr.replace("/,/g", " "); + var maxSizeValues = maxSizeAttr.split(" "); + maxSizeValues = maxSizeValues.without(""); + + if (maxSizeValues.length > 1) { + this.maximumSize = { + width: parseFloat(maxSizeValues[0]), + height: parseFloat(maxSizeValues[1]) + }; + } + } + + if (this.minimumSize && this.maximumSize && + (this.minimumSize.width > this.maximumSize.width || + this.minimumSize.height > this.maximumSize.height)) { + + //TODO wird verschluckt!!! + throw this + ": Minimum Size must be greater than maxiumSize."; + } + + /**get current bounds and adjust it to upperLeft == (0,0)*/ + //initialize all SVGShape objects + this._svgShapes = this._initSVGShapes(svgNode); + + //get upperLeft and lowerRight of stencil + var upperLeft = { + x: undefined, + y: undefined + }; + var lowerRight = { + x: undefined, + y: undefined + }; + var me = this; + this._svgShapes.each(function (svgShape) { + upperLeft.x = (upperLeft.x !== undefined) ? Math.min(upperLeft.x, svgShape.x) : svgShape.x; + upperLeft.y = (upperLeft.y !== undefined) ? Math.min(upperLeft.y, svgShape.y) : svgShape.y; + lowerRight.x = (lowerRight.x !== undefined) ? Math.max(lowerRight.x, svgShape.x + svgShape.width) : svgShape.x + svgShape.width; + lowerRight.y = (lowerRight.y !== undefined) ? Math.max(lowerRight.y, svgShape.y + svgShape.height) : svgShape.y + svgShape.height; + + /** set if resizing is enabled */ + //TODO isResizable durch die beiden anderen booleans ersetzen? + if (svgShape.isHorizontallyResizable) { + me.isHorizontallyResizable = true; + me.isResizable = true; + } + if (svgShape.isVerticallyResizable) { + me.isVerticallyResizable = true; + me.isResizable = true; + } + if (svgShape.anchorTop && svgShape.anchorBottom) { + me.isVerticallyResizable = true; + me.isResizable = true; + } + if (svgShape.anchorLeft && svgShape.anchorRight) { + me.isHorizontallyResizable = true; + me.isResizable = true; + } + }); + + //move all SVGShapes by -upperLeft + this._svgShapes.each(function (svgShape) { + svgShape.x -= upperLeft.x; + svgShape.y -= upperLeft.y; + svgShape.update(); + }); + + //set bounds of shape + //the offsets are also needed for positioning the magnets and the docker + var offsetX = upperLeft.x; + var offsetY = upperLeft.y; + + lowerRight.x -= offsetX; + lowerRight.y -= offsetY; + upperLeft.x = 0; + upperLeft.y = 0; + + //prevent that width or height of initial bounds is 0 + if (lowerRight.x === 0) { + lowerRight.x = 1; + } + if (lowerRight.y === 0) { + lowerRight.y = 1; + } + + this._oldBounds.set(upperLeft, lowerRight); + this.bounds.set(upperLeft, lowerRight); + + /**initialize magnets */ + + var magnets = svgDocument.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_ORYX, "magnets"); + + if (magnets && magnets.length > 0) { + + magnets = $A(magnets[0].getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_ORYX, "magnet")); + + var me = this; + magnets.each(function (magnetElem) { + var magnet = new ORYX.Core.Controls.Magnet({ + eventHandlerCallback: me.eventHandlerCallback + }); + var cx = parseFloat(magnetElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, "cx")); + var cy = parseFloat(magnetElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, "cy")); + magnet.bounds.centerMoveTo({ + x: cx - offsetX, + y: cy - offsetY + }); + + //get anchors + var anchors = magnetElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, "anchors"); + if (anchors) { + anchors = anchors.replace("/,/g", " "); + anchors = anchors.split(" ").without(""); + for (var i = 0; i < anchors.length; i++) { + switch (anchors[i].toLowerCase()) { + case "left": + magnet.anchorLeft = true; + break; + case "right": + magnet.anchorRight = true; + break; + case "top": + magnet.anchorTop = true; + break; + case "bottom": + magnet.anchorBottom = true; + break; + } + } + } + + me.add(magnet); + + //check, if magnet is default magnet + if (!this._defaultMagnet) { + var defaultAttr = magnetElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, "default"); + if (defaultAttr && defaultAttr.toLowerCase() === "yes") { + me._defaultMagnet = magnet; + } + } + }); + } else { + // Add a Magnet in the Center of Shape + var magnet = new ORYX.Core.Controls.Magnet(); + magnet.bounds.centerMoveTo(this.bounds.width() / 2, this.bounds.height() / 2); + this.add(magnet); + } + + /**initialize docker */ + var dockerElem = svgDocument.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_ORYX, "docker"); + + if (dockerElem && dockerElem.length > 0) { + dockerElem = dockerElem[0]; + var docker = this.createDocker(); + var cx = parseFloat(dockerElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, "cx")); + var cy = parseFloat(dockerElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, "cy")); + docker.bounds.centerMoveTo({ + x: cx - offsetX, + y: cy - offsetY + }); + + //get anchors + var anchors = dockerElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, "anchors"); + if (anchors) { + anchors = anchors.replace("/,/g", " "); + anchors = anchors.split(" ").without(""); + + for (var i = 0; i < anchors.length; i++) { + switch (anchors[i].toLowerCase()) { + case "left": + docker.anchorLeft = true; + break; + case "right": + docker.anchorRight = true; + break; + case "top": + docker.anchorTop = true; + break; + case "bottom": + docker.anchorBottom = true; + break; + } + } + } + } + + /**initialize labels*/ + var textElems = svgNode.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'text'); + $A(textElems).each((function (textElem) { + var label = new ORYX.Core.SVG.Label({ + textElement: textElem, + shapeId: this.id + }); + label.x -= offsetX; + label.y -= offsetY; + this._labels[label.id] = label; + + label.registerOnChange(this.layout.bind(this)); + + // Only apply fitting on form-components + if (this._stencil.id().indexOf(ORYX.CONFIG.FORM_ELEMENT_ID_PREFIX) == 0) { + label.registerOnChange(this.fitToLabels.bind(this)); + } + + }).bind(this)); + }, + + fitToLabels: function () { + var y = 0; + + this.getLabels().each(function (label) { + var lr = label.getY() + label.getHeight(); + if (lr > y) { + y = lr; + } + }); + + var bounds = this.bounds; + var boundsChanged = false; + + if (this.minimumSize) { + // Check if y-value exceeds the min-value. If not, stick to this value. + var minHeight = this.minimumSize.height; + if (y < minHeight && bounds.height() > minHeight && minHeight > this.forcedHeight) { + bounds.set(bounds.upperLeft().x, bounds.upperLeft().y, bounds.lowerRight().x, bounds.upperLeft().y + minHeight); + boundsChanged = true; + } else if (y > minHeight && bounds.height() != y && y > this.forcedHeight) { + bounds.set(bounds.upperLeft().x, bounds.upperLeft().y, bounds.lowerRight().x, bounds.upperLeft().y + y); + boundsChanged = true; + } else if (bounds.height() > this.forcedHeight && this.forcedHeight > 0) { + bounds.set(bounds.upperLeft().x, bounds.upperLeft().y, bounds.lowerRight().x, bounds.upperLeft().y + this.forcedHeight); + boundsChanged = true; + } + } + + if (boundsChanged) { + // Force facade to re-layout since bounds are changed AFTER layout has been performed + if (this.facade.getCanvas() != null) { + this.facade.getCanvas().update(); + } + + // Re-select if needed to force the select + if (this.facade.getSelection().member(this)) { + var selectedNow = this.facade.getSelection(); + this.facade.setSelection([]); + this.facade.setSelection(selectedNow); + } + } + }, + + /** + * Override the Method, that a docker is not shown + * + */ + createDocker: function () { + var docker = new ORYX.Core.Controls.Docker({eventHandlerCallback: this.eventHandlerCallback}); + docker.bounds.registerCallback(this._dockerChangedCallback); + + this.dockers.push(docker); + docker.parent = this; + docker.bounds.registerCallback(this._changedCallback); + + return docker + }, + + toString: function () { + return this._stencil.title() + " " + this.id + } +}; +ORYX.Core.Node = ORYX.Core.Shape.extend(ORYX.Core.Node); +/* + * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +/* + * All code Copyright 2013 KIS Consultancy all rights reserved + */ + +NAMESPACE_SVG = "http://www.w3.org/2000/svg"; +NAMESPACE_ORYX = "http://www.b3mn.org/oryx"; + + +/** + * Init namespaces + */ +if (!ORYX) { + var ORYX = {}; +} +if (!ORYX.Core) { + ORYX.Core = {}; +} + + +/** + * @classDescription Abstract base class for all connections. + * @extends {ORYX.Core.Shape} + * @param options {Object} + * + * TODO da die verschiebung der Edge nicht ueber eine + * translation gemacht wird, die sich auch auf alle kind UIObjects auswirkt, + * muessen die kinder hier beim verschieben speziell betrachtet werden. + * Das sollte ueberarbeitet werden. + * + */ +ORYX.Core.Edge = { + /** + * Constructor + * @param {Object} options + * @param {Stencil} stencil + */ + construct: function (options, stencil, facade) { + arguments.callee.$.construct.apply(this, arguments); + + this.isMovable = true; + this.isSelectable = true; + + this._dockerUpdated = false; + + this._markers = new Hash(); //a hash map of SVGMarker objects where keys are the marker ids + this._paths = []; + this._interactionPaths = []; + this._dockersByPath = new Hash(); + this._markersByPath = new Hash(); + + /* Data structures to store positioning information of attached child nodes */ + this.attachedNodePositionData = new Hash(); + + //TODO was muss hier initial erzeugt werden? + var stencilNode = this.node.childNodes[0].childNodes[0]; + stencilNode = ORYX.Editor.graft("http://www.w3.org/2000/svg", stencilNode, ['g', { + "pointer-events": "painted" + }]); + + //Add to the EventHandler + this.addEventHandlers(stencilNode.parentNode); + + + this._oldBounds = this.bounds.clone(); + + //load stencil + this._init(this._stencil.view()); + + if (stencil instanceof Array) { + this.deserialize(stencil); + } + + }, + + _update: function (force) { + if (this._dockerUpdated || this.isChanged || force) { + + this.dockers.invoke("update"); + + if (false && (this.bounds.width() === 0 || this.bounds.height() === 0)) { + var width = this.bounds.width(); + var height = this.bounds.height(); + this.bounds.extend({ + x: width === 0 ? 2 : 0, + y: height === 0 ? 2 : 0 + }); + this.bounds.moveBy({ + x: width === 0 ? -1 : 0, + y: height === 0 ? -1 : 0 + }); + + } + + // TODO: Bounds muss abhaengig des Eltern-Shapes gesetzt werden + var upL = this.bounds.upperLeft(); + var oldUpL = this._oldBounds.upperLeft(); + var oldWidth = this._oldBounds.width() === 0 ? this.bounds.width() : this._oldBounds.width(); + var oldHeight = this._oldBounds.height() === 0 ? this.bounds.height() : this._oldBounds.height(); + var diffX = upL.x - oldUpL.x; + var diffY = upL.y - oldUpL.y; + var diffWidth = (this.bounds.width() / oldWidth) || 1; + var diffHeight = (this.bounds.height() / oldHeight) || 1; + + this.dockers.each((function (docker) { + // Unregister on BoundsChangedCallback + docker.bounds.unregisterCallback(this._dockerChangedCallback); + + // If there is any changes at the edge and is there is not an DockersUpdate + // set the new bounds to the docker + if (!this._dockerUpdated) { + docker.bounds.moveBy(diffX, diffY); + + if (diffWidth !== 1 || diffHeight !== 1) { + var relX = docker.bounds.upperLeft().x - upL.x; + var relY = docker.bounds.upperLeft().y - upL.y; + + docker.bounds.moveTo(upL.x + relX * diffWidth, upL.y + relY * diffHeight); + } + } + // Do Docker update and register on DockersBoundChange + docker.update(); + docker.bounds.registerCallback(this._dockerChangedCallback); + + }).bind(this)); + + if (this._dockerUpdated) { + var a = this.dockers.first().bounds.center(); + var b = this.dockers.first().bounds.center(); + + this.dockers.each((function (docker) { + var center = docker.bounds.center(); + a.x = Math.min(a.x, center.x); + a.y = Math.min(a.y, center.y); + b.x = Math.max(b.x, center.x); + b.y = Math.max(b.y, center.y); + }).bind(this)); + + //set the bounds of the the association + this.bounds.set(Object.clone(a), Object.clone(b)); + } + + upL = this.bounds.upperLeft(); + oldUpL = this._oldBounds.upperLeft(); + diffWidth = (this.bounds.width() / (oldWidth || this.bounds.width())); + diffHeight = (this.bounds.height() / (oldHeight || this.bounds.height())); + diffX = upL.x - oldUpL.x; + diffY = upL.y - oldUpL.y; + + //reposition labels + this.getLabels().each(function (label) { + + if (label.getReferencePoint()) { + var ref = label.getReferencePoint(); + var from = ref.segment.from, to = ref.segment.to; + if (!from || !from.parent || !to || !to.parent) { + return; + } + + var fromPosition = from.bounds.center(), toPosition = to.bounds.center(); + + if (fromPosition.x === ref.segment.fromPosition.x && fromPosition.y === ref.segment.fromPosition.y && + toPosition.x === ref.segment.toPosition.x && toPosition.y === ref.segment.toPosition.y && !ref.dirty) { + return; + } + + if (!this.parent.initializingShapes) { + var oldDistance = ORYX.Core.Math.getDistanceBetweenTwoPoints(ref.segment.fromPosition, ref.segment.toPosition, ref.intersection); + var newIntersection = ORYX.Core.Math.getPointBetweenTwoPoints(fromPosition, toPosition, isNaN(oldDistance) ? 0.5 : oldDistance); + + /** + * Set position + */ + // Get the orthogonal identity vector of the current segment + var oiv = ORYX.Core.Math.getOrthogonalIdentityVector(fromPosition, toPosition); + var isHor = Math.abs(oiv.y) === 1, isVer = Math.abs(oiv.x) === 1; + oiv.x *= ref.distance; + oiv.y *= ref.distance; // vector * distance + oiv.x += newIntersection.x; + oiv.y += newIntersection.y; // vector + the intersection point + var mx = isHor && ref.orientation && (ref.iorientation || ref.orientation).endsWith("r") ? -label.getWidth() : 0; + var my = isVer && ref.orientation && (ref.iorientation || ref.orientation).startsWith("l") ? -label.getHeight() + 2 : 0; + label.setX(oiv.x + mx); + label.setY(oiv.y + my); + + // Update the reference point + this.updateReferencePointOfLabel(label, newIntersection, from, to); + } else { + var oiv = ORYX.Core.Math.getOrthogonalIdentityVector(fromPosition, toPosition); + oiv.x *= ref.distance; + oiv.y *= ref.distance; // vector * distance + oiv.x += ref.intersection.x; + oiv.y += ref.intersection.y; // vector + the intersection point + label.setX(oiv.x); + label.setY(oiv.y); + ref.segment.fromPosition = fromPosition; + ref.segment.toPosition = toPosition; + } + + return; + } + + // Update label position if no reference point is set + if (label.position && !this.parent.initializingShapes) { + var x = label.position.x + (diffX * (diffWidth || 1)); + if (x > this.bounds.lowerRight().x) { + x += this.bounds.width() - (this.bounds.width() / (diffWidth || 1)); + } + + var y = label.position.y + (diffY * (diffHeight || 1)); + if (y > this.bounds.lowerRight().y) { + y += this.bounds.height() - (this.bounds.height() / (diffHeight || 1)); + } + label.setX(x); + label.setY(y); + return; + } + + switch (label.getEdgePosition()) { + case "starttop": + var angle = this._getAngle(this.dockers[0], this.dockers[1]); + var pos = this.dockers.first().bounds.center(); + + if (angle <= 90 || angle > 270) { + label.horizontalAlign("left"); + label.verticalAlign("bottom"); + label.x = pos.x + label.getOffsetTop(); + label.y = pos.y - label.getOffsetTop(); + label.rotate(360 - angle, pos); + } else { + label.horizontalAlign("right"); + label.verticalAlign("bottom"); + label.x = pos.x - label.getOffsetTop(); + label.y = pos.y - label.getOffsetTop(); + label.rotate(180 - angle, pos); + } + + break; + + case "startmiddle": + var angle = this._getAngle(this.dockers[0], this.dockers[1]); + var pos = this.dockers.first().bounds.center(); + + if (angle <= 90 || angle > 270) { + label.horizontalAlign("left"); + label.verticalAlign("bottom"); + label.x = pos.x + 2; + label.y = pos.y + 4; + label.rotate(360 - angle, pos); + } else { + label.horizontalAlign("right"); + label.verticalAlign("bottom"); + label.x = pos.x + 1; + label.y = pos.y + 4; + label.rotate(180 - angle, pos); + } + + break; + + case "startbottom": + var angle = this._getAngle(this.dockers[0], this.dockers[1]); + var pos = this.dockers.first().bounds.center(); + + if (angle <= 90 || angle > 270) { + label.horizontalAlign("left"); + label.verticalAlign("top"); + label.x = pos.x + label.getOffsetBottom(); + label.y = pos.y + label.getOffsetBottom(); + label.rotate(360 - angle, pos); + } else { + label.horizontalAlign("right"); + label.verticalAlign("top"); + label.x = pos.x - label.getOffsetBottom(); + label.y = pos.y + label.getOffsetBottom(); + label.rotate(180 - angle, pos); + } + + break; + case "midtop": + var numOfDockers = this.dockers.length; + if (numOfDockers % 2 == 0) { + var angle = this._getAngle(this.dockers[numOfDockers / 2 - 1], this.dockers[numOfDockers / 2]) + var pos1 = this.dockers[numOfDockers / 2 - 1].bounds.center(); + var pos2 = this.dockers[numOfDockers / 2].bounds.center(); + var pos = {x: (pos1.x + pos2.x) / 2.0, y: (pos1.y + pos2.y) / 2.0}; + + label.horizontalAlign("center"); + label.verticalAlign("bottom"); + label.x = pos.x; + label.y = pos.y - label.getOffsetTop(); + + if (angle <= 90 || angle > 270) { + label.rotate(360 - angle, pos); + } else { + label.rotate(180 - angle, pos); + } + } else { + var index = parseInt(numOfDockers / 2); + var angle = this._getAngle(this.dockers[index], this.dockers[index + 1]) + var pos = this.dockers[index].bounds.center(); + + if (angle <= 90 || angle > 270) { + label.horizontalAlign("left"); + label.verticalAlign("bottom"); + label.x = pos.x + label.getOffsetTop(); + label.y = pos.y - label.getOffsetTop(); + label.rotate(360 - angle, pos); + } else { + label.horizontalAlign("right"); + label.verticalAlign("bottom"); + label.x = pos.x - label.getOffsetTop(); + label.y = pos.y - label.getOffsetTop(); + label.rotate(180 - angle, pos); + } + } + + break; + case "midbottom": + var numOfDockers = this.dockers.length; + if (numOfDockers % 2 == 0) { + var angle = this._getAngle(this.dockers[numOfDockers / 2 - 1], this.dockers[numOfDockers / 2]) + var pos1 = this.dockers[numOfDockers / 2 - 1].bounds.center(); + var pos2 = this.dockers[numOfDockers / 2].bounds.center(); + var pos = {x: (pos1.x + pos2.x) / 2.0, y: (pos1.y + pos2.y) / 2.0}; + + label.horizontalAlign("center"); + label.verticalAlign("top"); + label.x = pos.x; + label.y = pos.y + label.getOffsetTop(); + + if (angle <= 90 || angle > 270) { + label.rotate(360 - angle, pos); + } else { + label.rotate(180 - angle, pos); + } + } else { + var index = parseInt(numOfDockers / 2); + var angle = this._getAngle(this.dockers[index], this.dockers[index + 1]) + var pos = this.dockers[index].bounds.center(); + + if (angle <= 90 || angle > 270) { + label.horizontalAlign("left"); + label.verticalAlign("top"); + label.x = pos.x + label.getOffsetBottom(); + label.y = pos.y + label.getOffsetBottom(); + label.rotate(360 - angle, pos); + } else { + label.horizontalAlign("right"); + label.verticalAlign("top"); + label.x = pos.x - label.getOffsetBottom(); + label.y = pos.y + label.getOffsetBottom(); + label.rotate(180 - angle, pos); + } + } + + break; + case "endtop": + var length = this.dockers.length; + var angle = this._getAngle(this.dockers[length - 2], this.dockers[length - 1]); + var pos = this.dockers.last().bounds.center(); + + if (angle <= 90 || angle > 270) { + label.horizontalAlign("right"); + label.verticalAlign("bottom"); + label.x = pos.x - label.getOffsetTop(); + label.y = pos.y - label.getOffsetTop(); + label.rotate(360 - angle, pos); + } else { + label.horizontalAlign("left"); + label.verticalAlign("bottom"); + label.x = pos.x + label.getOffsetTop(); + label.y = pos.y - label.getOffsetTop(); + label.rotate(180 - angle, pos); + } + + break; + case "endbottom": + var length = this.dockers.length; + var angle = this._getAngle(this.dockers[length - 2], this.dockers[length - 1]); + var pos = this.dockers.last().bounds.center(); + + if (angle <= 90 || angle > 270) { + label.horizontalAlign("right"); + label.verticalAlign("top"); + label.x = pos.x - label.getOffsetBottom(); + label.y = pos.y + label.getOffsetBottom(); + label.rotate(360 - angle, pos); + } else { + label.horizontalAlign("left"); + label.verticalAlign("top"); + label.x = pos.x + label.getOffsetBottom(); + label.y = pos.y + label.getOffsetBottom(); + label.rotate(180 - angle, pos); + } + + break; + } + }.bind(this)); + + this.children.each(function (value) { + if (value instanceof ORYX.Core.Node) { + this.calculatePositionOfAttachedChildNode.call(this, value); + } + }.bind(this)); + + this.refreshAttachedNodes(); + this.refresh(); + + this.isChanged = false; + this._dockerUpdated = false; + + this._oldBounds = this.bounds.clone(); + } + + + // IE10 specific fix, start and end-markes get left behind when moving path + var userAgent = navigator.userAgent; + if (navigator.appVersion.indexOf("MSIE 10") !== -1 || (userAgent.indexOf('Trident') !== -1 && userAgent.indexOf('rv:11') !== -1)) { + this.node.parentNode.insertBefore(this.node, this.node); + } + }, + + /** + * Moves a point to the upperLeft of a node's bounds. + * + * @param {point} point + * The point to move + * @param {ORYX.Core.Bounds} bounds + * The Bounds of the related noe + */ + movePointToUpperLeftOfNode: function (point, bounds) { + point.x -= bounds.width() / 2; + point.y -= bounds.height() / 2; + }, + + /** + * Refreshes the visual representation of edge's attached nodes. + */ + refreshAttachedNodes: function () { + this.attachedNodePositionData.values().each(function (nodeData) { + var startPoint = nodeData.segment.docker1.bounds.center(); + var endPoint = nodeData.segment.docker2.bounds.center(); + this.relativizePoint(startPoint); + this.relativizePoint(endPoint); + + var newNodePosition = new Object(); + + /* Calculate new x-coordinate */ + newNodePosition.x = startPoint.x + + nodeData.relativDistanceFromDocker1 + * (endPoint.x - startPoint.x); + + /* Calculate new y-coordinate */ + newNodePosition.y = startPoint.y + + nodeData.relativDistanceFromDocker1 + * (endPoint.y - startPoint.y); + + /* Convert new position to the upper left of the node */ + this.movePointToUpperLeftOfNode(newNodePosition, nodeData.node.bounds); + + /* Move node to its new position */ + nodeData.node.bounds.moveTo(newNodePosition); + nodeData.node._update(); + + }.bind(this)); + }, + + /** + * Calculates the position of an edge's child node. The node is placed on + * the path of the edge. + * + * @param {node} + * The node to calculate the new position + * @return {Point} + * The calculated upper left point of the node's shape. + */ + calculatePositionOfAttachedChildNode: function (node) { + /* Initialize position */ + var position = new Object(); + position.x = 0; + position.y = 0; + + /* Case: Node was just added */ + if (!this.attachedNodePositionData[node.getId()]) { + this.attachedNodePositionData[node.getId()] = new Object(); + this.attachedNodePositionData[node.getId()] + .relativDistanceFromDocker1 = 0; + this.attachedNodePositionData[node.getId()].node = node; + this.attachedNodePositionData[node.getId()].segment = new Object(); + this.findEdgeSegmentForNode(node); + } else if (node.isChanged) { + this.findEdgeSegmentForNode(node); + } + + + }, + + /** + * Finds the appropriate edge segement for a node. + * The segment is choosen, which has the smallest distance to the node. + * + * @param {ORYX.Core.Node} node + * The concerning node + */ + findEdgeSegmentForNode: function (node) { + var length = this.dockers.length; + var smallestDistance = undefined; + + for (i = 1; i < length; i++) { + var lineP1 = this.dockers[i - 1].bounds.center(); + var lineP2 = this.dockers[i].bounds.center(); + this.relativizePoint(lineP1); + this.relativizePoint(lineP2); + + var nodeCenterPoint = node.bounds.center(); + var distance = ORYX.Core.Math.distancePointLinie( + lineP1, + lineP2, + nodeCenterPoint, + true); + + if ((distance || distance == 0) && ((!smallestDistance && smallestDistance != 0) + || distance < smallestDistance)) { + + smallestDistance = distance; + + this.attachedNodePositionData[node.getId()].segment.docker1 = + this.dockers[i - 1]; + this.attachedNodePositionData[node.getId()].segment.docker2 = + this.dockers[i]; + + } + + /* Either the distance does not match the segment or the distance + * between docker1 and docker2 is 0 + * + * In this case choose the nearest docker as attaching point. + * + */ + if (!distance && !smallestDistance && smallestDistance != 0) { + (ORYX.Core.Math.getDistancePointToPoint(nodeCenterPoint, lineP1) + < ORYX.Core.Math.getDistancePointToPoint(nodeCenterPoint, lineP2)) ? + this.attachedNodePositionData[node.getId()].relativDistanceFromDocker1 = 0 : + this.attachedNodePositionData[node.getId()].relativDistanceFromDocker1 = 1; + this.attachedNodePositionData[node.getId()].segment.docker1 = + this.dockers[i - 1]; + this.attachedNodePositionData[node.getId()].segment.docker2 = + this.dockers[i]; + } + } + + /* Calculate position on edge segment for the node */ + if (smallestDistance || smallestDistance == 0) { + this.attachedNodePositionData[node.getId()].relativDistanceFromDocker1 = + this.getLineParameterForPosition( + this.attachedNodePositionData[node.getId()].segment.docker1, + this.attachedNodePositionData[node.getId()].segment.docker2, + node); + } + }, + + + /** + * + * @param {ORYX.Core.Node|Object} node or position + * @return {Object} An object with the following attribute: {ORYX.Core.Docker} fromDocker, {ORYX.Core.Docker} toDocker, {X/Y} position, {int} distance + */ + findSegment: function (node) { + + var length = this.dockers.length; + var result; + + var nodeCenterPoint = node instanceof ORYX.Core.UIObject ? node.bounds.center() : node; + + for (i = 1; i < length; i++) { + var lineP1 = this.dockers[i - 1].bounds.center(); + var lineP2 = this.dockers[i].bounds.center(); + + var distance = ORYX.Core.Math.distancePointLinie(lineP1, lineP2, nodeCenterPoint, true); + + if (typeof distance == "number" && (result === undefined || distance < result.distance)) { + result = { + distance: distance, + fromDocker: this.dockers[i - 1], + toDocker: this.dockers[i] + } + + } + } + return result; + }, + + /** + * Returns the value of the scalar to determine the position of the node on + * line defined by docker1 and docker2. + * + * @param {point} docker1 + * The docker that defines the start of the line segment + * @param {point} docker2 + * The docker that defines the end of the line segment + * @param {ORYX.Core.Node} node + * The concerning node + * + * @return {float} positionParameter + * The scalar value to determine the position on the line + */ + getLineParameterForPosition: function (docker1, docker2, node) { + var dockerPoint1 = docker1.bounds.center(); + var dockerPoint2 = docker2.bounds.center(); + this.relativizePoint(dockerPoint1); + this.relativizePoint(dockerPoint2); + + var intersectionPoint = ORYX.Core.Math.getPointOfIntersectionPointLine( + dockerPoint1, + dockerPoint2, + node.bounds.center(), true); + if (!intersectionPoint) { + return 0; + } + + var relativeDistance = + ORYX.Core.Math.getDistancePointToPoint(intersectionPoint, dockerPoint1) / + ORYX.Core.Math.getDistancePointToPoint(dockerPoint1, dockerPoint2); + + return relativeDistance; + }, + /** + * Makes point relative to the upper left of the edge's bound. + * + * @param {point} point + * The point to relativize + */ + relativizePoint: function (point) { + point.x -= this.bounds.upperLeft().x; + point.y -= this.bounds.upperLeft().y; + }, + + /** + * Move the first and last docker and calls the refresh method. + * Attention: This does not calculates intersection point between the + * edge and the bounded nodes. This only works if only the nodes are + * moves. + * + */ + optimizedUpdate: function () { + + var updateDocker = function (docker) { + if (!docker._dockedShape || !docker._dockedShapeBounds) + return; + var off = { + x: docker._dockedShape.bounds.a.x - docker._dockedShapeBounds.a.x, + y: docker._dockedShape.bounds.a.y - docker._dockedShapeBounds.a.y + }; + docker.bounds.moveBy(off); + docker._dockedShapeBounds.moveBy(off); + } + + updateDocker(this.dockers.first()); + updateDocker(this.dockers.last()); + + this.refresh(); + }, + + refresh: function () { + //call base class refresh method + arguments.callee.$.refresh.apply(this, arguments); + + //TODO consider points for marker mids + var lastPoint; + this._paths.each((function (path, index) { + var dockers = this._dockersByPath[path.id]; + var c = undefined; + var d = undefined; + if (lastPoint) { + d = "M" + lastPoint.x + " " + lastPoint.y; + } else { + c = dockers[0].bounds.center(); + lastPoint = c; + + d = "M" + c.x + " " + c.y; + } + + for (var i = 1; i < dockers.length; i++) { + // for each docker, draw a line to the center + c = dockers[i].bounds.center(); + d = d + "L" + c.x + " " + c.y + " "; + lastPoint = c; + } + + path.setAttributeNS(null, "d", d); + this._interactionPaths[index].setAttributeNS(null, "d", d); + + }).bind(this)); + + + /* move child shapes of an edge */ + if (this.getChildNodes().length > 0) { + var x = this.bounds.upperLeft().x; + var y = this.bounds.upperLeft().y; + + this.node.firstChild.childNodes[1].setAttributeNS(null, "transform", "translate(" + x + ", " + y + ")"); + } + + }, + + /** + * Calculate the Border Intersection Point between two points + * @param {PointA} + * @param {PointB} + */ + getIntersectionPoint: function () { + + var length = Math.floor(this.dockers.length / 2) + + return ORYX.Core.Math.midPoint(this.dockers[length - 1].bounds.center(), this.dockers[length].bounds.center()) + }, + + /** + * Returns TRUE if the bounds is over the edge + * @param {Bounds} + * + */ + isBoundsIncluded: function (bounds) { + var dockers = this.dockers, size = dockers.length; + return dockers.any(function (docker, i) { + if (i == size - 1) { + return false; + } + var a = docker.bounds.center(); + var b = dockers[i + 1].bounds.center(); + + return ORYX.Core.Math.isRectOverLine(a.x, a.y, b.x, b.y, bounds.a.x, bounds.a.y, bounds.b.x, bounds.b.y); + }); + }, + + /** + * Calculate if the point is inside the Shape + * @param {PointX} + * @param {PointY} + */ + isPointIncluded: function (pointX, pointY) { + + var isbetweenAB = this.absoluteBounds().isIncluded(pointX, pointY, + ORYX.CONFIG.OFFSET_EDGE_BOUNDS); + + var isPointIncluded = undefined; + + if (isbetweenAB && this.dockers.length > 0) { + + var i = 0; + var point1, point2; + + + do { + + point1 = this.dockers[i].bounds.center(); + point2 = this.dockers[++i].bounds.center(); + + isPointIncluded = ORYX.Core.Math.isPointInLine(pointX, pointY, + point1.x, point1.y, + point2.x, point2.y, + ORYX.CONFIG.OFFSET_EDGE_BOUNDS); + + } while (!isPointIncluded && i < this.dockers.length - 1) + + } + + return isPointIncluded; + + }, + + + /** + * Calculate if the point is over an special offset area + * @param {Point} + */ + isPointOverOffset: function () { + return false + }, + + /** + * Returns TRUE if the given node + * is a child node of the shapes node + * @param {Element} node + * @return {Boolean} + * + */ + containsNode: function (node) { + if (this._paths.include(node) || + this._interactionPaths.include(node)) { + return true; + } + return false; + }, + + /** + * Returns the angle of the line between two dockers + * (0 - 359.99999999) + */ + _getAngle: function (docker1, docker2) { + var p1 = docker1 instanceof ORYX.Core.Controls.Docker ? docker1.absoluteCenterXY() : docker1; + var p2 = docker2 instanceof ORYX.Core.Controls.Docker ? docker2.absoluteCenterXY() : docker2; + + return ORYX.Core.Math.getAngle(p1, p2); + }, + + alignDockers: function () { + this._update(true); + + var firstPoint = this.dockers.first().bounds.center(); + var lastPoint = this.dockers.last().bounds.center(); + + var deltaX = lastPoint.x - firstPoint.x; + var deltaY = lastPoint.y - firstPoint.y; + + var numOfDockers = this.dockers.length - 1; + + this.dockers.each((function (docker, index) { + var part = index / numOfDockers; + docker.bounds.unregisterCallback(this._dockerChangedCallback); + docker.bounds.moveTo(firstPoint.x + part * deltaX, firstPoint.y + part * deltaY); + docker.bounds.registerCallback(this._dockerChangedCallback); + }).bind(this)); + + this._dockerChanged(); + }, + + add: function (shape) { + arguments.callee.$.add.apply(this, arguments); + + // If the new shape is a Docker which is not contained + if (shape instanceof ORYX.Core.Controls.Docker && this.dockers.include(shape)) { + // Add it to the dockers list ordered by paths + var pathArray = this._dockersByPath.values()[0]; + if (pathArray) { + pathArray.splice(this.dockers.indexOf(shape), 0, shape); + } + + /* Perform nessary adjustments on the edge's child shapes */ + this.handleChildShapesAfterAddDocker(shape); + } + }, + + /** + * Performs nessary adjustments on the edge's child shapes. + * + * @param {ORYX.Core.Controls.Docker} docker + * The added docker + */ + handleChildShapesAfterAddDocker: function (docker) { + /* Ensure type of Docker */ + if (!docker instanceof ORYX.Core.Controls.Docker) { + return undefined; + } + + var index = this.dockers.indexOf(docker); + if (!(0 < index && index < this.dockers.length - 1)) { + /* Exception: Expect added docker between first and last node of the edge */ + return undefined; + } + + /* Get child nodes concerning the segment of the new docker */ + var startDocker = this.dockers[index - 1]; + var endDocker = this.dockers[index + 1]; + + /* Adjust the position of edge's child nodes */ + var segmentElements = + this.getAttachedNodePositionDataForSegment(startDocker, endDocker); + + var lengthSegmentPart1 = ORYX.Core.Math.getDistancePointToPoint( + startDocker.bounds.center(), + docker.bounds.center()); + var lengthSegmentPart2 = ORYX.Core.Math.getDistancePointToPoint( + endDocker.bounds.center(), + docker.bounds.center()); + + if (!(lengthSegmentPart1 + lengthSegmentPart2)) { + return; + } + + var relativDockerPosition = lengthSegmentPart1 / (lengthSegmentPart1 + lengthSegmentPart2); + + segmentElements.each(function (nodePositionData) { + /* Assign child node to the new segment */ + if (nodePositionData.value.relativDistanceFromDocker1 < relativDockerPosition) { + /* Case: before added Docker */ + nodePositionData.value.segment.docker2 = docker; + nodePositionData.value.relativDistanceFromDocker1 = + nodePositionData.value.relativDistanceFromDocker1 / relativDockerPosition; + } else { + /* Case: after added Docker */ + nodePositionData.value.segment.docker1 = docker; + var newFullDistance = 1 - relativDockerPosition; + var relativPartOfSegment = + nodePositionData.value.relativDistanceFromDocker1 + - relativDockerPosition; + + nodePositionData.value.relativDistanceFromDocker1 = + relativPartOfSegment / newFullDistance; + + } + }) + + + // Update all labels reference points + this.getLabels().each(function (label) { + + var ref = label.getReferencePoint(); + if (!ref) { + return; + } + var index = this.dockers.indexOf(docker); + if (index >= ref.segment.fromIndex && index <= ref.segment.toIndex) { + + var segment = this.findSegment(ref.intersection); + if (!segment) { + // Choose whether the first of the last segment + segment.fromDocker = ref.segment.fromIndex >= (this.dockers.length / 2) ? this.dockers[0] : this.dockers[this.dockers.length - 2]; + segment.toDocker = this.dockers[this.dockers.indexOf(from) + 1]; // The next one if the to docker + } + + var fromPosition = segment.fromDocker.bounds.center(), toPosition = segment.toDocker.bounds.center(); + + var intersection = ORYX.Core.Math.getPointOfIntersectionPointLine( + fromPosition, // P1 - Center of the first docker + toPosition, // P2 - Center of the second docker + ref.intersection, // P3 - Center of the label + true); + //var oldDistance = ORYX.Core.Math.getDistanceBetweenTwoPoints(ref.segment.fromPosition, ref.segment.toPosition, ref.intersection); + //intersection = ORYX.Core.Math.getPointBetweenTwoPoints(fromPosition, toPosition, isNaN(oldDistance) ? 0.5 : (lengthOld*oldDistance)/lengthNew); + + // Update the reference point + this.updateReferencePointOfLabel(label, intersection, segment.fromDocker, segment.toDocker, true); + } + }.bind(this)); + + /* Update attached nodes visual representation */ + this.refreshAttachedNodes(); + }, + + /** + * Returns elements from {@link attachedNodePositiondata} that match the + * segement defined by startDocker and endDocker. + * + * @param {ORYX.Core.Controls.Docker} startDocker + * The docker defining the begin of the segment. + * @param {ORYX.Core.Controls.Docker} endDocker + * The docker defining the begin of the segment. + * + * @return {Hash} attachedNodePositionData + * Child elements matching the segment + */ + getAttachedNodePositionDataForSegment: function (startDocker, endDocker) { + /* Ensure that the segment is defined correctly */ + if (!((startDocker instanceof ORYX.Core.Controls.Docker) + && (endDocker instanceof ORYX.Core.Controls.Docker))) { + return []; + } + + /* Get elements of the segment */ + var elementsOfSegment = + this.attachedNodePositionData.findAll(function (nodePositionData) { + return nodePositionData.value.segment.docker1 === startDocker && + nodePositionData.value.segment.docker2 === endDocker; + }); + + /* Return a Hash in each case */ + if (!elementsOfSegment) { + return []; + } + + return elementsOfSegment; + }, + + /** + * Removes an edge's child shape + */ + remove: function (shape) { + arguments.callee.$.remove.apply(this, arguments); + + if (this.attachedNodePositionData[shape.getId()]) { + delete this.attachedNodePositionData[shape.getId()]; + } + + /* Adjust child shapes if neccessary */ + if (shape instanceof ORYX.Core.Controls.Docker) { + this.handleChildShapesAfterRemoveDocker(shape); + } + }, + + updateReferencePointOfLabel: function (label, intersection, from, to, dirty) { + if (!label.getReferencePoint() || !label.isVisible) { + return; + } + + var ref = label.getReferencePoint(); + + // + if (ref.orientation && ref.orientation !== "ce") { + var angle = this._getAngle(from, to); + if (ref.distance >= 0) { + if (angle == 0) { + label.horizontalAlign("left");//ref.orientation == "lr" ? "right" : "left"); + label.verticalAlign("bottom"); + } else if (angle > 0 && angle < 90) { + label.horizontalAlign("right"); + label.verticalAlign("bottom"); + } else if (angle == 90) { + label.horizontalAlign("right"); + label.verticalAlign("top");//ref.orientation == "lr" ? "bottom" : "top"); + } else if (angle > 90 && angle < 180) { + label.horizontalAlign("right"); + label.verticalAlign("top"); + } else if (angle == 180) { + label.horizontalAlign("left");//ref.orientation == "ur" ? "right" : "left"); + label.verticalAlign("top"); + } else if (angle > 180 && angle < 270) { + label.horizontalAlign("left"); + label.verticalAlign("top"); + } else if (angle == 270) { + label.horizontalAlign("left"); + label.verticalAlign("top");//ref.orientation == "ll" ? "bottom" : "top"); + } else if (angle > 270 && angle <= 360) { + label.horizontalAlign("left"); + label.verticalAlign("bottom"); + } + } else { + if (angle == 0) { + label.horizontalAlign("left");//ref.orientation == "ur" ? "right" : "left"); + label.verticalAlign("top"); + } else if (angle > 0 && angle < 90) { + label.horizontalAlign("left"); + label.verticalAlign("top"); + } else if (angle == 90) { + label.horizontalAlign("left"); + label.verticalAlign("top");//ref.orientation == "ll" ? "bottom" : "top"); + } else if (angle > 90 && angle < 180) { + label.horizontalAlign("left"); + label.verticalAlign("bottom"); + } else if (angle == 180) { + label.horizontalAlign("left");//ref.orientation == "lr" ? "right" : "left"); + label.verticalAlign("bottom"); + } else if (angle > 180 && angle < 270) { + label.horizontalAlign("right"); + label.verticalAlign("bottom"); + } else if (angle == 270) { + label.horizontalAlign("right"); + label.verticalAlign("top");//ref.orientation == "lr" ? "bottom" : "top"); + } else if (angle > 270 && angle <= 360) { + label.horizontalAlign("right"); + label.verticalAlign("top"); + } + } + ref.iorientation = ref.iorientation || ref.orientation; + ref.orientation = (label.verticalAlign() == "top" ? "u" : "l") + (label.horizontalAlign() == "left" ? "l" : "r"); + } + + label.setReferencePoint(jQuery.extend({}, { + intersection: intersection, + segment: { + from: from, + fromIndex: this.dockers.indexOf(from), + fromPosition: from.bounds.center(), + to: to, + toIndex: this.dockers.indexOf(to), + toPosition: to.bounds.center() + }, + dirty: dirty || false + }, ref)) + }, + /** + * Adjusts the child shapes of an edges after a docker was removed. + * + * @param{ORYX.Core.Controls.Docker} docker + * The removed docker. + */ + handleChildShapesAfterRemoveDocker: function (docker) { + /* Ensure docker type */ + if (!(docker instanceof ORYX.Core.Controls.Docker)) { + return; + } + + this.attachedNodePositionData.each(function (nodePositionData) { + if (nodePositionData.value.segment.docker1 === docker) { + /* The new start of the segment is the predecessor of docker2. */ + var index = this.dockers.indexOf(nodePositionData.value.segment.docker2); + if (index == -1) { + return; + } + nodePositionData.value.segment.docker1 = this.dockers[index - 1]; + } else if (nodePositionData.value.segment.docker2 === docker) { + /* The new end of the segment is the successor of docker1. */ + var index = this.dockers.indexOf(nodePositionData.value.segment.docker1); + if (index == -1) { + return; + } + nodePositionData.value.segment.docker2 = this.dockers[index + 1]; + } + }.bind(this)); + + // Update all labels reference points + this.getLabels().each(function (label) { + + var ref = label.getReferencePoint(); + if (!ref) { + return; + } + var from = ref.segment.from; + var to = ref.segment.to; + + if (from !== docker && to !== docker) { + return; + } + + var segment = this.findSegment(ref.intersection); + if (!segment) { + from = segment.fromDocker; + to = segment.toDocker; + } else { + from = from === docker ? this.dockers[this.dockers.indexOf(to) - 1] : from; + to = this.dockers[this.dockers.indexOf(from) + 1]; + } + + var intersection = ORYX.Core.Math.getPointOfIntersectionPointLine(from.bounds.center(), to.bounds.center(), ref.intersection, true); + // Update the reference point + this.updateReferencePointOfLabel(label, intersection, from, to, true); + }.bind(this)); + + /* Update attached nodes visual representation */ + this.refreshAttachedNodes(); + }, + + /** + *@deprecated Use the .createDocker() Method and set the point via the bounds + */ + addDocker: function (position, exDocker) { + var lastDocker; + var result; + this._dockersByPath.any((function (pair) { + return pair.value.any((function (docker, index) { + if (!lastDocker) { + lastDocker = docker; + return false; + } else { + var point1 = lastDocker.bounds.center(); + var point2 = docker.bounds.center(); + + var additionalIEZoom = 1; + if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) { + var ua = navigator.userAgent; + if (ua.indexOf('MSIE') >= 0) { + //IE 10 and below + var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100); + if (zoom !== 100) { + additionalIEZoom = zoom / 100 + } + } + } + + if (additionalIEZoom !== 1) { + position.x = position.x / additionalIEZoom; + position.y = position.y / additionalIEZoom; + } + + if (ORYX.Core.Math.isPointInLine(position.x, position.y, point1.x, point1.y, point2.x, point2.y, 10)) { + var path = this._paths.find(function (path) { + return path.id === pair.key; + }); + if (path) { + var allowAttr = path.getAttributeNS(NAMESPACE_ORYX, 'allowDockers'); + if (allowAttr && allowAttr.toLowerCase() === "no") { + return true; + } + } + + var newDocker = (exDocker) ? exDocker : this.createDocker(this.dockers.indexOf(lastDocker) + 1, position); + newDocker.bounds.centerMoveTo(position); + if (exDocker) + this.add(newDocker, this.dockers.indexOf(lastDocker) + 1); + result = newDocker; + return true; + } else { + lastDocker = docker; + return false; + } + } + }).bind(this)); + }).bind(this)); + return result; + }, + + removeDocker: function (docker) { + if (this.dockers.length > 2 && !(this.dockers.first() === docker)) { + this._dockersByPath.any((function (pair) { + if (pair.value.member(docker)) { + if (docker === pair.value.last()) { + return true; + } else { + this.remove(docker); + this._dockersByPath[pair.key] = pair.value.without(docker); + this.isChanged = true; + this._dockerChanged(); + return true; + } + } + return false; + }).bind(this)); + } + }, + + /** + * Removes all dockers from the edge which are on + * the line between two dockers + * @return {Object} Removed dockers in an indicied array + * (key is the removed position of the docker, value is docker themselve) + */ + removeUnusedDockers: function () { + var marked = $H({}); + + this.dockers.each(function (docker, i) { + if (i == 0 || i == this.dockers.length - 1) { + return + } + var previous = this.dockers[i - 1]; + + /* Do not consider already removed dockers */ + if (marked.values().indexOf(previous) != -1 && this.dockers[i - 2]) { + previous = this.dockers[i - 2]; + } + var next = this.dockers[i + 1]; + + var cp = previous.getDockedShape() && previous.referencePoint ? previous.getAbsoluteReferencePoint() : previous.bounds.center(); + var cn = next.getDockedShape() && next.referencePoint ? next.getAbsoluteReferencePoint() : next.bounds.center(); + var cd = docker.bounds.center(); + + if (ORYX.Core.Math.isPointInLine(cd.x, cd.y, cp.x, cp.y, cn.x, cn.y, 1)) { + marked[i] = docker; + } + }.bind(this)) + + marked.each(function (docker) { + this.removeDocker(docker.value); + }.bind(this)) + + if (marked.values().length > 0) { + this._update(true); + } + + return marked; + }, + + /** + * Initializes the Edge after loading the SVG representation of the edge. * @param {SVGDocument} svgDocument */ - _init: function(svgDocument){ - arguments.callee.$._init.apply(this, arguments); - - var svgNode = svgDocument.getElementsByTagName("g")[0]; //outer most g node - // set all required attributes - var attributeTitle = svgDocument.ownerDocument.createAttribute("title"); - attributeTitle.nodeValue = this.getStencil().title(); - svgNode.setAttributeNode(attributeTitle); - - var attributeId = svgDocument.ownerDocument.createAttribute("id"); - attributeId.nodeValue = this.id; - svgNode.setAttributeNode(attributeId); - - // - var stencilTargetNode = this.node.childNodes[0].childNodes[0]; //" - svgNode = stencilTargetNode.appendChild(svgNode); - - // Add to the EventHandler - this.addEventHandlers(svgNode.parentNode); - - /**set minimum and maximum size*/ - var minSizeAttr = svgNode.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, "minimumSize"); - if (minSizeAttr) { - minSizeAttr = minSizeAttr.replace("/,/g", " "); - var minSizeValues = minSizeAttr.split(" "); - minSizeValues = minSizeValues.without(""); - - if (minSizeValues.length > 1) { - this.minimumSize = { - width: parseFloat(minSizeValues[0]), - height: parseFloat(minSizeValues[1]) - }; + _init: function (svgDocument) { + arguments.callee.$._init.apply(this, arguments); + + var minPointX, minPointY, maxPointX, maxPointY; + + //init markers + var defs = svgDocument.getElementsByTagNameNS(NAMESPACE_SVG, "defs"); + if (defs.length > 0) { + defs = defs[0]; + var markerElements = $A(defs.getElementsByTagNameNS(NAMESPACE_SVG, "marker")); + var marker; + var me = this; + markerElements.each(function (markerElement) { + try { + marker = new ORYX.Core.SVG.SVGMarker(markerElement.cloneNode(true)); + me._markers[marker.id] = marker; + var textElements = $A(marker.element.getElementsByTagNameNS(NAMESPACE_SVG, "text")); + var label; + textElements.each(function (textElement) { + label = new ORYX.Core.SVG.Label({ + textElement: textElement, + shapeId: this.id + }); + me._labels[label.id] = label; + }); + } catch (e) { + } + }); + } + + + var gs = svgDocument.getElementsByTagNameNS(NAMESPACE_SVG, "g"); + if (gs.length <= 0) { + throw "Edge: No g element found."; + } + var g = gs[0]; + + + g.setAttributeNS(null, "id", null); + + var isFirst = true; + + $A(g.childNodes).each((function (path, index) { + if (ORYX.Editor.checkClassType(path, SVGPathElement)) { + path = path.cloneNode(false); + + var pathId = this.id + "_" + index; + path.setAttributeNS(null, "id", pathId); + this._paths.push(path); + + //check, if markers are set and update the id + var markersByThisPath = []; + var markerUrl = path.getAttributeNS(null, "marker-start"); + + if (markerUrl && markerUrl !== "") { + markerUrl = markerUrl.strip(); + markerUrl = markerUrl.replace(/^url\(#/, ''); + + var markerStartId = this.getValidMarkerId(markerUrl); + path.setAttributeNS(null, "marker-start", "url(#" + markerStartId + ")"); + + markersByThisPath.push(this._markers[markerStartId]); + } + + markerUrl = path.getAttributeNS(null, "marker-mid"); + + if (markerUrl && markerUrl !== "") { + markerUrl = markerUrl.strip(); + markerUrl = markerUrl.replace(/^url\(#/, ''); + var markerMidId = this.getValidMarkerId(markerUrl); + path.setAttributeNS(null, "marker-mid", "url(#" + markerMidId + ")"); + + markersByThisPath.push(this._markers[markerMidId]); + } + + markerUrl = path.getAttributeNS(null, "marker-end"); + + if (markerUrl && markerUrl !== "") { + markerUrl = markerUrl.strip(); + + var markerEndId = this.getValidMarkerId(markerUrl); + path.setAttributeNS(null, "marker-end", "url(#" + markerEndId + ")"); + + markersByThisPath.push(this._markers[markerEndId]); + } + + this._markersByPath[pathId] = markersByThisPath; + + //init dockers + var parser = new PathParser(); + var handler = new ORYX.Core.SVG.PointsPathHandler(); + parser.setHandler(handler); + parser.parsePath(path); + + if (handler.points.length < 4) { + throw "Edge: Path has to have two or more points specified."; + } + + this._dockersByPath[pathId] = []; + + for (var i = 0; i < handler.points.length; i += 2) { + //handler.points.each((function(point, pIndex){ + var x = handler.points[i]; + var y = handler.points[i + 1]; + if (isFirst || i > 0) { + var docker = new ORYX.Core.Controls.Docker({ + eventHandlerCallback: this.eventHandlerCallback + }); + docker.bounds.centerMoveTo(x, y); + docker.bounds.registerCallback(this._dockerChangedCallback); + this.add(docker, this.dockers.length); + + //this._dockersByPath[pathId].push(docker); + + //calculate minPoint and maxPoint + if (minPointX) { + minPointX = Math.min(x, minPointX); + minPointY = Math.min(y, minPointY); + } else { + minPointX = x; + minPointY = y; + } + + if (maxPointX) { + maxPointX = Math.max(x, maxPointX); + maxPointY = Math.max(y, maxPointY); + } else { + maxPointX = x; + maxPointY = y; + } + } + //}).bind(this)); + } + isFirst = false; + } + }).bind(this)); + + this.bounds.set(minPointX, minPointY, maxPointX, maxPointY); + + if (false && (this.bounds.width() === 0 || this.bounds.height() === 0)) { + var width = this.bounds.width(); + var height = this.bounds.height(); + + this.bounds.extend({ + x: width === 0 ? 2 : 0, + y: height === 0 ? 2 : 0 + }); + + this.bounds.moveBy({ + x: width === 0 ? -1 : 0, + y: height === 0 ? -1 : 0 + }); + + } + + this._oldBounds = this.bounds.clone(); + + //add paths to this.node + this._paths.reverse(); + var paths = []; + this._paths.each((function (path) { + paths.push(this.node.childNodes[0].childNodes[0].childNodes[0].appendChild(path)); + }).bind(this)); + + this._paths = paths; + + //init interaction path + this._paths.each((function (path) { + var iPath = path.cloneNode(false); + iPath.setAttributeNS(null, "id", undefined); + iPath.setAttributeNS(null, "stroke-width", 10); + iPath.setAttributeNS(null, "visibility", "hidden"); + iPath.setAttributeNS(null, "stroke-dasharray", null); + iPath.setAttributeNS(null, "stroke", "black"); + iPath.setAttributeNS(null, "fill", "none"); + iPath.setAttributeNS(null, "title", this.getStencil().title()); + this._interactionPaths.push(this.node.childNodes[0].childNodes[0].childNodes[0].appendChild(iPath)); + }).bind(this)); + + this._paths.reverse(); + this._interactionPaths.reverse(); + + /**initialize labels*/ + var textElems = svgDocument.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'text'); + + $A(textElems).each((function (textElem) { + var label = new ORYX.Core.SVG.Label({ + textElement: textElem, + shapeId: this.id + }); + this.node.childNodes[0].childNodes[0].appendChild(label.node); + this._labels[label.id] = label; + + label.registerOnChange(this.layout.bind(this)); + }).bind(this)); + + + this.propertiesChanged.each(function (pair) { + pair.value = true; + }); + + + //if(this.dockers.length == 2) { + + + // } + + //this._update(true); + }, + + getValidMarkerId: function (markerUrl) { + if (markerUrl.indexOf("url(\"#") >= 0) { + // Fix for IE9, additional quotes are added to the 0) { + defs = defs[0]; + this._markers.each(function (marker) { + var foundMarker = defs.ownerDocument.getElementById(marker.value.id); + if (foundMarker) { + marker.value.element = defs.removeChild(marker.value.element); + } + }); + } + } + }, + + /** + * Calls when a docker has changed + */ + _dockerChanged: function () { + + //this._update(true); + this._dockerUpdated = true; + + }, + + serialize: function () { + var result = arguments.callee.$.serialize.apply(this); + + //add dockers triple + var value = ""; + this._dockersByPath.each((function (pair) { + pair.value.each(function (docker) { + var position = docker.getDockedShape() && docker.referencePoint ? docker.referencePoint : docker.bounds.center(); + value = value.concat(position.x + " " + position.y + " "); + }); + + value += " # "; + }).bind(this)); + result.push({ + name: 'dockers', + prefix: 'oryx', + value: value, + type: 'literal' + }); + + //add parent triple dependant on the dockedShapes + //TODO change this when canvas becomes a resource + /* var source = this.dockers.first().getDockedShape(); + var target = this.dockers.last().getDockedShape(); + var sharedParent; + if (source && target) { + //get shared parent + while (source.parent) { + source = source.parent; + if (source instanceof ORYX.Core.Canvas) { + sharedParent = source; + break; + } + else { + var targetParent = target.parent; + var found; + while (targetParent) { + if (source === targetParent) { + sharedParent = source; + found = true; + break; + } + else { + targetParent = targetParent.parent; + } + } + if (found) { + break; + } + } + } + } + else + if (source) { + sharedParent = source.parent; + } + else + if (target) { + sharedParent = target.parent; + } +*/ + //if (sharedParent) { + /* result.push({ + name: 'parent', + prefix: 'raziel', + //value: '#' + ERDF.__stripHashes(sharedParent.resourceId), + value: '#' + ERDF.__stripHashes(this.getCanvas().resourceId), + type: 'resource' + });*/ + //} + + //serialize target and source + var lastDocker = this.dockers.last(); + + var target = lastDocker.getDockedShape(); + + if (target) { + result.push({ + name: 'target', + prefix: 'raziel', + value: '#' + ERDF.__stripHashes(target.resourceId), + type: 'resource' + }); + } + + try { + //result = this.getStencil().serialize(this, result); + var serializeEvent = this.getStencil().serialize(); + + /* + * call serialize callback by reference, result should be found + * in serializeEvent.result + */ + if (serializeEvent.type) { + serializeEvent.shape = this; + serializeEvent.data = result; + serializeEvent.result = undefined; + serializeEvent.forceExecution = true; + + this._delegateEvent(serializeEvent); + + if (serializeEvent.result) { + result = serializeEvent.result; + } + } + } catch (e) { + } + return result; + }, + + deserialize: function (data) { + try { + //data = this.getStencil().deserialize(this, data); + + var deserializeEvent = this.getStencil().deserialize(); + + /* + * call serialize callback by reference, result should be found + * in serializeEventInfo.result + */ + if (deserializeEvent.type) { + deserializeEvent.shape = this; + deserializeEvent.data = data; + deserializeEvent.result = undefined; + deserializeEvent.forceExecution = true; + + this._delegateEvent(deserializeEvent); + if (deserializeEvent.result) { + data = deserializeEvent.result; + } + } + } catch (e) { + } + + // Set the outgoing shapes + var target = data.find(function (ser) { + return (ser.prefix + "-" + ser.name) == 'raziel-target' + }); + var targetShape; + if (target) { + targetShape = this.getCanvas().getChildShapeByResourceId(target.value); + } + + var outgoing = data.findAll(function (ser) { + return (ser.prefix + "-" + ser.name) == 'raziel-outgoing' + }); + outgoing.each((function (obj) { + // TODO: Look at Canvas + if (!this.parent) { + return + } + ; + + // Set outgoing Shape + var next = this.getCanvas().getChildShapeByResourceId(obj.value); + + if (next) { + if (next == targetShape) { + // If this is an edge, set the last docker to the next shape + this.dockers.last().setDockedShape(next); + this.dockers.last().setReferencePoint({ + x: next.bounds.width() / 2.0, + y: next.bounds.height() / 2.0 + }); + } else if (next instanceof ORYX.Core.Edge) { + //Set the first docker of the next shape + next.dockers.first().setDockedShape(this); + //next.dockers.first().setReferencePoint({x: this.bounds.width() / 2.0, y: this.bounds.height() / 2.0}); + } /*else if(next.dockers.length > 0) { //next is a node and next has a docker + next.dockers.first().setDockedShape(this); + next.dockers.first().setReferencePoint({x: this.bounds.width() / 2.0, y: this.bounds.height() / 2.0}); + }*/ + } + + }).bind(this)); + + + var oryxDockers = data.find(function (obj) { + return (obj.prefix === "oryx" && + obj.name === "dockers"); + }); + + if (oryxDockers) { + var dataByPath = oryxDockers.value.split("#").without("").without(" "); + + dataByPath.each((function (data, index) { + var values = data.replace(/,/g, " ").split(" ").without(""); + + //for each docker two values must be defined + if (values.length % 2 === 0) { + var path = this._paths[index]; + + if (path) { + if (index === 0) { + while (this._dockersByPath[path.id].length > 2) { + this.removeDocker(this._dockersByPath[path.id][1]); + } + } else { + while (this._dockersByPath[path.id].length > 1) { + this.removeDocker(this._dockersByPath[path.id][0]); + } + } + + var dockersByPath = this._dockersByPath[path.id]; + + if (index === 0) { + //set position of first docker + var x = parseFloat(values.shift()); + var y = parseFloat(values.shift()); + + if (dockersByPath.first().getDockedShape()) { + dockersByPath.first().setReferencePoint({ + x: x, + y: y + }); + } else { + dockersByPath.first().bounds.centerMoveTo(x, y); + } + } + + //set position of last docker + y = parseFloat(values.pop()); + x = parseFloat(values.pop()); + + if (dockersByPath.last().getDockedShape()) { + dockersByPath.last().setReferencePoint({ + x: x, + y: y + }); + } else { + dockersByPath.last().bounds.centerMoveTo(x, y); + } + + //add additional dockers + for (var i = 0; i < values.length; i++) { + x = parseFloat(values[i]); + y = parseFloat(values[++i]); + + var newDocker = this.createDocker(); + newDocker.bounds.centerMoveTo(x, y); + + //this.dockers = this.dockers.without(newDocker); + //this.dockers.splice(this.dockers.indexOf(dockersByPath.last()), 0, newDocker); + //dockersByPath.splice(this.dockers.indexOf(dockersByPath.last()), 0, newDocker); + } + } + } + }).bind(this)); + } else { + this.alignDockers(); + } + + arguments.callee.$.deserialize.apply(this, arguments); + + this._changed(); + }, + + toString: function () { + return this.getStencil().title() + " " + this.id; + }, + + /** + * @return {ORYX.Core.Shape} Returns last docked shape or null. + */ + getTarget: function () { + return this.dockers.last() ? this.dockers.last().getDockedShape() : null; + }, + + /** + * @return {ORYX.Core.Shape} Returns the first docked shape or null + */ + getSource: function () { + return this.dockers.first() ? this.dockers.first().getDockedShape() : null; + }, + + /** + * Checks whether the edge is at least docked to one shape. + * + * @return {boolean} True if edge is docked + */ + isDocked: function () { + var isDocked = false; + this.dockers.each(function (docker) { + if (docker.isDocked()) { + isDocked = true; + throw $break; + } + }); + return isDocked; + }, + + /** + * Calls {@link ORYX.Core.AbstractShape#toJSON} and add a some stencil set information. + */ + toJSON: function () { + var json = arguments.callee.$.toJSON.apply(this, arguments); + + if (this.getTarget()) { + json.target = { + resourceId: this.getTarget().resourceId + }; + } + + return json; + } +}; +ORYX.Core.Edge = ORYX.Core.Shape.extend(ORYX.Core.Edge); +/* + * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +/* + * All code Copyright 2013 KIS Consultancy all rights reserved + */ + +if (!ORYX) { + var ORYX = {} +} +if (!ORYX.Plugins) { + ORYX.Plugins = {} +} + +/** + This abstract plugin class can be used to build plugins on. + It provides some more basic functionality like registering events (on*-handlers)... + @example + ORYX.Plugins.MyPlugin = ORYX.Plugins.AbstractPlugin.extend({ + construct: function() { + // Call super class constructor + arguments.callee.$.construct.apply(this, arguments); + + [...] + }, + [...] + }); + + @class ORYX.Plugins.AbstractPlugin + @constructor Creates a new instance + @author Willi Tscheschner + */ +ORYX.Plugins.AbstractPlugin = Clazz.extend({ + /** + * The facade which offer editor-specific functionality + * @type Facade + * @memberOf ORYX.Plugins.AbstractPlugin.prototype + */ + facade: null, + + construct: function (facade) { + this.facade = facade; + + this.facade.registerOnEvent(ORYX.CONFIG.EVENT_LOADED, this.onLoaded.bind(this)); + }, + + /** + Overwrite to handle load event. TODO: Document params!!! + @methodOf ORYX.Plugins.AbstractPlugin.prototype + */ + onLoaded: function () { + }, + + /** + Overwrite to handle selection changed event. TODO: Document params!!! + @methodOf ORYX.Plugins.AbstractPlugin.prototype + */ + onSelectionChanged: function () { + }, + + /** + Show overlay on given shape. + @methodOf ORYX.Plugins.AbstractPlugin.prototype + @example + showOverlay( + myShape, + { stroke: "green" }, + ORYX.Editor.graft("http://www.w3.org/2000/svg", null, ['path', { + "title": "Click the element to execute it!", + "stroke-width": 2.0, + "stroke": "black", + "d": "M0,-5 L5,0 L0,5 Z", + "line-captions": "round" + }]) + ) + @param {Oryx.XXX.Shape[]} shapes One shape or array of shapes the overlay should be put on + @param {Oryx.XXX.Attributes} attributes some attributes... + @param {Oryx.svg.node} svgNode The svg node which should be used as overlay + @param {String} [svgNode="NW"] The svg node position where the overlay should be placed + */ + showOverlay: function (shapes, attributes, svgNode, svgNodePosition) { + + if (!(shapes instanceof Array)) { + shapes = [shapes] + } + + // Define Shapes + shapes = shapes.map(function (shape) { + var el = shape; + if (typeof shape == "string") { + el = this.facade.getCanvas().getChildShapeByResourceId(shape); + el = el || this.facade.getCanvas().getChildById(shape, true); + } + return el; + }.bind(this)).compact(); + + // Define unified id + if (!this.overlayID) { + this.overlayID = this.type + ORYX.Editor.provideId(); + } + + this.facade.raiseEvent({ + type: ORYX.CONFIG.EVENT_OVERLAY_SHOW, + id: this.overlayID, + shapes: shapes, + attributes: attributes, + node: svgNode, + nodePosition: svgNodePosition || "NW" + }); + + }, + + /** + Hide current overlay. + @methodOf ORYX.Plugins.AbstractPlugin.prototype + */ + hideOverlay: function () { + this.facade.raiseEvent({ + type: ORYX.CONFIG.EVENT_OVERLAY_HIDE, + id: this.overlayID + }); + }, + + /** + Does a transformation with the given xslt stylesheet. + @methodOf ORYX.Plugins.AbstractPlugin.prototype + @param {String} data The data (e.g. eRDF) which should be transformed + @param {String} stylesheet URL of a stylesheet which should be used for transforming data. + */ + doTransform: function (data, stylesheet) { + + if (!stylesheet || !data) { + return "" + } + + var parser = new DOMParser(); + var parsedData = parser.parseFromString(data, "text/xml"); + source = stylesheet; + new Ajax.Request(source, { + asynchronous: false, + method: 'get', + onSuccess: function (transport) { + xsl = transport.responseText + }.bind(this), + onFailure: (function (transport) { + ORYX.Log.error("XSL load failed" + transport); + }).bind(this) + }); + var xsltProcessor = new XSLTProcessor(); + var domParser = new DOMParser(); + var xslObject = domParser.parseFromString(xsl, "text/xml"); + xsltProcessor.importStylesheet(xslObject); + + try { + + var newData = xsltProcessor.transformToFragment(parsedData, document); + var serializedData = (new XMLSerializer()).serializeToString(newData); + + /* Firefox 2 to 3 problem?! */ + serializedData = !serializedData.startsWith("" + serializedData : serializedData; + + return serializedData; + + } catch (error) { + return -1; + } + + }, + + /** + * Opens a new window that shows the given XML content. + * @methodOf ORYX.Plugins.AbstractPlugin.prototype + * @param {Object} content The XML content to be shown. + * @example + * openDownloadWindow( "my.xml", "" ); + */ + openXMLWindow: function (content) { + var win = window.open( + 'data:application/xml,' + encodeURIComponent( + content + ), + '_blank', "resizable=yes,width=600,height=600,toolbar=0,scrollbars=yes" + ); + }, + + /** + * Opens a download window for downloading the given content. + * @methodOf ORYX.Plugins.AbstractPlugin.prototype + * @param {String} filename The content's file name + * @param {String} content The content to download + */ + openDownloadWindow: function (filename, content) { + var win = window.open(""); + if (win != null) { + win.document.open(); + win.document.write(""); + var submitForm = win.document.createElement("form"); + win.document.body.appendChild(submitForm); + + var createHiddenElement = function (name, value) { + var newElement = document.createElement("input"); + newElement.name = name; + newElement.type = "hidden"; + newElement.value = value; + return newElement + } + + submitForm.appendChild(createHiddenElement("download", content)); + submitForm.appendChild(createHiddenElement("file", filename)); + + + submitForm.method = "POST"; + win.document.write(""); + win.document.close(); + submitForm.action = ORYX.PATH + "/download"; + submitForm.submit(); + } + }, + + /** + * Serializes DOM. + * @methodOf ORYX.Plugins.AbstractPlugin.prototype + * @type {String} Serialized DOM + */ + getSerializedDOM: function () { + // Force to set all resource IDs + var serializedDOM = DataManager.serializeDOM(this.facade); + + //add namespaces + serializedDOM = '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + '' + + serializedDOM + + ''; + + return serializedDOM; + }, + + /** + * Sets the editor in read only mode: Edges/ dockers cannot be moved anymore, + * shapes cannot be selected anymore. + * @methodOf ORYX.Plugins.AbstractPlugin.prototype + */ + enableReadOnlyMode: function () { + //Edges cannot be moved anymore + this.facade.disableEvent(ORYX.CONFIG.EVENT_MOUSEDOWN); + + // Stop the user from editing the diagram while the plugin is active + this._stopSelectionChange = function () { + if (this.facade.getSelection().length > 0) { + this.facade.setSelection([]); + } + }; + this.facade.registerOnEvent(ORYX.CONFIG.EVENT_SELECTION_CHANGED, this._stopSelectionChange.bind(this)); + }, + /** + * Disables read only mode, see @see + * @methodOf ORYX.Plugins.AbstractPlugin.prototype + * @see ORYX.Plugins.AbstractPlugin.prototype.enableReadOnlyMode + */ + disableReadOnlyMode: function () { + // Edges can be moved now again + 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; + } + }, + + /** + * Extracts RDF from DOM. + * @methodOf ORYX.Plugins.AbstractPlugin.prototype + * @type {String} Extracted RFD. Null if there are transformation errors. + */ + getRDFFromDOM: function () { + //convert to RDF + try { + var xsl = ""; + source = ORYX.PATH + "lib/extract-rdf.xsl"; + new Ajax.Request(source, { + asynchronous: false, + method: 'get', + onSuccess: function (transport) { + xsl = transport.responseText + }.bind(this), + onFailure: (function (transport) { + ORYX.Log.error("XSL load failed" + transport); + }).bind(this) + }); + + var domParser = new DOMParser(); + var xmlObject = domParser.parseFromString(this.getSerializedDOM(), "text/xml"); + var xslObject = domParser.parseFromString(xsl, "text/xml"); + var xsltProcessor = new XSLTProcessor(); + xsltProcessor.importStylesheet(xslObject); + var result = xsltProcessor.transformToFragment(xmlObject, document); + + var serializer = new XMLSerializer(); + + return serializer.serializeToString(result); + } catch (e) { + console.log("error serializing " + e); + return ""; + } + + + }, + + /** + * Checks if a certain stencil set is loaded right now. + * + */ + isStencilSetExtensionLoaded: function (stencilSetExtensionNamespace) { + return this.facade.getStencilSets().values().any( + function (ss) { + return ss.extensions().keys().any( + function (extensionKey) { + return extensionKey == stencilSetExtensionNamespace; + }.bind(this) + ); + }.bind(this) + ); + }, + + /** + * Raises an event so that registered layouters does + * have the posiblility to layout the given shapes + * For further reading, have a look into the AbstractLayouter + * class + * @param {Object} shapes + */ + doLayout: function (shapes) { + // Raises a do layout event + if (this.facade.raiseEvent) { + this.facade.raiseEvent({ + type: ORYX.CONFIG.EVENT_LAYOUT, + shapes: shapes + }); + } else { + this.facade.handleEvents({ + type: ORYX.CONFIG.EVENT_LAYOUT, + shapes: shapes + }); + } + }, + + + /** + * Does a primitive layouting with the incoming/outgoing + * edges (set the dockers to the right position) and if + * necessary, it will be called the real layouting + * @param {ORYX.Core.Node} node + * @param {Array} edges + */ + layoutEdges: function (node, allEdges, offset) { + + if (!this.facade.isExecutingCommands()) { + return + } + + var Command = ORYX.Core.Command.extend({ + construct: function (edges, node, offset, plugin) { + this.edges = edges; + this.node = node; + this.plugin = plugin; + this.offset = offset; + + // Get the new absolute center + var center = node.absoluteXY(); + this.ulo = {x: center.x - offset.x, y: center.y - offset.y}; + + + }, + execute: function () { + + if (this.changes) { + this.executeAgain(); + return; + } else { + this.changes = []; + this.edges.each(function (edge) { + this.changes.push({ + edge: edge, + oldDockerPositions: edge.dockers.map(function (r) { + return r.bounds.center() + }) + }) + }.bind(this)); + } + + // Find all edges, which are related to the node and + // have more than two dockers + this.edges + // Find all edges with more than two dockers + .findAll(function (r) { + return r.dockers.length > 2 + }.bind(this)) + // For every edge, check second and one before last docker + // if there are horizontal/vertical on the same level + // and if so, align the the bounds + .each(function (edge) { + if (edge.dockers.first().getDockedShape() === this.node) { + var second = edge.dockers[1]; + if (this.align(second.bounds, edge.dockers.first())) { + second.update(); + } + } else if (edge.dockers.last().getDockedShape() === this.node) { + var beforeLast = edge.dockers[edge.dockers.length - 2]; + if (this.align(beforeLast.bounds, edge.dockers.last())) { + beforeLast.update(); + } + } + edge._update(true); + edge.removeUnusedDockers(); + if (this.isBendPointIncluded(edge)) { + this.plugin.doLayout(edge); + return; + } + }.bind(this)); + + + // Find all edges, which have only to dockers + // and is located horizontal/vertical. + // Do layout with those edges + this.edges + // Find all edges with exactly two dockers + .each(function (edge) { + if (edge.dockers.length == 2) { + var p1 = edge.dockers.first().getAbsoluteReferencePoint() || edge.dockers.first().bounds.center(); + var p2 = edge.dockers.last().getAbsoluteReferencePoint() || edge.dockers.first().bounds.center(); + // Find all horizontal/vertical edges + if (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) { + this.plugin.doLayout(edge); + } + } + }.bind(this)); + + this.edges.each(function (edge, i) { + this.changes[i].dockerPositions = edge.dockers.map(function (r) { + return r.bounds.center() + }); + }.bind(this)); + + }, + /** + * Align the bounds if the center is + * the same than the old center + * @params {Object} bounds + * @params {Object} bounds2 + */ + align: function (bounds, refDocker) { + + var abRef = refDocker.getAbsoluteReferencePoint() || refDocker.bounds.center(); + + var xdif = bounds.center().x - abRef.x; + var ydif = bounds.center().y - abRef.y; + if (Math.abs(-Math.abs(xdif) + Math.abs(this.offset.x)) < 3 && this.offset.xs === undefined) { + bounds.moveBy({x: -xdif, y: 0}) + } + if (Math.abs(-Math.abs(ydif) + Math.abs(this.offset.y)) < 3 && this.offset.ys === undefined) { + bounds.moveBy({y: -ydif, x: 0}) + } + + if (this.offset.xs !== undefined || this.offset.ys !== undefined) { + var absPXY = refDocker.getDockedShape().absoluteXY(); + xdif = bounds.center().x - (absPXY.x + ((abRef.x - absPXY.x) / this.offset.xs)); + ydif = bounds.center().y - (absPXY.y + ((abRef.y - absPXY.y) / this.offset.ys)); + + if (Math.abs(-Math.abs(xdif) + Math.abs(this.offset.x)) < 3) { + bounds.moveBy({x: -(bounds.center().x - abRef.x), y: 0}) + } + + if (Math.abs(-Math.abs(ydif) + Math.abs(this.offset.y)) < 3) { + bounds.moveBy({y: -(bounds.center().y - abRef.y), x: 0}) + } + } + }, + + /** + * Returns a TRUE if there are bend point which overlay the shape + */ + isBendPointIncluded: function (edge) { + // Get absolute bounds + var ab = edge.dockers.first().getDockedShape(); + var bb = edge.dockers.last().getDockedShape(); + + if (ab) { + ab = ab.absoluteBounds(); + ab.widen(5); + } + + if (bb) { + bb = bb.absoluteBounds(); + bb.widen(20); // Wide with 20 because of the arrow from the edge + } + + return edge.dockers + .any(function (docker, i) { + var c = docker.bounds.center(); + // Dont count first and last + return i != 0 && i != edge.dockers.length - 1 && + // Check if the point is included to the absolute bounds + ((ab && ab.isIncluded(c)) || (bb && bb.isIncluded(c))) + }) + }, + + removeAllDocker: function (edge) { + edge.dockers.slice(1, edge.dockers.length - 1).each(function (docker) { + edge.removeDocker(docker); + }) + }, + executeAgain: function () { + this.changes.each(function (change) { + // Reset the dockers + this.removeAllDocker(change.edge); + change.dockerPositions.each(function (pos, i) { + if (i == 0 || i == change.dockerPositions.length - 1) { + return + } + var docker = change.edge.createDocker(undefined, pos); + docker.bounds.centerMoveTo(pos); + docker.update(); + }.bind(this)); + change.edge._update(true); + }.bind(this)); + }, + rollback: function () { + this.changes.each(function (change) { + // Reset the dockers + this.removeAllDocker(change.edge); + change.oldDockerPositions.each(function (pos, i) { + if (i == 0 || i == change.oldDockerPositions.length - 1) { + return + } + var docker = change.edge.createDocker(undefined, pos); + docker.bounds.centerMoveTo(pos); + docker.update(); + }.bind(this)); + change.edge._update(true); + }.bind(this)); + } + }); + + this.facade.executeCommands([new Command(allEdges, node, offset, this)]); + + } +});/* + * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +/* + * All code Copyright 2013 KIS Consultancy all rights reserved + */ + +if (!ORYX) { + var ORYX = {} +} +if (!ORYX.Plugins) { + ORYX.Plugins = {} +} + +/** + This abstract plugin implements the core behaviour of layout + + @class ORYX.Plugins.AbstractLayouter + @constructor Creates a new instance + @author Willi Tscheschner + */ +ORYX.Plugins.AbstractLayouter = ORYX.Plugins.AbstractPlugin.extend({ + + /** + * 'layouted' defined all types of shapes which will be layouted. + * It can be one value or an array of values. The value + * can be a Stencil ID (as String) or an class type of either + * a ORYX.Core.Node or ORYX.Core.Edge + * @type Array|String|Object + * @memberOf ORYX.Plugins.AbstractLayouter.prototype + */ + layouted: [], + + /** + * Constructor + * @param {Object} facade + * @memberOf ORYX.Plugins.AbstractLayouter.prototype + */ + construct: function (facade) { + arguments.callee.$.construct.apply(this, arguments); + + this.facade.registerOnEvent(ORYX.CONFIG.EVENT_LAYOUT, this._initLayout.bind(this)); + }, + + /** + * Proofs if this shape should be layouted or not + * @param {Object} shape + * @memberOf ORYX.Plugins.AbstractLayouter.prototype + */ + isIncludedInLayout: function (shape) { + if (!(this.layouted instanceof Array)) { + this.layouted = [this.layouted].compact(); + } + + // If there are no elements + if (this.layouted.length <= 0) { + // Return TRUE + return true; + } + + // Return TRUE if there is any correlation between + // the 'layouted' attribute and the shape themselve. + return this.layouted.any(function (s) { + if (typeof s == "string") { + return shape.getStencil().id().include(s); + } else { + return shape instanceof s; + } + }) + }, + + /** + * Callback to start the layouting + * @param {Object} event Layout event + * @param {Object} shapes Given shapes + * @memberOf ORYX.Plugins.AbstractLayouter.prototype + */ + _initLayout: function (event) { + + // Get the shapes + var shapes = [event.shapes].flatten().compact(); + + // Find all shapes which should be layouted + var toLayout = shapes.findAll(function (shape) { + return this.isIncludedInLayout(shape) + }.bind(this)) + + // If there are shapes left + if (toLayout.length > 0) { + // Do layout + this.layout(toLayout); + } + }, + + /** + * Implementation of layouting a set on shapes + * @param {Object} shapes Given shapes + * @memberOf ORYX.Plugins.AbstractLayouter.prototype + */ + layout: function (shapes) { + throw new Error("Layouter has to implement the layout function.") + } +});/* + * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +/* + * All code Copyright 2013 KIS Consultancy all rights reserved + */ + +if (!ORYX.Plugins) + ORYX.Plugins = new Object(); + +ORYX.Plugins.Edit = Clazz.extend({ + + construct: function (facade) { + + this.facade = facade; + this.clipboard = new ORYX.Plugins.Edit.ClipBoard(); + + //this.facade.registerOnEvent(ORYX.CONFIG.EVENT_KEYDOWN, this.keyHandler.bind(this)); + + 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 (fn, args) { + window.setTimeout(function () { + fn.apply(this, (args instanceof Array ? args : [])); + }.bind(this), 1); + }, + + /** + * Handles the mouse down event and starts the copy-move-paste action, if + * control or meta key is pressed. + */ + handleMouseDown: function (event) { + if (this._controlPressed) { + this._controlPressed = false; + this.editCopy(); +// console.log("copiedEle: %0",this.clipboard.shapesAsJson) +// console.log("mousevent: %o",event) + this.editPaste(); + event.forceExecution = true; + this.facade.raiseEvent(event, this.clipboard.shapesAsJson); + + } + }, + + /** + * The key handler for this plugin. Every action from the set of cut, copy, + * paste and delete should be accessible trough simple keyboard shortcuts. + * This method checks whether any event triggers one of those actions. + * + * @param {Object} event The keyboard event that should be analysed for + * triggering of this plugin. + */ +// keyHandler: function(event){ +// //TODO document what event.which is. +// +// ORYX.Log.debug("edit.js handles a keyEvent."); +// +// // assure we have the current event. +// if (!event) +// event = window.event; +// +// +// // get the currently pressed key and state of control key. +// var pressedKey = event.which || event.keyCode; +// var ctrlPressed = event.ctrlKey; +// +// // if the object is to be deleted, do so, and return immediately. +// if ((pressedKey == ORYX.CONFIG.KEY_CODE_DELETE) || +// ((pressedKey == ORYX.CONFIG.KEY_CODE_BACKSPACE) && +// (event.metaKey || event.appleMetaKey))) { +// +// ORYX.Log.debug("edit.js deletes the shape."); +// this.editDelete(); +// return; +// } +// +// // if control key is not pressed, we're not interested anymore. +// if (!ctrlPressed) +// return; +// +// // when ctrl is pressed, switch trough the possibilities. +// switch (pressedKey) { +// +// // cut. +// case ORYX.CONFIG.KEY_CODE_X: +// this.editCut(); +// break; +// +// // copy. +// case ORYX.CONFIG.KEY_CODE_C: +// this.editCopy(); +// break; +// +// // paste. +// case ORYX.CONFIG.KEY_CODE_V: +// this.editPaste(); +// break; +// } +// }, + + /** + * Returns a list of shapes which should be considered while copying. + * Besides the shapes of given ones, edges and attached nodes are added to the result set. + * If one of the given shape is a child of another given shape, it is not put into the result. + */ + getAllShapesToConsider: function (shapes) { + var shapesToConsider = []; // only top-level shapes + var childShapesToConsider = []; // all child shapes of top-level shapes + + shapes.each(function (shape) { + //Throw away these shapes which have a parent in given shapes + isChildShapeOfAnother = shapes.any(function (s2) { + return s2.hasChildShape(shape); + }); + if (isChildShapeOfAnother) return; + + // This shape should be considered + shapesToConsider.push(shape); + // Consider attached nodes (e.g. intermediate events) + if (shape instanceof ORYX.Core.Node) { + var attached = shape.getOutgoingNodes(); + attached = attached.findAll(function (a) { + return !shapes.include(a) + }); + shapesToConsider = shapesToConsider.concat(attached); + } + + childShapesToConsider = childShapesToConsider.concat(shape.getChildShapes(true)); + }.bind(this)); + + // All edges between considered child shapes should be considered + // Look for these edges having incoming and outgoing in childShapesToConsider + var edgesToConsider = this.facade.getCanvas().getChildEdges().select(function (edge) { + // Ignore if already added + if (shapesToConsider.include(edge)) return false; + // Ignore if there are no docked shapes + if (edge.getAllDockedShapes().size() === 0) return false; + // True if all docked shapes are in considered child shapes + return edge.getAllDockedShapes().all(function (shape) { + // Remember: Edges can have other edges on outgoing, that is why edges must not be included in childShapesToConsider + return shape instanceof ORYX.Core.Edge || childShapesToConsider.include(shape); + }); + }); + shapesToConsider = shapesToConsider.concat(edgesToConsider); + + return shapesToConsider; + }, + + /** + * Performs the cut operation by first copy-ing and then deleting the + * current selection. + */ + editCut: function () { + //TODO document why this returns false. + //TODO document what the magic boolean parameters are supposed to do. + + this.editCopy(false, true); + this.editDelete(true); + return false; + }, + + /** + * Performs the copy operation. + * @param {Object} will_not_update ?? + */ + editCopy: function (will_update, useNoOffset) { + var selection = this.facade.getSelection(); + + //if the selection is empty, do not remove the previously copied elements + if (selection.length == 0) return; + + this.clipboard.refresh(selection, this.getAllShapesToConsider(selection), this.facade.getCanvas().getStencil().stencilSet().namespace(), useNoOffset); + + if (will_update) this.facade.updateSelection(); + }, + + /** + * Performs the paste operation. + */ + editPaste: function () { + // Create a new canvas with childShapes + //and stencilset namespace to be JSON Import conform + var canvas = { + childShapes: this.clipboard.shapesAsJson, + stencilset: { + namespace: this.clipboard.SSnamespace + } + }; + // Apply json helper to iterate over json object + jQuery.extend(canvas, ORYX.Core.AbstractShape.JSONHelper); + + var childShapeResourceIds = canvas.getChildShapes(true).pluck("resourceId"); + var outgoings = {}; + // Iterate over all shapes + canvas.eachChild(function (shape, parent) { + // Throw away these references where referenced shape isn't copied + shape.outgoing = shape.outgoing.select(function (out) { + return childShapeResourceIds.include(out.resourceId); + }); + shape.outgoing.each(function (out) { + if (!outgoings[out.resourceId]) { + outgoings[out.resourceId] = []; + } + outgoings[out.resourceId].push(shape); + }); + + return shape; + }.bind(this), true, true); + + + // Iterate over all shapes + canvas.eachChild(function (shape, parent) { + + // Check if there has a valid target + if (shape.target && !(childShapeResourceIds.include(shape.target.resourceId))) { + shape.target = undefined; + shape.targetRemoved = true; + } + + // Check if the first docker is removed + if (shape.dockers && + shape.dockers.length >= 1 && + shape.dockers[0].getDocker && + ((shape.dockers[0].getDocker().getDockedShape() && + !childShapeResourceIds.include(shape.dockers[0].getDocker().getDockedShape().resourceId)) || + !shape.getShape().dockers[0].getDockedShape() && !outgoings[shape.resourceId])) { + + shape.sourceRemoved = true; + } + + return shape; + }.bind(this), true, true); + + + // Iterate over top-level shapes + canvas.eachChild(function (shape, parent) { + // All top-level shapes should get an offset in their bounds + // Move the shape occording to COPY_MOVE_OFFSET + if (this.clipboard.useOffset) { + shape.bounds = { + lowerRight: { + x: shape.bounds.lowerRight.x + ORYX.CONFIG.COPY_MOVE_OFFSET, + y: shape.bounds.lowerRight.y + ORYX.CONFIG.COPY_MOVE_OFFSET + }, + upperLeft: { + x: shape.bounds.upperLeft.x + ORYX.CONFIG.COPY_MOVE_OFFSET, + y: shape.bounds.upperLeft.y + ORYX.CONFIG.COPY_MOVE_OFFSET + } + }; + } + // Only apply offset to shapes with a target + if (shape.dockers) { + shape.dockers = shape.dockers.map(function (docker, i) { + // If shape had a target but the copied does not have anyone anymore, + // migrate the relative dockers to absolute ones. + if ((shape.targetRemoved === true && i == shape.dockers.length - 1 && docker.getDocker) || + (shape.sourceRemoved === true && i == 0 && docker.getDocker)) { + + docker = docker.getDocker().bounds.center(); + } + + // If it is the first docker and it has a docked shape, + // just return the coordinates + if ((i == 0 && docker.getDocker instanceof Function && + shape.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)))) || + (i == shape.dockers.length - 1 && docker.getDocker instanceof Function && + shape.targetRemoved !== true && (docker.getDocker().getDockedShape() || shape.target))) { + + return { + x: docker.x, + y: docker.y, + getDocker: docker.getDocker + } + } else if (this.clipboard.useOffset) { + return { + x: docker.x + ORYX.CONFIG.COPY_MOVE_OFFSET, + y: docker.y + ORYX.CONFIG.COPY_MOVE_OFFSET, + getDocker: docker.getDocker + }; + } else { + return { + x: docker.x, + y: docker.y, + getDocker: docker.getDocker + }; + } + }.bind(this)); + + } 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]))) { + + shape.dockers = shape.dockers.map(function (docker, i) { + + if ((shape.sourceRemoved === true && i == 0 && docker.getDocker)) { + docker = docker.getDocker().bounds.center(); + } + + if (this.clipboard.useOffset) { + return { + x: docker.x + ORYX.CONFIG.COPY_MOVE_OFFSET, + y: docker.y + ORYX.CONFIG.COPY_MOVE_OFFSET, + getDocker: docker.getDocker + }; + } else { + return { + x: docker.x, + y: docker.y, + getDocker: docker.getDocker + }; + } + }.bind(this)); + } + + return shape; + }.bind(this), false, true); + + this.clipboard.useOffset = true; + this.facade.importJSON(canvas); + }, + + /** + * Performs the delete operation. No more asking. + */ + editDelete: function () { + var selection = this.facade.getSelection(); + + var clipboard = new ORYX.Plugins.Edit.ClipBoard(); + clipboard.refresh(selection, this.getAllShapesToConsider(selection)); + + var command = new ORYX.Plugins.Edit.DeleteCommand(clipboard, this.facade); + + this.facade.executeCommands([command]); + } +}); + +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 (selection, shapes, namespace, useNoOffset) { + this.selection = selection; + this.SSnamespace = namespace; + // Store outgoings, targets and parents to restore them later on + this.outgoings = {}; + this.parents = {}; + this.targets = {}; + this.useOffset = useNoOffset !== true; + + this.shapesAsJson = shapes.map(function (shape) { + var s = shape.toJSON(); + s.parent = {resourceId: shape.getParentShape().resourceId}; + s.parentIndex = shape.getParentShape().getChildShapes().indexOf(shape) + return s; + }); + } +}); + +ORYX.Plugins.Edit.DeleteCommand = ORYX.Core.Command.extend({ + construct: function (clipboard, facade) { + this.clipboard = clipboard; + this.shapesAsJson = clipboard.shapesAsJson; + this.facade = facade; + + // Store dockers of deleted shapes to restore connections + this.dockers = this.shapesAsJson.map(function (shapeAsJson) { + var shape = shapeAsJson.getShape(); + var incomingDockers = shape.getIncomingShapes().map(function (s) { + return s.getDockers().last(); + }); + var outgoingDockers = shape.getOutgoingShapes().map(function (s) { + return s.getDockers().first(); + }); + var dockers = shape.getDockers().concat(incomingDockers, outgoingDockers).compact().map(function (docker) { + return { + object: docker, + referencePoint: docker.referencePoint, + dockedShape: docker.getDockedShape() + }; + }); + return dockers; + }).flatten(); + }, + execute: function () { + this.shapesAsJson.each(function (shapeAsJson) { + // Delete shape + this.facade.deleteShape(shapeAsJson.getShape()); + }.bind(this)); + + this.facade.setSelection([]); + this.facade.getCanvas().update(); + this.facade.updateSelection(); + + }, + rollback: function () { + this.shapesAsJson.each(function (shapeAsJson) { + var shape = shapeAsJson.getShape(); + var parent = this.facade.getCanvas().getChildShapeByResourceId(shapeAsJson.parent.resourceId) || this.facade.getCanvas(); + parent.add(shape, shape.parentIndex); + }.bind(this)); + + //reconnect shapes + this.dockers.each(function (d) { + d.object.setDockedShape(d.dockedShape); + d.object.setReferencePoint(d.referencePoint); + }.bind(this)); + + this.facade.setSelection(this.selectedShapes); + this.facade.getCanvas().update(); + this.facade.updateSelection(); + + } +});/* + * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +/* + * All code Copyright 2013 KIS Consultancy all rights reserved + */ + +/** + * @namespace Oryx name space for plugins + * @name ORYX.Plugins + */ +if (!ORYX.Plugins) + ORYX.Plugins = new Object(); + +/** + * The view plugin offers all of zooming functionality accessible over the + * tool bar. This are zoom in, zoom out, zoom to standard, zoom fit to model. + * + * @class ORYX.Plugins.View + * @extends Clazz + * @param {Object} facade The editor facade for plugins. + */ +ORYX.Plugins.View = { + /** @lends ORYX.Plugins.View.prototype */ + facade: undefined, + + construct: function (facade, ownPluginData) { + this.facade = facade; + //Standard Values + this.zoomLevel = 1.0; + this.maxFitToScreenLevel = 1.5; + this.minZoomLevel = 0.1; + this.maxZoomLevel = 2.5; + this.diff = 5; //difference between canvas and view port, s.th. like toolbar?? + + //Read properties + if (ownPluginData !== undefined && ownPluginData !== null) { + ownPluginData.properties.each(function (property) { + if (property.zoomLevel) { + this.zoomLevel = Number(1.0); + } + if (property.maxFitToScreenLevel) { + this.maxFitToScreenLevel = Number(property.maxFitToScreenLevel); + } + if (property.minZoomLevel) { + this.minZoomLevel = Number(property.minZoomLevel); + } + if (property.maxZoomLevel) { + this.maxZoomLevel = Number(property.maxZoomLevel); + } + }.bind(this)); + } + + + /* Register zoom in */ + this.facade.offer({ + 'name': ORYX.I18N.View.zoomIn, + 'functionality': this.zoom.bind(this, [1.0 + 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) + }); + + /* Register zoom out */ + this.facade.offer({ + 'name': ORYX.I18N.View.zoomOut, + 'functionality': this.zoom.bind(this, [1.0 - 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) + }); + + /* Register zoom standard */ + 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) + }); + + /* Register zoom fit to model */ + 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 + }); + }, + + /** + * It sets the zoom level to a fix value and call the zooming function. + * + * @param {Number} zoomLevel + * the zoom level + */ + setAFixZoomLevel: function (zoomLevel) { + this.zoomLevel = zoomLevel; + this._checkZoomLevelRange(); + this.zoom(1); + }, + + /** + * It does the actual zooming. It changes the viewable size of the canvas + * and all to its child elements. + * + * @param {Number} factor + * the factor to adjust the zoom level + */ + zoom: function (factor) { + // TODO: Zoomen auf allen Objekten im SVG-DOM + + this.zoomLevel *= factor; + var scrollNode = this.facade.getCanvas().getHTMLContainer().parentNode.parentNode; + var canvas = this.facade.getCanvas(); + var newWidth = canvas.bounds.width() * this.zoomLevel; + var newHeight = canvas.bounds.height() * this.zoomLevel; + + /* Set new top offset */ + var offsetTop = (canvas.node.parentNode.parentNode.parentNode.offsetHeight - newHeight) / 2.0; + offsetTop = offsetTop > 20 ? offsetTop - 20 : 0; + canvas.node.parentNode.parentNode.style.marginTop = offsetTop + "px"; + offsetTop += 5; + canvas.getHTMLContainer().style.top = offsetTop + "px"; + + /*readjust scrollbar*/ + var newScrollTop = scrollNode.scrollTop - Math.round((canvas.getHTMLContainer().parentNode.getHeight() - newHeight) / 2) + this.diff; + var newScrollLeft = scrollNode.scrollLeft - Math.round((canvas.getHTMLContainer().parentNode.getWidth() - newWidth) / 2) + this.diff; + + /* Set new Zoom-Level */ + canvas.setSize({width: newWidth, height: newHeight}, true); + + /* Set Scale-Factor */ + canvas.node.setAttributeNS(null, "transform", "scale(" + this.zoomLevel + ")"); + + /* Refresh the Selection */ + this.facade.updateSelection(); + scrollNode.scrollTop = newScrollTop; + scrollNode.scrollLeft = newScrollLeft; + + /* Update the zoom-level*/ + canvas.zoomLevel = this.zoomLevel; + }, + + + /** + * It calculates the zoom level to fit whole model into the visible area + * of the canvas. Than the model gets zoomed and the position of the + * scroll bars are adjusted. + * + */ + zoomFitToModel: function () { + + /* Get the size of the visible area of the canvas */ + var scrollNode = this.facade.getCanvas().getHTMLContainer().parentNode.parentNode; + var visibleHeight = scrollNode.getHeight() - 30; + var visibleWidth = scrollNode.getWidth() - 30; + + var nodes = this.facade.getCanvas().getChildShapes(); + + if (!nodes || nodes.length < 1) { + return false; + } + + /* Calculate size of canvas to fit the model */ + var bounds = nodes[0].absoluteBounds().clone(); + nodes.each(function (node) { + bounds.include(node.absoluteBounds().clone()); + }); + + + /* Set new Zoom Level */ + var scaleFactorWidth = visibleWidth / bounds.width(); + var scaleFactorHeight = visibleHeight / bounds.height(); + + /* Choose the smaller zoom level to fit the whole model */ + var zoomFactor = scaleFactorHeight < scaleFactorWidth ? scaleFactorHeight : scaleFactorWidth; + + /*Test if maximum zoom is reached*/ + if (zoomFactor > this.maxFitToScreenLevel) { + zoomFactor = this.maxFitToScreenLevel + } + /* Do zooming */ + this.setAFixZoomLevel(zoomFactor); + + /* Set scroll bar position */ + scrollNode.scrollTop = Math.round(bounds.upperLeft().y * this.zoomLevel) - 5; + scrollNode.scrollLeft = Math.round(bounds.upperLeft().x * this.zoomLevel) - 5; + + }, + + /** + * It checks if the zoom level is less or equal to the level, which is required + * to schow the whole canvas. + * + * @private + */ + _checkSize: function () { + var canvasParent = this.facade.getCanvas().getHTMLContainer().parentNode; + var minForCanvas = Math.min((canvasParent.parentNode.getWidth() / canvasParent.getWidth()), (canvasParent.parentNode.getHeight() / canvasParent.getHeight())); + return 1.05 > minForCanvas; + + }, + /** + * It checks if the zoom level is included in the definined zoom + * level range. + * + * @private + */ + _checkZoomLevelRange: function () { + /*var canvasParent=this.facade.getCanvas().getHTMLContainer().parentNode; + var maxForCanvas= Math.max((canvasParent.parentNode.getWidth()/canvasParent.getWidth()),(canvasParent.parentNode.getHeight()/canvasParent.getHeight())); + if(this.zoomLevel > maxForCanvas) { + this.zoomLevel = maxForCanvas; + }*/ + 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); +/* + * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +if (!Signavio) { + var Signavio = {} +} +; +if (!Signavio.Core) { + Signavio.Core = {} +} +; +Signavio.Core.Version = "1.0"; +/* + * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +/* + * All code Copyright 2013 KIS Consultancy all rights reserved + */ + +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 () { + + /** + * Provides an uniq id + * @overwrite + * @return {String} + * + */ + ORYX.Editor.provideId = function () { + var res = [], hex = '0123456789ABCDEF'; + + for (var i = 0; i < 36; i++) res[i] = Math.floor(Math.random() * 0x10); + + res[14] = 4; + res[19] = (res[19] & 0x3) | 0x8; + + for (var i = 0; i < 36; i++) res[i] = hex[res[i]]; + + res[8] = res[13] = res[18] = res[23] = '-'; + + return "sid-" + res.join(''); + }; + + +}(); + +/* + * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +/* + * All code Copyright 2013 KIS Consultancy all rights reserved + */ + +if (!ORYX.Plugins) { + ORYX.Plugins = new Object(); +} + +/** + * This plugin is responsible for displaying loading indicators and to prevent + * the user from accidently unloading the page by, e.g., pressing the backspace + * button and returning to the previous site in history. + * @param {Object} facade The editor plugin facade to register enhancements with. + */ +ORYX.Plugins.Loading = { + + construct: function (facade) { + + this.facade = facade; + + // The parent Node + 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 (options) { + if (options.text) + this.node.innerHTML = options.text + "..."; + else + this.node.innerHTML = ORYX.I18N.Loading.waiting; + this.node.removeClassName('StatusIndicator'); + this.node.addClassName('LoadingIndicator'); + this.node.style.display = "block"; + + var pos = this.facade.getCanvas().rootNode.parentNode.parentNode.parentNode.parentNode; + + this.node.style.top = pos.offsetTop + 'px'; + this.node.style.left = pos.offsetLeft + 'px'; + + }, + + disableLoading: function () { + this.node.style.display = "none"; + }, + + showStatus: function (options) { + if (options.text) { + this.node.innerHTML = options.text; + this.node.addClassName('StatusIndicator'); + this.node.removeClassName('LoadingIndicator'); + this.node.style.display = 'block'; + + var pos = this.facade.getCanvas().rootNode.parentNode.parentNode.parentNode.parentNode; + + this.node.style.top = pos.offsetTop + 'px'; + this.node.style.left = pos.offsetLeft + 'px'; + + var tout = options.timeout ? options.timeout : 2000; + + window.setTimeout((function () { + + this.disableLoading(); + + }).bind(this), tout); + } + + } +} + +ORYX.Plugins.Loading = Clazz.extend(ORYX.Plugins.Loading); +/* + * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +if (!ORYX.Plugins) { + ORYX.Plugins = new Object(); +} + +/* + * All code Copyright 2013 KIS Consultancy all rights reserved + */ + +/** + * This plugin is responsible for resizing the canvas. + * @param {Object} facade The editor plugin facade to register enhancements with. + */ +ORYX.Plugins.CanvasResize = Clazz.extend({ + + construct: function (facade) { + + this.facade = facade; + 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 (position, shrink) { + + resizeCanvas = function (position, extentionSize, facade) { + var canvas = facade.getCanvas(); + var b = canvas.bounds; + var scrollNode = facade.getCanvas().getHTMLContainer().parentNode.parentNode; + + if (position == "E" || position == "W") { + canvas.setSize({ + width: (b.width() + extentionSize) * canvas.zoomLevel, + height: (b.height()) * canvas.zoomLevel + }) + + } else if (position == "S" || position == "N") { + canvas.setSize({ + width: (b.width()) * canvas.zoomLevel, + height: (b.height() + extentionSize) * canvas.zoomLevel + }) + } + + if (position == "N" || position == "W") { + + var move = position == "N" ? {x: 0, y: extentionSize} : {x: extentionSize, y: 0}; + + // Move all children + canvas.getChildNodes(false, function (shape) { + shape.bounds.moveBy(move) + }) + // Move all dockers, when the edge has at least one docked shape + var edges = canvas.getChildEdges().findAll(function (edge) { + return edge.getAllDockedShapes().length > 0 + }) + var dockers = edges.collect(function (edge) { + return edge.dockers.findAll(function (docker) { + return !docker.getDockedShape() + }) + }).flatten(); + dockers.each(function (docker) { + docker.bounds.moveBy(move) + }) + } else if (position == "S") { + scrollNode.scrollTop += extentionSize; + } else if (position == "E") { + scrollNode.scrollLeft += extentionSize; + } + + jQuery(window).trigger('resize'); + + canvas.update(); + facade.updateSelection(); + } + + var commandClass = ORYX.Core.Command.extend({ + construct: function (position, extentionSize, facade) { + this.position = position; + this.extentionSize = extentionSize; + this.facade = facade; + }, + execute: function () { + resizeCanvas(this.position, this.extentionSize, this.facade); + }, + rollback: function () { + resizeCanvas(this.position, -this.extentionSize, this.facade); + }, + update: function () { + } + }); + + var extentionSize = ORYX.CONFIG.CANVAS_RESIZE_INTERVAL; + if (shrink) extentionSize = -extentionSize; + var command = new commandClass(position, extentionSize, this.facade); + + this.facade.executeCommands([command]); + + } + +}); + + +ORYX.Plugins.CanvasResizeButton = Clazz.extend({ + + construct: function (canvas, position, callback) { + this.canvas = canvas; + var parentNode = canvas.getHTMLContainer().parentNode; + + window.myParent = parentNode; + + var actualScrollNode = jQuery('#canvasSection')[0]; + var scrollNode = actualScrollNode; + var canvasNode = jQuery('#canvasSection').find(".ORYX_Editor")[0]; + var svgRootNode = canvasNode.children[0]; + + var iconClass = 'glyphicon glyphicon-chevron-'; + var iconClassShrink = 'glyphicon glyphicon-chevron-'; + if (position == 'N') { + iconClass += 'up'; + iconClassShrink += 'down'; + } else if (position == 'S') { + iconClass += 'down'; + iconClassShrink += 'up'; + } else if (position == 'E') { + iconClass += 'right'; + iconClassShrink += 'left'; + } else if (position == 'W') { + iconClass += 'left'; + iconClassShrink += 'right'; + } + + // The buttons + var idGrow = 'canvas-shrink-' + position; + var idShrink = 'canvas-grow-' + position; + + var buttonGrow = 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] + }, + ['i', {'class': iconClass}] + ]); + var buttonShrink = 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] + }, + ['i', {'class': iconClassShrink}] + ]); + // Defines a callback which gives back + // a boolean if the current mouse event + // is over the particular button area + var offSetWidth = 60; + var isOverOffset = function (event) { + + var isOverButton = event.target.id.indexOf("canvas-shrink") != -1 + || event.target.id.indexOf("canvas-grow") != -1 + || event.target.parentNode.id.indexOf("canvas-shrink") != -1 + || event.target.parentNode.id.indexOf("canvas-grow") != -1; + if (isOverButton) { + if (event.target.id == idGrow || event.target.id == idShrink || + event.target.parentNode.id == idGrow || event.target.parentNode.id == idShrink) { + return true; + } else { + return false; + } + } + + if (event.target != parentNode && event.target != scrollNode && event.target != scrollNode.firstChild && event.target != svgRootNode && event.target != scrollNode) { + return false; + } + + //if(inCanvas){offSetWidth=30}else{offSetWidth=30*2} + //Safari work around + var X = event.offsetX !== undefined ? event.offsetX : event.layerX; + var Y = event.offsetY !== undefined ? event.offsetY : event.layerY; + + var canvasOffset = 0; + if (canvasNode.clientWidth < actualScrollNode.clientWidth) { + var widthDiff = actualScrollNode.clientWidth - canvasNode.clientWidth; + canvasOffset = widthDiff / 2; + } + + // Adjust to relative location to the actual viewport + Y = Y - actualScrollNode.scrollTop; + X = X - actualScrollNode.scrollLeft; + + + if (position == "N") { + return Y < offSetWidth; + } else if (position == "W") { + return X < offSetWidth + canvasOffset; + } else if (position == "E") { + return actualScrollNode.clientWidth - X < offSetWidth + canvasOffset; + } else if (position == "S") { + return actualScrollNode.clientHeight - Y < offSetWidth; + } + + return false; + }; + + var showButtons = (function () { + buttonGrow.show(); + + var w = canvas.bounds.width(); + var h = canvas.bounds.height(); + + if (position == "N" && (h - ORYX.CONFIG.CANVAS_RESIZE_INTERVAL > ORYX.CONFIG.CANVAS_MIN_HEIGHT)) buttonShrink.show(); + else if (position == "E" && (w - ORYX.CONFIG.CANVAS_RESIZE_INTERVAL > ORYX.CONFIG.CANVAS_MIN_WIDTH)) buttonShrink.show(); + else if (position == "S" && (h - ORYX.CONFIG.CANVAS_RESIZE_INTERVAL > ORYX.CONFIG.CANVAS_MIN_HEIGHT)) buttonShrink.show(); + else if (position == "W" && (w - ORYX.CONFIG.CANVAS_RESIZE_INTERVAL > ORYX.CONFIG.CANVAS_MIN_WIDTH)) buttonShrink.show(); + else buttonShrink.hide(); + + + }).bind(this); + + var hideButtons = function () { + buttonGrow.hide(); + buttonShrink.hide(); + }; + + // If the mouse move is over the button area, show the button + parentNode.parentNode.addEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, function (event) { + if (isOverOffset(event)) { + showButtons(); + } else { + hideButtons() + } + }, false); + // If the mouse is over the button, show them + buttonGrow.addEventListener(ORYX.CONFIG.EVENT_MOUSEOVER, function (event) { + showButtons(); + }, true); + buttonShrink.addEventListener(ORYX.CONFIG.EVENT_MOUSEOVER, function (event) { + showButtons(); + }, true); + // If the mouse is out, hide the button + //scrollNode.addEventListener( ORYX.CONFIG.EVENT_MOUSEOUT, function(event){button.hide()}, true ) + parentNode.parentNode.addEventListener(ORYX.CONFIG.EVENT_MOUSEOUT, function (event) { + hideButtons() + }, true); + //svgRootNode.addEventListener( ORYX.CONFIG.EVENT_MOUSEOUT, function(event){ inCanvas = false } , true ); + + // Hide the button initialy + hideButtons(); + + // Add the callbacks + buttonGrow.addEventListener('click', function () { + callback(position); + showButtons(); + }, true); + buttonShrink.addEventListener('click', function () { + callback(position, true); + showButtons(); + }, true); + + } + + +}); + +/* + * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +/* + * All code Copyright 2013 KIS Consultancy all rights reserved + */ + +if (!ORYX.Plugins) + ORYX.Plugins = new Object(); + +ORYX.Plugins.RenameShapes = Clazz.extend({ + + facade: undefined, + + construct: function (facade) { + + this.facade = facade; + + 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, // F2-Key + keyAction: ORYX.CONFIG.KEY_ACTION_DOWN + } + ], + functionality: this.renamePerF2.bind(this) + }); + + + document.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEDOWN, this.hide.bind(this), true); + }, + + /** + * This method handles the "F2" key down event. The selected shape are looked + * up and the editing of title/name of it gets started. + */ + renamePerF2: function () { + var selectedShapes = this.facade.getSelection(); + this.actOnDBLClick(undefined, selectedShapes.first()); + }, + + actOnDBLClick: function (evt, shape) { + + if (!(shape instanceof ORYX.Core.Shape)) { + return; + } + + // Destroys the old input, if there is one + this.destroy(); + + // Get all properties which where at least one ref to view is set + var props = shape.getStencil().properties().findAll(function (item) { + return (item.refToView() + && item.refToView().length > 0 + && item.directlyEditable()); + }); + // from these, get all properties where write access are and the type is String or Expression + props = 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); + }); + + // Get all ref ids + var allRefToViews = props.collect(function (prop) { + return prop.refToView(); + }).flatten().compact(); + // Get all labels from the shape with the ref ids + var labels = shape.getLabels().findAll(function (label) { + return allRefToViews.any(function (toView) { + return label.id.endsWith(toView); + }); + }); + + // If there are no referenced labels --> return + if (labels.length == 0) { + return; + } + + // Define the nearest label + var nearestLabel = labels.length <= 1 ? labels[0] : null; + if (!nearestLabel) { + nearestLabel = labels.find(function (label) { + return label.node == evt.target || label.node == evt.target.parentNode; + }); + if (!nearestLabel) { + + var evtCoord = this.facade.eventCoordinates(evt); + + var additionalIEZoom = 1; + if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) { + var ua = navigator.userAgent; + if (ua.indexOf('MSIE') >= 0) { + //IE 10 and below + var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100); + if (zoom !== 100) { + additionalIEZoom = zoom / 100 + } + } + } + + if (additionalIEZoom !== 1) { + evtCoord.x = evtCoord.x / additionalIEZoom; + evtCoord.y = evtCoord.y / additionalIEZoom; + } + + evtCoord.y += $("editor-header").clientHeight - $("canvasSection").scrollTop - 5; + if (KISBPM.HEADER_CONFIG.showAppTitle == false) { + evtCoord.y += 61; + } + + evtCoord.x -= $("canvasSection").scrollLeft; + + var trans = this.facade.getCanvas().rootNode.lastChild.getScreenCTM(); + evtCoord.x *= trans.a; + evtCoord.y *= trans.d; + + var diff = labels.collect(function (label) { + var center = this.getCenterPosition(label.node); + var len = Math.sqrt(Math.pow(center.x - evtCoord.x, 2) + Math.pow(center.y - evtCoord.y, 2)); + return {diff: len, label: label}; + }.bind(this)); + + diff.sort(function (a, b) { + return a.diff > b.diff; + }); + + nearestLabel = diff[0].label; + } - else { - //set minimumSize to (1,1), so that width and height of the stencil can never be (0,0) - this.minimumSize = { - width: 1, - height: 1 - }; + } + // Get the particular property for the label + var prop = props.find(function (item) { + return item.refToView().any(function (toView) { + return nearestLabel.id == shape.id + toView; + }); + }); + + // Get the center position from the nearest label + var width = Math.min(Math.max(100, shape.bounds.width()), 200); + var center = this.getCenterPosition(nearestLabel.node, shape); + center.x -= (width / 2); + var propId = prop.prefix() + "-" + prop.id(); + var textInput = document.createElement("textarea"); + textInput.id = 'shapeTextInput'; + textInput.style.position = 'absolute'; + textInput.style.width = width + 'px'; + textInput.style.left = (center.x < 10) ? 10 : center.x + 'px'; + textInput.style.top = (center.y - 15) + 'px'; + textInput.className = 'x-form-textarea x-form-field x_form_text_set_absolute'; + textInput.value = shape.properties[propId]; + this.oldValueText = shape.properties[propId]; + document.getElementById('canvasSection').appendChild(textInput); + this.shownTextField = textInput; + + + // Value change listener needs to be defined now since we reference it in the text field + this.updateValueFunction = function (newValue, oldValue) { + var currentEl = shape; + var facade = this.facade; + + if (oldValue != newValue) { + // Implement the specific command for property change + var commandClass = ORYX.Core.Command.extend({ + construct: function () { + this.el = currentEl; + this.propId = propId; + this.oldValue = oldValue; + this.newValue = newValue; + this.facade = facade; + }, + execute: function () { + this.el.setProperty(this.propId, this.newValue); + //this.el.update(); + this.facade.setSelection([this.el]); + this.facade.getCanvas().update(); + this.facade.updateSelection(); + }, + rollback: function () { + this.el.setProperty(this.propId, this.oldValue); + //this.el.update(); + this.facade.setSelection([this.el]); + this.facade.getCanvas().update(); + this.facade.updateSelection(); + } + }); + // Instantiated the class + var command = new commandClass(); + + // Execute the command + this.facade.executeCommands([command]); + } + }.bind(this); + + jQuery("#shapeTextInput").focus(); + + jQuery("#shapeTextInput").autogrow(); + + // Disable the keydown in the editor (that when hitting the delete button, the shapes not get deleted) + this.facade.disableEvent(ORYX.CONFIG.EVENT_KEYDOWN); + + }, + + getCenterPosition: function (svgNode, shape) { + + if (!svgNode) { + return {x: 0, y: 0}; + } + + var scale = this.facade.getCanvas().node.getScreenCTM(); + var absoluteXY = shape.bounds.upperLeft(); + + var hasParent = true; + var searchShape = shape; + while (hasParent) { + if (searchShape.getParentShape().getStencil().idWithoutNs() === 'BPMNDiagram') { + hasParent = false; + } else { + var parentXY = searchShape.getParentShape().bounds.upperLeft(); + absoluteXY.x += parentXY.x; + absoluteXY.y += parentXY.y; + searchShape = searchShape.getParentShape(); + } + } + + var center = shape.bounds.midPoint(); + center.x += absoluteXY.x + scale.e; + center.y += absoluteXY.y + scale.f; + + center.x *= scale.a; + center.y *= scale.d; + + var additionalIEZoom = 1; + if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) { + var ua = navigator.userAgent; + if (ua.indexOf('MSIE') >= 0) { + //IE 10 and below + var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100); + if (zoom !== 100) { + additionalIEZoom = zoom / 100 + } + } + } + + if (additionalIEZoom === 1) { + center.y = center.y - jQuery("#canvasSection").offset().top + 5; + center.x -= jQuery("#canvasSection").offset().left; + + } else { + var canvasOffsetLeft = jQuery("#canvasSection").offset().left; + var canvasScrollLeft = jQuery("#canvasSection").scrollLeft(); + var canvasScrollTop = jQuery("#canvasSection").scrollTop(); + + var offset = scale.e - (canvasOffsetLeft * additionalIEZoom); + var additionaloffset = 0; + if (offset > 10) { + additionaloffset = (offset / additionalIEZoom) - offset; + } + center.y = center.y - (jQuery("#canvasSection").offset().top * additionalIEZoom) + 5 + ((canvasScrollTop * additionalIEZoom) - canvasScrollTop); + center.x = center.x - (canvasOffsetLeft * additionalIEZoom) + additionaloffset + ((canvasScrollLeft * additionalIEZoom) - canvasScrollLeft); + } + + + return center; + }, + + hide: function (e) { + if (this.shownTextField && (!e || e.target !== this.shownTextField)) { + var newValue = this.shownTextField.value; + if (newValue !== this.oldValueText) { + this.updateValueFunction(newValue, this.oldValueText); } + this.destroy(); + } + }, + + hideField: function (e) { + if (this.shownTextField) { + this.destroy(); + } + }, + + destroy: function (e) { + var textInputComp = jQuery("#shapeTextInput"); + if (textInputComp) { + textInputComp.remove(); + delete this.shownTextField; + + this.facade.enableEvent(ORYX.CONFIG.EVENT_KEYDOWN); + } + } +}); +/* + * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +/* + * All code Copyright 2013 KIS Consultancy all rights reserved + */ + +if (!ORYX.Plugins) + ORYX.Plugins = new Object(); + +/** + * Supports EPCs by offering a syntax check and export and import ability.. + * + * + */ +ORYX.Plugins.ProcessLink = Clazz.extend({ + + facade: undefined, + + /** + * Offers the plugin functionality: + * + */ + construct: function (facade) { + + this.facade = facade; + + this.facade.registerOnEvent(ORYX.CONFIG.EVENT_PROPERTY_CHANGED, this.propertyChanged.bind(this)); + + }, + + + /** + * + * @param {Object} option + */ + propertyChanged: function (option, node) { + + if (option.name !== "oryx-refuri" || !node instanceof ORYX.Core.Node) { + return + } + + + if (option.value && option.value.length > 0 && option.value != "undefined") { + + this.show(node, option.value); + + } else { + + this.hide(node); + + } + + }, + + /** + * Shows the Link for a particular shape with a specific url + * + * @param {Object} shape + * @param {Object} url + */ + show: function (shape, url) { + + + // Generate the svg-representation of a link + var link = ORYX.Editor.graft("http://www.w3.org/2000/svg", null, + ['a', + {'target': '_blank'}, + ['path', + { + "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" + } + ] + ]); + + var link = 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" + }], + ]); + + /* + * + * [ 'a', + {'target': '_blank'}, + ['path', { "style": "fill:none;stroke-width:0.5px; stroke:#000000", "d": "M7,4 l0,2"}], + ['path', { "style": "fill:none;stroke-width:0.5px; stroke:#000000", "d": "M4,8 l-2,0 l0,6"}], + ['path', { "style": "fill:none;stroke-width:0.5px; stroke:#000000", "d": "M10,8 l2,0 l0,6"}], + ['rect', { "style": "fill:#96ff96;stroke:#000000;stroke-width:1", "width": 6, "height": 4, "x": 4, "y": 0}], + ['rect', { "style": "fill:#ffafff;stroke:#000000;stroke-width:1", "width": 6, "height": 4, "x": 4, "y": 6}], + ['rect', { "style": "fill:#96ff96;stroke:#000000;stroke-width:1", "width": 6, "height": 4, "x": 0, "y": 12}], + ['rect', { "style": "fill:#96ff96;stroke:#000000;stroke-width:1", "width": 6, "height": 4, "x": 8, "y": 12}], + ['rect', { "style": "fill:none;stroke:none;pointer-events:all", "width": 14, "height": 16, "x": 0, "y": 0}] + ]); + */ + + // Set the link with the special namespace + link.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", url); + + + // Shows the link in the overlay + this.facade.raiseEvent({ + type: ORYX.CONFIG.EVENT_OVERLAY_SHOW, + id: "arissupport.urlref_" + shape.id, + shapes: [shape], + node: link, + nodePosition: "SE" + }); + + }, + + /** + * Hides the Link for a particular shape + * + * @param {Object} shape + */ + hide: function (shape) { + + this.facade.raiseEvent({ + type: ORYX.CONFIG.EVENT_OVERLAY_HIDE, + id: "arissupport.urlref_" + shape.id + }); + + } +});/* + * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +/* + * All code Copyright 2013 KIS Consultancy all rights reserved + */ + +Array.prototype.insertFrom = function (from, to) { + to = Math.max(0, to); + from = Math.min(Math.max(0, from), this.length - 1); + + var el = this[from]; + var old = this.without(el); + var newA = old.slice(0, to); + newA.push(el); + if (old.length > to) { + newA = newA.concat(old.slice(to)) + } + ; + return newA; +} + +if (!ORYX.Plugins) + ORYX.Plugins = new Object(); + +ORYX.Plugins.Arrangement = ORYX.Plugins.AbstractPlugin.extend({ + + facade: undefined, + + construct: function (facade) { + this.facade = facade; + + // Z-Ordering + /** Hide for SIGNAVIO + + this.facade.offer({ + 'name':ORYX.I18N.Arrangement.btf, + 'functionality': this.setZLevel.bind(this, this.setToTop), + 'group': ORYX.I18N.Arrangement.groupZ, + 'icon': ORYX.PATH + "images/shape_move_front.png", + 'description': ORYX.I18N.Arrangement.btfDesc, + 'index': 1, + 'minShape': 1}); + + this.facade.offer({ + 'name':ORYX.I18N.Arrangement.btb, + 'functionality': this.setZLevel.bind(this, this.setToBack), + 'group': ORYX.I18N.Arrangement.groupZ, + 'icon': ORYX.PATH + "images/shape_move_back.png", + 'description': ORYX.I18N.Arrangement.btbDesc, + 'index': 2, + 'minShape': 1}); + + this.facade.offer({ + 'name':ORYX.I18N.Arrangement.bf, + 'functionality': this.setZLevel.bind(this, this.setForward), + 'group': ORYX.I18N.Arrangement.groupZ, + 'icon': ORYX.PATH + "images/shape_move_forwards.png", + 'description': ORYX.I18N.Arrangement.bfDesc, + 'index': 3, + 'minShape': 1}); + + this.facade.offer({ + 'name':ORYX.I18N.Arrangement.bb, + 'functionality': this.setZLevel.bind(this, this.setBackward), + 'group': ORYX.I18N.Arrangement.groupZ, + 'icon': ORYX.PATH + "images/shape_move_backwards.png", + 'description': ORYX.I18N.Arrangement.bbDesc, + 'index': 4, + 'minShape': 1}); + + // Aligment + this.facade.offer({ + 'name':ORYX.I18N.Arrangement.ab, + 'functionality': this.alignShapes.bind(this, [ORYX.CONFIG.EDITOR_ALIGN_BOTTOM]), + 'group': ORYX.I18N.Arrangement.groupA, + 'icon': ORYX.PATH + "images/shape_align_bottom.png", + 'description': ORYX.I18N.Arrangement.abDesc, + 'index': 1, + 'minShape': 2}); + + + + this.facade.offer({ + 'name':ORYX.I18N.Arrangement.at, + 'functionality': this.alignShapes.bind(this, [ORYX.CONFIG.EDITOR_ALIGN_TOP]), + 'group': ORYX.I18N.Arrangement.groupA, + 'icon': ORYX.PATH + "images/shape_align_top.png", + 'description': ORYX.I18N.Arrangement.atDesc, + 'index': 3, + 'minShape': 2}); + + this.facade.offer({ + 'name':ORYX.I18N.Arrangement.al, + 'functionality': this.alignShapes.bind(this, [ORYX.CONFIG.EDITOR_ALIGN_LEFT]), + 'group': ORYX.I18N.Arrangement.groupA, + 'icon': ORYX.PATH + "images/shape_align_left.png", + 'description': ORYX.I18N.Arrangement.alDesc, + 'index': 4, + 'minShape': 2}); + + this.facade.offer({ + 'name':ORYX.I18N.Arrangement.ar, + 'functionality': this.alignShapes.bind(this, [ORYX.CONFIG.EDITOR_ALIGN_RIGHT]), + 'group': ORYX.I18N.Arrangement.groupA, + 'icon': ORYX.PATH + "images/shape_align_right.png", + 'description': ORYX.I18N.Arrangement.arDesc, + 'index': 6, + 'minShape': 2}); + + **/ + + 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 (elemnt) { + var selection = this.facade.getSelection(); + if (selection.length === 1 && selection[0] instanceof ORYX.Core.Edge) { + this.setToTop(selection); } - - var maxSizeAttr = svgNode.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, "maximumSize"); - if (maxSizeAttr) { - maxSizeAttr = maxSizeAttr.replace("/,/g", " "); - var maxSizeValues = maxSizeAttr.split(" "); - maxSizeValues = maxSizeValues.without(""); - - if (maxSizeValues.length > 1) { - this.maximumSize = { - width: parseFloat(maxSizeValues[0]), - height: parseFloat(maxSizeValues[1]) - }; + }, + + setZLevel: function (callback, event) { + + //Command-Pattern for dragging one docker + var zLevelCommand = ORYX.Core.Command.extend({ + construct: function (callback, elements, facade) { + this.callback = callback; + this.elements = elements; + // For redo, the previous elements get stored + this.elAndIndex = elements.map(function (el) { + return {el: el, previous: el.parent.children[el.parent.children.indexOf(el) - 1]} + }) + this.facade = facade; + }, + execute: function () { + + // Call the defined z-order callback with the elements + this.callback(this.elements) + this.facade.setSelection(this.elements) + }, + rollback: function () { + + // Sort all elements on the index of there containment + var sortedEl = this.elAndIndex.sortBy(function (el) { + var value = el.el; + var t = $A(value.node.parentNode.childNodes); + return t.indexOf(value.node); + }); + + // Every element get setted back bevor the old previous element + for (var i = 0; i < sortedEl.length; i++) { + var el = sortedEl[i].el; + var p = el.parent; + var oldIndex = p.children.indexOf(el); + var newIndex = p.children.indexOf(sortedEl[i].previous); + newIndex = newIndex || 0 + p.children = p.children.insertFrom(oldIndex, newIndex) + el.node.parentNode.insertBefore(el.node, el.node.parentNode.childNodes[newIndex + 1]); + } + + // Reset the selection + this.facade.setSelection(this.elements) } + }); + + // Instanziate the dockCommand + var command = new zLevelCommand(callback, this.facade.getSelection(), this.facade); + if (event.excludeCommand) { + command.execute(); + } else { + this.facade.executeCommands([command]); } - - if (this.minimumSize && this.maximumSize && - (this.minimumSize.width > this.maximumSize.width || - this.minimumSize.height > this.maximumSize.height)) { - - //TODO wird verschluckt!!! - throw this + ": Minimum Size must be greater than maxiumSize."; - } - - /**get current bounds and adjust it to upperLeft == (0,0)*/ - //initialize all SVGShape objects - this._svgShapes = this._initSVGShapes(svgNode); - - //get upperLeft and lowerRight of stencil - var upperLeft = { - x: undefined, - y: undefined - }; - var lowerRight = { - x: undefined, - y: undefined - }; - var me = this; - this._svgShapes.each(function(svgShape){ - upperLeft.x = (upperLeft.x !== undefined) ? Math.min(upperLeft.x, svgShape.x) : svgShape.x; - upperLeft.y = (upperLeft.y !== undefined) ? Math.min(upperLeft.y, svgShape.y) : svgShape.y; - lowerRight.x = (lowerRight.x !== undefined) ? Math.max(lowerRight.x, svgShape.x + svgShape.width) : svgShape.x + svgShape.width; - lowerRight.y = (lowerRight.y !== undefined) ? Math.max(lowerRight.y, svgShape.y + svgShape.height) : svgShape.y + svgShape.height; - - /** set if resizing is enabled */ - //TODO isResizable durch die beiden anderen booleans ersetzen? - if (svgShape.isHorizontallyResizable) { - me.isHorizontallyResizable = true; - me.isResizable = true; - } - if (svgShape.isVerticallyResizable) { - me.isVerticallyResizable = true; - me.isResizable = true; + + }, + + setToTop: function (elements) { + + // Sortieren des Arrays nach dem Index des SVGKnotens im Bezug auf dem Elternknoten. + var tmpElem = elements.sortBy(function (value, index) { + var t = $A(value.node.parentNode.childNodes); + return t.indexOf(value.node); + }); + // Sortiertes Array wird nach oben verschoben. + tmpElem.each(function (value) { + var p = value.parent; + if (p.children.last() === value) { + return; } - if (svgShape.anchorTop && svgShape.anchorBottom) { - me.isVerticallyResizable = true; - me.isResizable = true; + p.children = p.children.without(value) + p.children.push(value); + value.node.parentNode.appendChild(value.node); + }); + }, + + setToBack: function (elements) { + // Sortieren des Arrays nach dem Index des SVGKnotens im Bezug auf dem Elternknoten. + var tmpElem = elements.sortBy(function (value, index) { + var t = $A(value.node.parentNode.childNodes); + return t.indexOf(value.node); + }); + + tmpElem = tmpElem.reverse(); + + // Sortiertes Array wird nach unten verschoben. + tmpElem.each(function (value) { + var p = value.parent + p.children = p.children.without(value) + p.children.unshift(value); + value.node.parentNode.insertBefore(value.node, value.node.parentNode.firstChild); + }); + + + }, + + setBackward: function (elements) { + // Sortieren des Arrays nach dem Index des SVGKnotens im Bezug auf dem Elternknoten. + var tmpElem = elements.sortBy(function (value, index) { + var t = $A(value.node.parentNode.childNodes); + return t.indexOf(value.node); + }); + + // Reverse the elements + tmpElem = tmpElem.reverse(); + + // Delete all Nodes who are the next Node in the nodes-Array + var compactElem = tmpElem.findAll(function (el) { + return !tmpElem.some(function (checkedEl) { + return checkedEl.node == el.node.previousSibling + }) + }); + + // Sortiertes Array wird nach eine Ebene nach oben verschoben. + compactElem.each(function (el) { + if (el.node.previousSibling === null) { + return; } - if (svgShape.anchorLeft && svgShape.anchorRight) { - me.isHorizontallyResizable = true; - me.isResizable = true; + var p = el.parent; + var index = p.children.indexOf(el); + p.children = p.children.insertFrom(index, index - 1) + el.node.parentNode.insertBefore(el.node, el.node.previousSibling); + }); + + + }, + + setForward: function (elements) { + // Sortieren des Arrays nach dem Index des SVGKnotens im Bezug auf dem Elternknoten. + var tmpElem = elements.sortBy(function (value, index) { + var t = $A(value.node.parentNode.childNodes); + return t.indexOf(value.node); + }); + + + // Delete all Nodes who are the next Node in the nodes-Array + var compactElem = tmpElem.findAll(function (el) { + return !tmpElem.some(function (checkedEl) { + return checkedEl.node == el.node.nextSibling + }) + }); + + + // Sortiertes Array wird eine Ebene nach unten verschoben. + compactElem.each(function (el) { + var nextNode = el.node.nextSibling + if (nextNode === null) { + return; } + var index = el.parent.children.indexOf(el); + var p = el.parent; + p.children = p.children.insertFrom(index, index + 1) + el.node.parentNode.insertBefore(nextNode, el.node); }); - - //move all SVGShapes by -upperLeft - this._svgShapes.each(function(svgShape){ - svgShape.x -= upperLeft.x; - svgShape.y -= upperLeft.y; - svgShape.update(); + }, + + + alignShapes: function (way) { + + var elements = this.facade.getSelection(); + + // Set the elements to all Top-Level elements + elements = this.facade.getCanvas().getShapesWithSharedParent(elements); + // Get only nodes + elements = elements.findAll(function (value) { + return (value instanceof ORYX.Core.Node) }); - - //set bounds of shape - //the offsets are also needed for positioning the magnets and the docker - var offsetX = upperLeft.x; - var offsetY = upperLeft.y; - - lowerRight.x -= offsetX; - lowerRight.y -= offsetY; - upperLeft.x = 0; - upperLeft.y = 0; - - //prevent that width or height of initial bounds is 0 - if (lowerRight.x === 0) { - lowerRight.x = 1; - } - if (lowerRight.y === 0) { - lowerRight.y = 1; + // Delete all attached intermediate events from the array + elements = elements.findAll(function (value) { + var d = value.getIncomingShapes() + return d.length == 0 || !elements.include(d[0]) + }); + if (elements.length < 2) { + return; } - - this._oldBounds.set(upperLeft, lowerRight); - this.bounds.set(upperLeft, lowerRight); - - /**initialize magnets */ - - var magnets = svgDocument.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_ORYX, "magnets"); - - if (magnets && magnets.length > 0) { - - magnets = $A(magnets[0].getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_ORYX, "magnet")); - - var me = this; - magnets.each(function(magnetElem){ - var magnet = new ORYX.Core.Controls.Magnet({ - eventHandlerCallback: me.eventHandlerCallback - }); - var cx = parseFloat(magnetElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, "cx")); - var cy = parseFloat(magnetElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, "cy")); - magnet.bounds.centerMoveTo({ - x: cx - offsetX, - y: cy - offsetY - }); - - //get anchors - var anchors = magnetElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, "anchors"); - if (anchors) { - anchors = anchors.replace("/,/g", " "); - anchors = anchors.split(" ").without(""); - for(var i = 0; i < anchors.length; i++) { - switch(anchors[i].toLowerCase()) { - case "left": - magnet.anchorLeft = true; - break; - case "right": - magnet.anchorRight = true; - break; - case "top": - magnet.anchorTop = true; - break; - case "bottom": - magnet.anchorBottom = true; - break; - } - } + + // get bounds of all shapes. + var bounds = elements[0].absoluteBounds().clone(); + elements.each(function (shape) { + bounds.include(shape.absoluteBounds().clone()); + }); + + // get biggest width and heigth + var maxWidth = 0; + var maxHeight = 0; + elements.each(function (shape) { + maxWidth = Math.max(shape.bounds.width(), maxWidth); + maxHeight = Math.max(shape.bounds.height(), maxHeight); + }); + + var commandClass = ORYX.Core.Command.extend({ + construct: function (elements, bounds, maxHeight, maxWidth, way, plugin) { + this.elements = elements; + this.bounds = bounds; + this.maxHeight = maxHeight; + this.maxWidth = maxWidth; + this.way = way; + this.facade = plugin.facade; + this.plugin = plugin; + this.orgPos = []; + }, + setBounds: function (shape, maxSize) { + if (!maxSize) + maxSize = {width: ORYX.CONFIG.MAXIMUM_SIZE, height: ORYX.CONFIG.MAXIMUM_SIZE}; + + if (!shape.bounds) { + throw "Bounds not definined." } - - me.add(magnet); - - //check, if magnet is default magnet - if (!this._defaultMagnet) { - var defaultAttr = magnetElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, "default"); - if (defaultAttr && defaultAttr.toLowerCase() === "yes") { - me._defaultMagnet = magnet; + + var newBounds = { + a: { + x: shape.bounds.upperLeft().x - (this.maxWidth - shape.bounds.width()) / 2, + y: shape.bounds.upperLeft().y - (this.maxHeight - shape.bounds.height()) / 2 + }, + b: { + x: shape.bounds.lowerRight().x + (this.maxWidth - shape.bounds.width()) / 2, + y: shape.bounds.lowerRight().y + (this.maxHeight - shape.bounds.height()) / 2 + } + } + + /* If the new width of shape exceeds the maximum width, set width value to maximum. */ + if (this.maxWidth > maxSize.width) { + newBounds.a.x = shape.bounds.upperLeft().x - + (maxSize.width - shape.bounds.width()) / 2; + + newBounds.b.x = shape.bounds.lowerRight().x + (maxSize.width - shape.bounds.width()) / 2 + } + + /* If the new height of shape exceeds the maximum height, set height value to maximum. */ + if (this.maxHeight > maxSize.height) { + newBounds.a.y = shape.bounds.upperLeft().y - + (maxSize.height - shape.bounds.height()) / 2; + + newBounds.b.y = shape.bounds.lowerRight().y + (maxSize.height - shape.bounds.height()) / 2 + } + + /* set bounds of shape */ + shape.bounds.set(newBounds); + + }, + execute: function () { + // align each shape according to the way that was specified. + this.elements.each(function (shape, index) { + this.orgPos[index] = shape.bounds.upperLeft(); + + var relBounds = this.bounds.clone(); + var newCoordinates; + if (shape.parent && !(shape.parent instanceof ORYX.Core.Canvas)) { + var upL = shape.parent.absoluteBounds().upperLeft(); + relBounds.moveBy(-upL.x, -upL.y); + } + + switch (this.way) { + // align the shapes in the requested way. + case ORYX.CONFIG.EDITOR_ALIGN_BOTTOM: + newCoordinates = { + x: shape.bounds.upperLeft().x, + y: relBounds.b.y - shape.bounds.height() + }; + break; + + case ORYX.CONFIG.EDITOR_ALIGN_MIDDLE: + newCoordinates = { + x: shape.bounds.upperLeft().x, + y: (relBounds.a.y + relBounds.b.y - shape.bounds.height()) / 2 + }; + break; + + case ORYX.CONFIG.EDITOR_ALIGN_TOP: + newCoordinates = { + x: shape.bounds.upperLeft().x, + y: relBounds.a.y + }; + break; + + case ORYX.CONFIG.EDITOR_ALIGN_LEFT: + newCoordinates = { + x: relBounds.a.x, + y: shape.bounds.upperLeft().y + }; + break; + + case ORYX.CONFIG.EDITOR_ALIGN_CENTER: + newCoordinates = { + x: (relBounds.a.x + relBounds.b.x - shape.bounds.width()) / 2, + y: shape.bounds.upperLeft().y + }; + break; + + case ORYX.CONFIG.EDITOR_ALIGN_RIGHT: + newCoordinates = { + x: relBounds.b.x - shape.bounds.width(), + y: shape.bounds.upperLeft().y + }; + break; + + case ORYX.CONFIG.EDITOR_ALIGN_SIZE: + if (shape.isResizable) { + this.orgPos[index] = {a: shape.bounds.upperLeft(), b: shape.bounds.lowerRight()}; + this.setBounds(shape, shape.maximumSize); + } + break; } - } - }); - } - else { - // Add a Magnet in the Center of Shape - var magnet = new ORYX.Core.Controls.Magnet(); - magnet.bounds.centerMoveTo(this.bounds.width() / 2, this.bounds.height() / 2); - this.add(magnet); - } - - /**initialize docker */ - var dockerElem = svgDocument.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_ORYX, "docker"); - - if (dockerElem && dockerElem.length > 0) { - dockerElem = dockerElem[0]; - var docker = this.createDocker(); - var cx = parseFloat(dockerElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, "cx")); - var cy = parseFloat(dockerElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, "cy")); - docker.bounds.centerMoveTo({ - x: cx - offsetX, - y: cy - offsetY - }); - - //get anchors - var anchors = dockerElem.getAttributeNS(ORYX.CONFIG.NAMESPACE_ORYX, "anchors"); - if (anchors) { - anchors = anchors.replace("/,/g", " "); - anchors = anchors.split(" ").without(""); - - for(var i = 0; i < anchors.length; i++) { - switch(anchors[i].toLowerCase()) { - case "left": - docker.anchorLeft = true; - break; - case "right": - docker.anchorRight = true; - break; - case "top": - docker.anchorTop = true; - break; - case "bottom": - docker.anchorBottom = true; - break; - } - } + + if (newCoordinates) { + var offset = { + x: shape.bounds.upperLeft().x - newCoordinates.x, + y: shape.bounds.upperLeft().y - newCoordinates.y + } + // Set the new position + shape.bounds.moveTo(newCoordinates); + this.plugin.layoutEdges(shape, shape.getAllDockedShapes(), offset); + //shape.update() + } + }.bind(this)); + + //this.facade.getCanvas().update(); + //this.facade.updateSelection(); + }, + rollback: function () { + this.elements.each(function (shape, index) { + if (this.way == ORYX.CONFIG.EDITOR_ALIGN_SIZE) { + if (shape.isResizable) { + shape.bounds.set(this.orgPos[index]); + } + } else { + shape.bounds.moveTo(this.orgPos[index]); + } + }.bind(this)); + + //this.facade.getCanvas().update(); + //this.facade.updateSelection(); + } + }) + + var command = new commandClass(elements, bounds, maxHeight, maxWidth, parseInt(way), this); + + this.facade.executeCommands([command]); + } +});/* + * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +/* + * All code Copyright 2013 KIS Consultancy all rights reserved + */ + +if (!ORYX.Plugins) + ORYX.Plugins = new Object(); + +ORYX.Plugins.Save = Clazz.extend({ + + facade: undefined, + + processURI: undefined, + + changeSymbol: "*", + + construct: function (facade) { + this.facade = facade; + + document.addEventListener("keydown", function (e) { + if (e.ctrlKey && e.keyCode === 83) { + Event.stop(e); } + }, false); + + window.onbeforeunload = this.onUnLoad.bind(this); + + this.changeDifference = 0; + + // Register on event for executing commands --> store all commands in a stack + // --> Execute + 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)); + // --> Saved from other places in the editor + this.facade.registerOnEvent(ORYX.CONFIG.EVENT_SAVED, function () { + this.changeDifference = 0; + this.updateTitle(); + }.bind(this)); + + // --> Rollback + this.facade.registerOnEvent(ORYX.CONFIG.EVENT_UNDO_ROLLBACK, function () { + this.changeDifference--; + this.updateTitle(); + }.bind(this)); + + //TODO very critical for load time performance!!! + //this.serializedDOM = DataManager.__persistDOM(this.facade); + + this.hasChanges = this._hasChanges.bind(this); + }, + + updateTitle: function () { + + var value = window.document.title || document.getElementsByTagName("title")[0].childNodes[0].nodeValue; + + if (this.changeDifference === 0 && value.startsWith(this.changeSymbol)) { + window.document.title = value.slice(1); + } else if (this.changeDifference !== 0 && !value.startsWith(this.changeSymbol)) { + window.document.title = this.changeSymbol + "" + value; } - - /**initialize labels*/ - var textElems = svgNode.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'text'); - $A(textElems).each((function(textElem){ - var label = new ORYX.Core.SVG.Label({ - textElement: textElem, - shapeId: this.id - }); - label.x -= offsetX; - label.y -= offsetY; - this._labels[label.id] = label; - - label.registerOnChange(this.layout.bind(this)); - - // Only apply fitting on form-components - if(this._stencil.id().indexOf(ORYX.CONFIG.FORM_ELEMENT_ID_PREFIX) == 0) { - label.registerOnChange(this.fitToLabels.bind(this)); - } - - }).bind(this)); }, - - fitToLabels: function() { - var y = 0; - - this.getLabels().each(function(label){ - var lr = label.getY() + label.getHeight(); - if(lr > y) { - y = lr; - } - }); - - var bounds = this.bounds; - var boundsChanged = false; - - if(this.minimumSize) { - // Check if y-value exceeds the min-value. If not, stick to this value. - var minHeight = this.minimumSize.height; - if(y < minHeight && bounds.height() > minHeight && minHeight > this.forcedHeight) { - bounds.set(bounds.upperLeft().x, bounds.upperLeft().y, bounds.lowerRight().x, bounds.upperLeft().y + minHeight); - boundsChanged = true; - } else if(y > minHeight && bounds.height() != y && y > this.forcedHeight){ - bounds.set(bounds.upperLeft().x, bounds.upperLeft().y, bounds.lowerRight().x, bounds.upperLeft().y + y); - boundsChanged = true; - } else if(bounds.height() > this.forcedHeight && this.forcedHeight > 0) { - bounds.set(bounds.upperLeft().x, bounds.upperLeft().y, bounds.lowerRight().x, bounds.upperLeft().y + this.forcedHeight); - boundsChanged = true; - } - } - - if(boundsChanged) { - // Force facade to re-layout since bounds are changed AFTER layout has been performed - if(this.facade.getCanvas() != null) { - this.facade.getCanvas().update(); - } - - // Re-select if needed to force the select - if(this.facade.getSelection().member(this)) { - var selectedNow = this.facade.getSelection(); - this.facade.setSelection([]); - this.facade.setSelection(selectedNow); - } - } - }, - - /** - * Override the Method, that a docker is not shown - * - */ - createDocker: function() { - var docker = new ORYX.Core.Controls.Docker({eventHandlerCallback: this.eventHandlerCallback}); - docker.bounds.registerCallback(this._dockerChangedCallback); - - this.dockers.push( docker ); - docker.parent = this; - docker.bounds.registerCallback(this._changedCallback); - - return docker - }, - - toString: function(){ - return this._stencil.title() + " " + this.id + + _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; + } } -}; -ORYX.Core.Node = ORYX.Core.Shape.extend(ORYX.Core.Node); +}); /* * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. * License rights for this program may be obtained from Alfresco Software, Ltd. @@ -15041,2450 +20101,1605 @@ ORYX.Core.Node = ORYX.Core.Shape.extend(ORYX.Core.Node); * All code Copyright 2013 KIS Consultancy all rights reserved */ -NAMESPACE_SVG = "http://www.w3.org/2000/svg"; -NAMESPACE_ORYX = "http://www.b3mn.org/oryx"; +if (!ORYX.Plugins) + ORYX.Plugins = new Object(); +ORYX.Plugins.DragDropResize = ORYX.Plugins.AbstractPlugin.extend({ -/** - * Init namespaces - */ -if (!ORYX) { - var ORYX = {}; -} -if (!ORYX.Core) { - ORYX.Core = {}; -} + /** + * Constructor + * @param {Object} Facade: The Facade of the Editor + */ + construct: function (facade) { + this.facade = facade; + // Initialize variables + this.currentShapes = []; // Current selected Shapes + //this.pluginsData = []; // Available Plugins + this.toMoveShapes = []; // Shapes there will be moved + this.distPoints = []; // Distance Points for Snap on Grid + this.isResizing = false; // Flag: If there was currently resized + this.dragEnable = false; // Flag: If Dragging is enabled + this.dragIntialized = false; // Flag: If the Dragging is initialized + this.edgesMovable = true; // Flag: If an edge is docked it is not movable + this.offSetPosition = {x: 0, y: 0}; // Offset of the Dragging + this.faktorXY = {x: 1, y: 1}; // The Current Zoom-Faktor + this.containmentParentNode; // the current future parent node for the dragged shapes + this.isAddingAllowed = false; // flag, if adding current selected shapes to containmentParentNode is allowed + this.isAttachingAllowed = false; // flag, if attaching to the current shape is allowed + + this.callbackMouseMove = this.handleMouseMove.bind(this); + this.callbackMouseUp = this.handleMouseUp.bind(this); + + // Get the SVG-Containernode + var containerNode = this.facade.getCanvas().getSvgContainer(); + + // Create the Selected Rectangle in the SVG + this.selectedRect = new ORYX.Plugins.SelectedRect(containerNode); + + // Show grid line if enabled + if (ORYX.CONFIG.SHOW_GRIDLINE) { + this.vLine = new ORYX.Plugins.GridLine(containerNode, ORYX.Plugins.GridLine.DIR_VERTICAL); + this.hLine = new ORYX.Plugins.GridLine(containerNode, ORYX.Plugins.GridLine.DIR_HORIZONTAL); + } + + // Get a HTML-ContainerNode + containerNode = this.facade.getCanvas().getHTMLContainer(); + + this.scrollNode = this.facade.getCanvas().rootNode.parentNode.parentNode; + + // Create the southeastern button for resizing + this.resizerSE = new ORYX.Plugins.Resizer(containerNode, "southeast", this.facade); + this.resizerSE.registerOnResize(this.onResize.bind(this)); // register the resize callback + this.resizerSE.registerOnResizeEnd(this.onResizeEnd.bind(this)); // register the resize end callback + this.resizerSE.registerOnResizeStart(this.onResizeStart.bind(this)); // register the resize start callback + + // Create the northwestern button for resizing + this.resizerNW = new ORYX.Plugins.Resizer(containerNode, "northwest", this.facade); + this.resizerNW.registerOnResize(this.onResize.bind(this)); // register the resize callback + this.resizerNW.registerOnResizeEnd(this.onResizeEnd.bind(this)); // register the resize end callback + this.resizerNW.registerOnResizeStart(this.onResizeStart.bind(this)); // register the resize start callback + + // For the Drag and Drop + // Register on MouseDown-Event on a Shape + this.facade.registerOnEvent(ORYX.CONFIG.EVENT_MOUSEDOWN, this.handleMouseDown.bind(this)); + }, -/** - * @classDescription Abstract base class for all connections. - * @extends {ORYX.Core.Shape} - * @param options {Object} - * - * TODO da die verschiebung der Edge nicht ueber eine - * translation gemacht wird, die sich auch auf alle kind UIObjects auswirkt, - * muessen die kinder hier beim verschieben speziell betrachtet werden. - * Das sollte ueberarbeitet werden. - * - */ -ORYX.Core.Edge = { /** - * Constructor - * @param {Object} options - * @param {Stencil} stencil + * On Mouse Down + * */ - construct: function(options, stencil, facade){ - arguments.callee.$.construct.apply(this, arguments); - - this.isMovable = true; - this.isSelectable = true; - - this._dockerUpdated = false; - - this._markers = new Hash(); //a hash map of SVGMarker objects where keys are the marker ids - this._paths = []; - this._interactionPaths = []; - this._dockersByPath = new Hash(); - this._markersByPath = new Hash(); - - /* Data structures to store positioning information of attached child nodes */ - this.attachedNodePositionData = new Hash(); - - //TODO was muss hier initial erzeugt werden? - var stencilNode = this.node.childNodes[0].childNodes[0]; - stencilNode = ORYX.Editor.graft("http://www.w3.org/2000/svg", stencilNode, ['g', { - "pointer-events": "painted" - }]); - - //Add to the EventHandler - this.addEventHandlers(stencilNode.parentNode); - - - this._oldBounds = this.bounds.clone(); - - //load stencil - this._init(this._stencil.view()); - - if (stencil instanceof Array) { - this.deserialize(stencil); + handleMouseDown: function (event, uiObj) { + // If the selection Bounds not intialized and the uiObj is not member of current selectio + // then return + if (!this.dragBounds || !this.currentShapes.member(uiObj) || !this.toMoveShapes.length) { + return; } - - }, - - _update: function(force){ - if(this._dockerUpdated || this.isChanged || force) { - - this.dockers.invoke("update"); - - if (false && (this.bounds.width() === 0 || this.bounds.height() === 0)) { - var width = this.bounds.width(); - var height = this.bounds.height(); - this.bounds.extend({ - x: width === 0 ? 2 : 0, - y: height === 0 ? 2 : 0 - }); - this.bounds.moveBy({ - x: width === 0 ? -1 : 0, - y: height === 0 ? -1 : 0 - }); - - } - - // TODO: Bounds muss abhaengig des Eltern-Shapes gesetzt werden - var upL = this.bounds.upperLeft(); - var oldUpL = this._oldBounds.upperLeft(); - var oldWidth = this._oldBounds.width() === 0 ? this.bounds.width() : this._oldBounds.width(); - var oldHeight = this._oldBounds.height() === 0 ? this.bounds.height() : this._oldBounds.height(); - var diffX = upL.x - oldUpL.x; - var diffY = upL.y - oldUpL.y; - var diffWidth = (this.bounds.width() / oldWidth) || 1; - var diffHeight = (this.bounds.height() / oldHeight) || 1; - - this.dockers.each((function(docker){ - // Unregister on BoundsChangedCallback - docker.bounds.unregisterCallback(this._dockerChangedCallback); - - // If there is any changes at the edge and is there is not an DockersUpdate - // set the new bounds to the docker - if (!this._dockerUpdated) { - docker.bounds.moveBy(diffX, diffY); - - if (diffWidth !== 1 || diffHeight !== 1) { - var relX = docker.bounds.upperLeft().x - upL.x; - var relY = docker.bounds.upperLeft().y - upL.y; - - docker.bounds.moveTo(upL.x + relX * diffWidth, upL.y + relY * diffHeight); - } - } - // Do Docker update and register on DockersBoundChange - docker.update(); - docker.bounds.registerCallback(this._dockerChangedCallback); - - }).bind(this)); - - if (this._dockerUpdated) { - var a = this.dockers.first().bounds.center(); - var b = this.dockers.first().bounds.center(); - - this.dockers.each((function(docker){ - var center = docker.bounds.center(); - a.x = Math.min(a.x, center.x); - a.y = Math.min(a.y, center.y); - b.x = Math.max(b.x, center.x); - b.y = Math.max(b.y, center.y); - }).bind(this)); - - //set the bounds of the the association - this.bounds.set(Object.clone(a), Object.clone(b)); - } - - upL = this.bounds.upperLeft(); oldUpL = this._oldBounds.upperLeft(); - diffWidth = (this.bounds.width() / (oldWidth||this.bounds.width())); diffHeight = (this.bounds.height() / (oldHeight||this.bounds.height())); - diffX = upL.x - oldUpL.x; diffY = upL.y - oldUpL.y; - - //reposition labels - this.getLabels().each(function(label) { - - if (label.getReferencePoint()){ - var ref = label.getReferencePoint(); - var from = ref.segment.from, to = ref.segment.to; - if (!from || !from.parent || !to || !to.parent) { - return; - } - - var fromPosition = from.bounds.center(), toPosition = to.bounds.center(); + ; + + // Start Dragging + this.dragEnable = true; + this.dragIntialized = true; + this.edgesMovable = true; + + // Calculate the current zoom factor + var a = this.facade.getCanvas().node.getScreenCTM(); + this.faktorXY.x = a.a; + this.faktorXY.y = a.d; + + var eventX = Event.pointerX(event); + var eventY = Event.pointerY(event); + + // Set the offset position of dragging + var upL = this.dragBounds.upperLeft(); + this.offSetPosition = { + x: eventX - (upL.x * this.faktorXY.x), + y: eventY - (upL.y * this.faktorXY.y) + }; - if (fromPosition.x === ref.segment.fromPosition.x && fromPosition.y === ref.segment.fromPosition.y && - toPosition.x === ref.segment.toPosition.x && toPosition.y === ref.segment.toPosition.y && !ref.dirty){ - return; - } - - if (!this.parent.initializingShapes) { - var oldDistance = ORYX.Core.Math.getDistanceBetweenTwoPoints(ref.segment.fromPosition, ref.segment.toPosition, ref.intersection); - var newIntersection = ORYX.Core.Math.getPointBetweenTwoPoints(fromPosition, toPosition, isNaN(oldDistance) ? 0.5 : oldDistance); - - /** - * Set position - */ - // Get the orthogonal identity vector of the current segment - var oiv = ORYX.Core.Math.getOrthogonalIdentityVector(fromPosition, toPosition); - var isHor = Math.abs(oiv.y)===1, isVer = Math.abs(oiv.x)===1; - oiv.x *= ref.distance; oiv.y *= ref.distance; // vector * distance - oiv.x += newIntersection.x; oiv.y += newIntersection.y; // vector + the intersection point - var mx = isHor && ref.orientation && (ref.iorientation||ref.orientation).endsWith("r") ? -label.getWidth() : 0; - var my = isVer && ref.orientation && (ref.iorientation||ref.orientation).startsWith("l") ? -label.getHeight()+2 : 0; - label.setX(oiv.x+mx); label.setY(oiv.y+my); - - // Update the reference point - this.updateReferencePointOfLabel(label, newIntersection, from, to); - } else { - var oiv = ORYX.Core.Math.getOrthogonalIdentityVector(fromPosition, toPosition); - oiv.x *= ref.distance; oiv.y *= ref.distance; // vector * distance - oiv.x += ref.intersection.x; oiv.y += ref.intersection.y; // vector + the intersection point - label.setX(oiv.x); label.setY(oiv.y); - ref.segment.fromPosition = fromPosition; ref.segment.toPosition = toPosition; - } - - return; - } - - // Update label position if no reference point is set - if (label.position && !this.parent.initializingShapes){ - var x = label.position.x + (diffX * (diffWidth||1)); - if (x > this.bounds.lowerRight().x){ - x += this.bounds.width()-(this.bounds.width()/(diffWidth||1)); - } - - var y = label.position.y + (diffY * (diffHeight||1)); - if (y > this.bounds.lowerRight().y){ - y += this.bounds.height()-(this.bounds.height()/(diffHeight||1)); - } - label.setX(x);label.setY(y); - return; - } - - switch (label.getEdgePosition()) { - case "starttop": - var angle = this._getAngle(this.dockers[0], this.dockers[1]); - var pos = this.dockers.first().bounds.center(); - - if (angle <= 90 || angle > 270) { - label.horizontalAlign("left"); - label.verticalAlign("bottom"); - label.x = pos.x + label.getOffsetTop(); - label.y = pos.y - label.getOffsetTop(); - label.rotate(360 - angle, pos); - } else { - label.horizontalAlign("right"); - label.verticalAlign("bottom"); - label.x = pos.x - label.getOffsetTop(); - label.y = pos.y - label.getOffsetTop(); - label.rotate(180 - angle, pos); - } - - break; - - case "startmiddle": - var angle = this._getAngle(this.dockers[0], this.dockers[1]); - var pos = this.dockers.first().bounds.center(); - - if (angle <= 90 || angle > 270) { - label.horizontalAlign("left"); - label.verticalAlign("bottom"); - label.x = pos.x + 2; - label.y = pos.y + 4; - label.rotate(360 - angle, pos); - } else { - label.horizontalAlign("right"); - label.verticalAlign("bottom"); - label.x = pos.x + 1; - label.y = pos.y + 4; - label.rotate(180 - angle, pos); - } - - break; - - case "startbottom": - var angle = this._getAngle(this.dockers[0], this.dockers[1]); - var pos = this.dockers.first().bounds.center(); - - if (angle <= 90 || angle > 270) { - label.horizontalAlign("left"); - label.verticalAlign("top"); - label.x = pos.x + label.getOffsetBottom(); - label.y = pos.y + label.getOffsetBottom(); - label.rotate(360 - angle, pos); - } else { - label.horizontalAlign("right"); - label.verticalAlign("top"); - label.x = pos.x - label.getOffsetBottom(); - label.y = pos.y + label.getOffsetBottom(); - label.rotate(180 - angle, pos); - } - - break; - case "midtop": - var numOfDockers = this.dockers.length; - if(numOfDockers%2 == 0) { - var angle = this._getAngle(this.dockers[numOfDockers/2-1], this.dockers[numOfDockers/2]) - var pos1 = this.dockers[numOfDockers/2-1].bounds.center(); - var pos2 = this.dockers[numOfDockers/2].bounds.center(); - var pos = {x:(pos1.x + pos2.x)/2.0, y:(pos1.y+pos2.y)/2.0}; - - label.horizontalAlign("center"); - label.verticalAlign("bottom"); - label.x = pos.x; - label.y = pos.y - label.getOffsetTop(); - - if (angle <= 90 || angle > 270) { - label.rotate(360 - angle, pos); - } else { - label.rotate(180 - angle, pos); - } - } else { - var index = parseInt(numOfDockers/2); - var angle = this._getAngle(this.dockers[index], this.dockers[index+1]) - var pos = this.dockers[index].bounds.center(); - - if (angle <= 90 || angle > 270) { - label.horizontalAlign("left"); - label.verticalAlign("bottom"); - label.x = pos.x + label.getOffsetTop(); - label.y = pos.y - label.getOffsetTop(); - label.rotate(360 - angle, pos); - } else { - label.horizontalAlign("right"); - label.verticalAlign("bottom"); - label.x = pos.x - label.getOffsetTop(); - label.y = pos.y - label.getOffsetTop(); - label.rotate(180 - angle, pos); - } - } - - break; - case "midbottom": - var numOfDockers = this.dockers.length; - if(numOfDockers%2 == 0) { - var angle = this._getAngle(this.dockers[numOfDockers/2-1], this.dockers[numOfDockers/2]) - var pos1 = this.dockers[numOfDockers/2-1].bounds.center(); - var pos2 = this.dockers[numOfDockers/2].bounds.center(); - var pos = {x:(pos1.x + pos2.x)/2.0, y:(pos1.y+pos2.y)/2.0}; - - label.horizontalAlign("center"); - label.verticalAlign("top"); - label.x = pos.x; - label.y = pos.y + label.getOffsetTop(); - - if (angle <= 90 || angle > 270) { - label.rotate(360 - angle, pos); - } else { - label.rotate(180 - angle, pos); - } - } else { - var index = parseInt(numOfDockers/2); - var angle = this._getAngle(this.dockers[index], this.dockers[index+1]) - var pos = this.dockers[index].bounds.center(); - - if (angle <= 90 || angle > 270) { - label.horizontalAlign("left"); - label.verticalAlign("top"); - label.x = pos.x + label.getOffsetBottom(); - label.y = pos.y + label.getOffsetBottom(); - label.rotate(360 - angle, pos); - } else { - label.horizontalAlign("right"); - label.verticalAlign("top"); - label.x = pos.x - label.getOffsetBottom(); - label.y = pos.y + label.getOffsetBottom(); - label.rotate(180 - angle, pos); - } - } - - break; - case "endtop": - var length = this.dockers.length; - var angle = this._getAngle(this.dockers[length-2], this.dockers[length-1]); - var pos = this.dockers.last().bounds.center(); - - if (angle <= 90 || angle > 270) { - label.horizontalAlign("right"); - label.verticalAlign("bottom"); - label.x = pos.x - label.getOffsetTop(); - label.y = pos.y - label.getOffsetTop(); - label.rotate(360 - angle, pos); - } else { - label.horizontalAlign("left"); - label.verticalAlign("bottom"); - label.x = pos.x + label.getOffsetTop(); - label.y = pos.y - label.getOffsetTop(); - label.rotate(180 - angle, pos); - } - - break; - case "endbottom": - var length = this.dockers.length; - var angle = this._getAngle(this.dockers[length-2], this.dockers[length-1]); - var pos = this.dockers.last().bounds.center(); - - if (angle <= 90 || angle > 270) { - label.horizontalAlign("right"); - label.verticalAlign("top"); - label.x = pos.x - label.getOffsetBottom(); - label.y = pos.y + label.getOffsetBottom(); - label.rotate(360 - angle, pos); - } else { - label.horizontalAlign("left"); - label.verticalAlign("top"); - label.x = pos.x + label.getOffsetBottom(); - label.y = pos.y + label.getOffsetBottom(); - label.rotate(180 - angle, pos); - } - - break; - } - }.bind(this)); - - this.children.each(function(value) { - if(value instanceof ORYX.Core.Node) { - this.calculatePositionOfAttachedChildNode.call(this, value); - } - }.bind(this)); - - this.refreshAttachedNodes(); - this.refresh(); - - this.isChanged = false; - this._dockerUpdated = false; - - this._oldBounds = this.bounds.clone(); - } - - - // IE10 specific fix, start and end-markes get left behind when moving path - var userAgent = navigator.userAgent; - if (navigator.appVersion.indexOf("MSIE 10") !== -1 || (userAgent.indexOf('Trident') !== -1 && userAgent.indexOf('rv:11') !== -1)) - { - this.node.parentNode.insertBefore(this.node, this.node); - } + this.offsetScroll = {x: this.scrollNode.scrollLeft, y: this.scrollNode.scrollTop}; + + // Register on Global Mouse-MOVE Event + document.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, this.callbackMouseMove, false); + // Register on Global Mouse-UP Event + document.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEUP, this.callbackMouseUp, true); + + return; }, - - /** - * Moves a point to the upperLeft of a node's bounds. - * - * @param {point} point - * The point to move - * @param {ORYX.Core.Bounds} bounds - * The Bounds of the related noe - */ - movePointToUpperLeftOfNode: function(point, bounds) { - point.x -= bounds.width()/2; - point.y -= bounds.height()/2; - }, - - /** - * Refreshes the visual representation of edge's attached nodes. - */ - refreshAttachedNodes: function() { - this.attachedNodePositionData.values().each(function(nodeData) { - var startPoint = nodeData.segment.docker1.bounds.center(); - var endPoint = nodeData.segment.docker2.bounds.center(); - this.relativizePoint(startPoint); - this.relativizePoint(endPoint); - - var newNodePosition = new Object(); - - /* Calculate new x-coordinate */ - newNodePosition.x = startPoint.x - + nodeData.relativDistanceFromDocker1 - * (endPoint.x - startPoint.x); - - /* Calculate new y-coordinate */ - newNodePosition.y = startPoint.y - + nodeData.relativDistanceFromDocker1 - * (endPoint.y - startPoint.y); - - /* Convert new position to the upper left of the node */ - this.movePointToUpperLeftOfNode(newNodePosition, nodeData.node.bounds); - - /* Move node to its new position */ - nodeData.node.bounds.moveTo(newNodePosition); - nodeData.node._update(); - - }.bind(this)); - }, - - /** - * Calculates the position of an edge's child node. The node is placed on - * the path of the edge. - * - * @param {node} - * The node to calculate the new position - * @return {Point} - * The calculated upper left point of the node's shape. - */ - calculatePositionOfAttachedChildNode: function(node) { - /* Initialize position */ - var position = new Object(); - position.x = 0; - position.y = 0; - - /* Case: Node was just added */ - if(!this.attachedNodePositionData[node.getId()]) { - this.attachedNodePositionData[node.getId()] = new Object(); - this.attachedNodePositionData[node.getId()] - .relativDistanceFromDocker1 = 0; - this.attachedNodePositionData[node.getId()].node = node; - this.attachedNodePositionData[node.getId()].segment = new Object(); - this.findEdgeSegmentForNode(node); - }else if(node.isChanged) { - this.findEdgeSegmentForNode(node); - } - - - - }, - - /** - * Finds the appropriate edge segement for a node. - * The segment is choosen, which has the smallest distance to the node. - * - * @param {ORYX.Core.Node} node - * The concerning node - */ - findEdgeSegmentForNode: function(node) { - var length = this.dockers.length; - var smallestDistance = undefined; - - for(i=1;i 0) { + + // Get the position and the docker + var position = this.facade.eventCoordinates(event); + var docker = this.toMoveShapes[0].dockers[0]; + + + //Command-Pattern for dragging several Shapes + var dockCommand = ORYX.Core.Command.extend({ + construct: function (docker, position, newDockedShape, facade) { + this.docker = docker; + this.newPosition = position; + this.newDockedShape = newDockedShape; + this.newParent = newDockedShape.parent || facade.getCanvas(); + this.oldPosition = docker.parent.bounds.center(); + this.oldDockedShape = docker.getDockedShape(); + this.oldParent = docker.parent.parent || facade.getCanvas(); + this.facade = facade; + + if (this.oldDockedShape) { + this.oldPosition = docker.parent.absoluteBounds().center(); + } + + }, + execute: function () { + this.dock(this.newDockedShape, this.newParent, this.newPosition); + + // Raise Event for having the docked shape on top of the other shape + this.facade.raiseEvent({type: ORYX.CONFIG.EVENT_ARRANGEMENT_TOP, excludeCommand: true}) + }, + rollback: function () { + this.dock(this.oldDockedShape, this.oldParent, this.oldPosition); + }, + dock: function (toDockShape, parent, pos) { + // Add to the same parent Shape + parent.add(this.docker.parent) + + + // Set the Docker to the new Shape + this.docker.setDockedShape(undefined); + this.docker.bounds.centerMoveTo(pos) + this.docker.setDockedShape(toDockShape); + //this.docker.update(); + + this.facade.setSelection([this.docker.parent]); + this.facade.getCanvas().update(); + this.facade.updateSelection(); + + + } + }); + + // Instanziate the dockCommand + var commands = [new dockCommand(docker, position, this.containmentParentNode, this.facade)]; + this.facade.executeCommands(commands); + + + // Check if adding is allowed to the other Shape + } else if (this.isAddingAllowed) { + + + // Refresh all Shapes --> Set the new Bounds + this.refreshSelectedShapes(); + + } + + this.facade.updateSelection(); + + //this.currentShapes.each(function(shape) {shape.update()}) + // Raise Event: Dragging is finished + this.facade.raiseEvent({type: ORYX.CONFIG.EVENT_DRAGDROP_END}); } - - path.setAttributeNS(null, "d", d); - this._interactionPaths[index].setAttributeNS(null, "d", d); - - }).bind(this)); - - - /* move child shapes of an edge */ - if(this.getChildNodes().length > 0) { - var x = this.bounds.upperLeft().x; - var y = this.bounds.upperLeft().y; - - this.node.firstChild.childNodes[1].setAttributeNS(null, "transform", "translate(" + x + ", " + y + ")"); - } - + + if (this.vLine) + this.vLine.hide(); + if (this.hLine) + this.hLine.hide(); + } + + // Disable + this.dragEnable = false; + + + // UnRegister on Global Mouse-UP/-Move Event + document.documentElement.removeEventListener(ORYX.CONFIG.EVENT_MOUSEUP, this.callbackMouseUp, true); + document.documentElement.removeEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, this.callbackMouseMove, false); + + return; }, - + /** - * Calculate the Border Intersection Point between two points - * @param {PointA} - * @param {PointB} - */ - getIntersectionPoint: function(){ - - var length = Math.floor(this.dockers.length / 2) - - return ORYX.Core.Math.midPoint(this.dockers[length - 1].bounds.center(), this.dockers[length].bounds.center()) - }, - - /** - * Returns TRUE if the bounds is over the edge - * @param {Bounds} + * On Key Mouse Move * */ - isBoundsIncluded: function(bounds){ - var dockers = this.dockers, size = dockers.length; - return dockers.any(function(docker, i){ - if (i == size-1){ return false; } - var a = docker.bounds.center(); - var b = dockers[i+1].bounds.center(); - - return ORYX.Core.Math.isRectOverLine(a.x, a.y, b.x, b.y, bounds.a.x, bounds.a.y, bounds.b.x, bounds.b.y); - }); - }, - - /** - * Calculate if the point is inside the Shape - * @param {PointX} - * @param {PointY} - */ - isPointIncluded: function(pointX, pointY){ - - var isbetweenAB = this.absoluteBounds().isIncluded(pointX, pointY, - ORYX.CONFIG.OFFSET_EDGE_BOUNDS); - - var isPointIncluded = undefined; - - if (isbetweenAB && this.dockers.length > 0) { - - var i = 0; - var point1, point2; - - - do { - - point1 = this.dockers[i].bounds.center(); - point2 = this.dockers[++i].bounds.center(); - - isPointIncluded = ORYX.Core.Math.isPointInLine(pointX, pointY, - point1.x, point1.y, - point2.x, point2.y, - ORYX.CONFIG.OFFSET_EDGE_BOUNDS); - - } while (!isPointIncluded && i < this.dockers.length - 1) - - } - - return isPointIncluded; + handleMouseMove: function (event) { + // If dragging is not enabled, go return + if (!this.dragEnable) { + return + } + ; + // If Dragging is initialized + if (this.dragIntialized) { + // Raise Event: Drag will be started + this.facade.raiseEvent({type: ORYX.CONFIG.EVENT_DRAGDROP_START}); + this.dragIntialized = false; + + // And hide the resizers and the highlighting + this.resizerSE.hide(); + this.resizerNW.hide(); + + // if only edges are selected, containmentParentNode must be the canvas + this._onlyEdges = this.currentShapes.all(function (currentShape) { + return (currentShape instanceof ORYX.Core.Edge); + }); + + // Do method before Drag + this.beforeDrag(); + + this._currentUnderlyingNodes = []; + + } + + + // Calculate the new position + var position = { + x: Event.pointerX(event) - this.offSetPosition.x, + y: Event.pointerY(event) - this.offSetPosition.y + } + + position.x -= this.offsetScroll.x - this.scrollNode.scrollLeft; + position.y -= this.offsetScroll.y - this.scrollNode.scrollTop; + + // If not the Control-Key are pressed + var modifierKeyPressed = event.shiftKey || event.ctrlKey; + if (ORYX.CONFIG.GRID_ENABLED && !modifierKeyPressed) { + // Snap the current position to the nearest Snap-Point + position = this.snapToGrid(position); + } else { + if (this.vLine) + this.vLine.hide(); + if (this.hLine) + this.hLine.hide(); + } + + // Adjust the point by the zoom faktor + position.x /= this.faktorXY.x; + position.y /= this.faktorXY.y; + + // Set that the position is not lower than zero + position.x = Math.max(0, position.x) + position.y = Math.max(0, position.y) + + // Set that the position is not bigger than the canvas + var c = this.facade.getCanvas(); + position.x = Math.min(c.bounds.width() - this.dragBounds.width(), position.x) + position.y = Math.min(c.bounds.height() - this.dragBounds.height(), position.y) + + + // Drag this bounds + this.dragBounds.moveTo(position); + + // Update all selected shapes and the selection rectangle + //this.refreshSelectedShapes(); + this.resizeRectangle(this.dragBounds); + + this.isAttachingAllowed = false; + + //check, if a node can be added to the underlying node + var eventCoordinates = this.facade.eventCoordinates(event); + + var additionalIEZoom = 1; + if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) { + var ua = navigator.userAgent; + if (ua.indexOf('MSIE') >= 0) { + //IE 10 and below + var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100); + if (zoom !== 100) { + additionalIEZoom = zoom / 100 + } + } + } + + if (additionalIEZoom !== 1) { + eventCoordinates.x = eventCoordinates.x / additionalIEZoom; + eventCoordinates.y = eventCoordinates.y / additionalIEZoom; + } + + var underlyingNodes = $A(this.facade.getCanvas().getAbstractShapesAtPosition(eventCoordinates)); + + var checkIfAttachable = this.toMoveShapes.length == 1 && this.toMoveShapes[0] instanceof ORYX.Core.Node && this.toMoveShapes[0].dockers.length > 0 + checkIfAttachable = checkIfAttachable && underlyingNodes.length != 1 + + + if (!checkIfAttachable && + underlyingNodes.length === this._currentUnderlyingNodes.length && + underlyingNodes.all(function (node, index) { + return this._currentUnderlyingNodes[index] === node + }.bind(this))) { + + return + + } else if (this._onlyEdges) { + + this.isAddingAllowed = true; + this.containmentParentNode = this.facade.getCanvas(); + + } else { + + /* Check the containment and connection rules */ + var options = { + event: event, + underlyingNodes: underlyingNodes, + checkIfAttachable: checkIfAttachable + }; + this.checkRules(options); + + } + + this._currentUnderlyingNodes = underlyingNodes.reverse(); + + //visualize the containment result + 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" + }); + } + + // Stop the Event + //Event.stop(event); + return; }, - - + +// /** +// * Rollbacks the docked shape of an edge, if the edge is not movable. +// */ +// redockEdges: function() { +// this._undockedEdgesCommand.dockers.each(function(el){ +// el.docker.setDockedShape(el.dockedShape); +// el.docker.setReferencePoint(el.refPoint); +// }) +// }, + /** - * Calculate if the point is over an special offset area - * @param {Point} + * Checks the containment and connection rules for the selected shapes. */ - isPointOverOffset: function(){ - return false - }, - - /** - * Returns TRUE if the given node - * is a child node of the shapes node - * @param {Element} node - * @return {Boolean} - * - */ - containsNode: function(node){ - if (this._paths.include(node) || - this._interactionPaths.include(node)){ - return true; - } - return false; - }, - - /** - * Returns the angle of the line between two dockers - * (0 - 359.99999999) - */ - _getAngle: function(docker1, docker2) { - var p1 = docker1 instanceof ORYX.Core.Controls.Docker ? docker1.absoluteCenterXY() : docker1; - var p2 = docker2 instanceof ORYX.Core.Controls.Docker ? docker2.absoluteCenterXY() : docker2; - - return ORYX.Core.Math.getAngle(p1, p2); - }, - - alignDockers: function(){ - this._update(true); - - var firstPoint = this.dockers.first().bounds.center(); - var lastPoint = this.dockers.last().bounds.center(); - - var deltaX = lastPoint.x - firstPoint.x; - var deltaY = lastPoint.y - firstPoint.y; - - var numOfDockers = this.dockers.length - 1; - - this.dockers.each((function(docker, index){ - var part = index / numOfDockers; - docker.bounds.unregisterCallback(this._dockerChangedCallback); - docker.bounds.moveTo(firstPoint.x + part * deltaX, firstPoint.y + part * deltaY); - docker.bounds.registerCallback(this._dockerChangedCallback); + checkRules: function (options) { + var event = options.event; + var underlyingNodes = options.underlyingNodes; + var checkIfAttachable = options.checkIfAttachable; + var noEdges = options.noEdges; + + //get underlying node that is not the same than one of the currently selected shapes or + // a child of one of the selected shapes with the highest z Order. + // The result is a shape or the canvas + this.containmentParentNode = underlyingNodes.reverse().find((function (node) { + return (node instanceof ORYX.Core.Canvas) || + (((node instanceof ORYX.Core.Node) || ((node instanceof ORYX.Core.Edge) && !noEdges)) + && (!(this.currentShapes.member(node) || + this.currentShapes.any(function (shape) { + return (shape.children.length > 0 && shape.getChildNodes(true).member(node)); + })))); }).bind(this)); - - this._dockerChanged(); - }, - - add: function(shape){ - arguments.callee.$.add.apply(this, arguments); - - // If the new shape is a Docker which is not contained - if (shape instanceof ORYX.Core.Controls.Docker && this.dockers.include(shape)){ - // Add it to the dockers list ordered by paths - var pathArray = this._dockersByPath.values()[0]; - if (pathArray) { - pathArray.splice(this.dockers.indexOf(shape), 0, shape); - } - - /* Perform nessary adjustments on the edge's child shapes */ - this.handleChildShapesAfterAddDocker(shape); - } - }, - - /** - * Performs nessary adjustments on the edge's child shapes. - * - * @param {ORYX.Core.Controls.Docker} docker - * The added docker - */ - handleChildShapesAfterAddDocker: function(docker) { - /* Ensure type of Docker */ - if(!docker instanceof ORYX.Core.Controls.Docker) {return undefined;} - - var index = this.dockers.indexOf(docker); - if(!(0 < index && index < this.dockers.length - 1)) { - /* Exception: Expect added docker between first and last node of the edge */ - return undefined; - } - - /* Get child nodes concerning the segment of the new docker */ - var startDocker = this.dockers[index-1]; - var endDocker = this.dockers[index+1]; - - /* Adjust the position of edge's child nodes */ - var segmentElements = - this.getAttachedNodePositionDataForSegment(startDocker, endDocker); - - var lengthSegmentPart1 = ORYX.Core.Math.getDistancePointToPoint( - startDocker.bounds.center(), - docker.bounds.center()); - var lengthSegmentPart2 = ORYX.Core.Math.getDistancePointToPoint( - endDocker.bounds.center(), - docker.bounds.center()); - - if(!(lengthSegmentPart1 + lengthSegmentPart2)) {return;} - - var relativDockerPosition = lengthSegmentPart1 / (lengthSegmentPart1 + lengthSegmentPart2); - - segmentElements.each(function(nodePositionData) { - /* Assign child node to the new segment */ - if(nodePositionData.value.relativDistanceFromDocker1 < relativDockerPosition) { - /* Case: before added Docker */ - nodePositionData.value.segment.docker2 = docker; - nodePositionData.value.relativDistanceFromDocker1 = - nodePositionData.value.relativDistanceFromDocker1 / relativDockerPosition; - } else { - /* Case: after added Docker */ - nodePositionData.value.segment.docker1 = docker; - var newFullDistance = 1 - relativDockerPosition; - var relativPartOfSegment = - nodePositionData.value.relativDistanceFromDocker1 - - relativDockerPosition; - - nodePositionData.value.relativDistanceFromDocker1 = - relativPartOfSegment / newFullDistance; - - } - }) - - - // Update all labels reference points - this.getLabels().each(function(label){ - - var ref = label.getReferencePoint(); - if (!ref) { - return; - } - var index = this.dockers.indexOf(docker); - if (index >= ref.segment.fromIndex && index <= ref.segment.toIndex){ - - var segment = this.findSegment(ref.intersection); - if (!segment){ - // Choose whether the first of the last segment - segment.fromDocker = ref.segment.fromIndex >= (this.dockers.length/2) ? this.dockers[0] : this.dockers[this.dockers.length-2]; - segment.toDocker = this.dockers[this.dockers.indexOf(from)+1]; // The next one if the to docker - } - - var fromPosition = segment.fromDocker.bounds.center(), toPosition = segment.toDocker.bounds.center(); - - var intersection = ORYX.Core.Math.getPointOfIntersectionPointLine( - fromPosition, // P1 - Center of the first docker - toPosition, // P2 - Center of the second docker - ref.intersection, // P3 - Center of the label - true); - //var oldDistance = ORYX.Core.Math.getDistanceBetweenTwoPoints(ref.segment.fromPosition, ref.segment.toPosition, ref.intersection); - //intersection = ORYX.Core.Math.getPointBetweenTwoPoints(fromPosition, toPosition, isNaN(oldDistance) ? 0.5 : (lengthOld*oldDistance)/lengthNew); - - // Update the reference point - this.updateReferencePointOfLabel(label, intersection, segment.fromDocker, segment.toDocker, true); - } - }.bind(this)); - - /* Update attached nodes visual representation */ - this.refreshAttachedNodes(); - }, - - /** - * Returns elements from {@link attachedNodePositiondata} that match the - * segement defined by startDocker and endDocker. - * - * @param {ORYX.Core.Controls.Docker} startDocker - * The docker defining the begin of the segment. - * @param {ORYX.Core.Controls.Docker} endDocker - * The docker defining the begin of the segment. - * - * @return {Hash} attachedNodePositionData - * Child elements matching the segment - */ - getAttachedNodePositionDataForSegment: function(startDocker, endDocker) { - /* Ensure that the segment is defined correctly */ - if(!((startDocker instanceof ORYX.Core.Controls.Docker) - && (endDocker instanceof ORYX.Core.Controls.Docker))) { - return []; - } - - /* Get elements of the segment */ - var elementsOfSegment = - this.attachedNodePositionData.findAll(function(nodePositionData) { - return nodePositionData.value.segment.docker1 === startDocker && - nodePositionData.value.segment.docker2 === endDocker; - }); - - /* Return a Hash in each case */ - if(!elementsOfSegment) {return [];} - - return elementsOfSegment; - }, - - /** - * Removes an edge's child shape - */ - remove: function(shape) { - arguments.callee.$.remove.apply(this, arguments); - - if(this.attachedNodePositionData[shape.getId()]) { - delete this.attachedNodePositionData[shape.getId()]; - } - - /* Adjust child shapes if neccessary */ - if(shape instanceof ORYX.Core.Controls.Docker) { - this.handleChildShapesAfterRemoveDocker(shape); - } - }, - - updateReferencePointOfLabel: function(label, intersection, from, to, dirty){ - if (!label.getReferencePoint() || !label.isVisible) { - return; - } - - var ref = label.getReferencePoint(); - - // - if (ref.orientation && ref.orientation !== "ce"){ - var angle = this._getAngle(from, to); - if (ref.distance >= 0){ - if(angle == 0){ - label.horizontalAlign("left");//ref.orientation == "lr" ? "right" : "left"); - label.verticalAlign("bottom"); - } else if (angle > 0 && angle < 90){ - label.horizontalAlign("right"); - label.verticalAlign("bottom"); - } else if (angle == 90){ - label.horizontalAlign("right"); - label.verticalAlign("top");//ref.orientation == "lr" ? "bottom" : "top"); - } else if (angle > 90 && angle < 180){ - label.horizontalAlign("right"); - label.verticalAlign("top"); - } else if (angle == 180){ - label.horizontalAlign("left");//ref.orientation == "ur" ? "right" : "left"); - label.verticalAlign("top"); - } else if (angle > 180 && angle < 270){ - label.horizontalAlign("left"); - label.verticalAlign("top"); - } else if (angle == 270){ - label.horizontalAlign("left"); - label.verticalAlign("top");//ref.orientation == "ll" ? "bottom" : "top"); - } else if (angle > 270 && angle <= 360){ - label.horizontalAlign("left"); - label.verticalAlign("bottom"); - } - } else { - if(angle == 0){ - label.horizontalAlign("left");//ref.orientation == "ur" ? "right" : "left"); - label.verticalAlign("top"); - } else if (angle > 0 && angle < 90){ - label.horizontalAlign("left"); - label.verticalAlign("top"); - } else if (angle == 90){ - label.horizontalAlign("left"); - label.verticalAlign("top");//ref.orientation == "ll" ? "bottom" : "top"); - } else if (angle > 90 && angle < 180){ - label.horizontalAlign("left"); - label.verticalAlign("bottom"); - } else if (angle == 180){ - label.horizontalAlign("left");//ref.orientation == "lr" ? "right" : "left"); - label.verticalAlign("bottom"); - } else if (angle > 180 && angle < 270){ - label.horizontalAlign("right"); - label.verticalAlign("bottom"); - } else if (angle == 270){ - label.horizontalAlign("right"); - label.verticalAlign("top");//ref.orientation == "lr" ? "bottom" : "top"); - } else if (angle > 270 && angle <= 360){ - label.horizontalAlign("right"); - label.verticalAlign("top"); - } - } - ref.iorientation = ref.iorientation || ref.orientation; - ref.orientation = (label.verticalAlign()=="top"?"u":"l") + (label.horizontalAlign()=="left"?"l":"r"); - } - - label.setReferencePoint(jQuery.extend({},{ - intersection: intersection, - segment: { - from: from, - fromIndex: this.dockers.indexOf(from), - fromPosition: from.bounds.center(), - to: to, - toIndex: this.dockers.indexOf(to), - toPosition: to.bounds.center() - }, - dirty: dirty || false - },ref)) - }, - /** - * Adjusts the child shapes of an edges after a docker was removed. - * - * @param{ORYX.Core.Controls.Docker} docker - * The removed docker. - */ - handleChildShapesAfterRemoveDocker: function(docker) { - /* Ensure docker type */ - if(!(docker instanceof ORYX.Core.Controls.Docker)) {return;} - - this.attachedNodePositionData.each(function(nodePositionData) { - if(nodePositionData.value.segment.docker1 === docker) { - /* The new start of the segment is the predecessor of docker2. */ - var index = this.dockers.indexOf(nodePositionData.value.segment.docker2); - if(index == -1) {return;} - nodePositionData.value.segment.docker1 = this.dockers[index - 1]; - } - else if(nodePositionData.value.segment.docker2 === docker) { - /* The new end of the segment is the successor of docker1. */ - var index = this.dockers.indexOf(nodePositionData.value.segment.docker1); - if(index == -1) {return;} - nodePositionData.value.segment.docker2 = this.dockers[index + 1]; - } - }.bind(this)); - - // Update all labels reference points - this.getLabels().each(function(label){ - var ref = label.getReferencePoint(); - if (!ref) { - return; - } - var from = ref.segment.from; - var to = ref.segment.to; - - if (from !== docker && to !== docker){ - return; - } - - var segment = this.findSegment(ref.intersection); - if (!segment){ - from = segment.fromDocker; - to = segment.toDocker; - } else { - from = from === docker ? this.dockers[this.dockers.indexOf(to)-1] : from; - to = this.dockers[this.dockers.indexOf(from)+1]; - } + if (checkIfAttachable) { - var intersection = ORYX.Core.Math.getPointOfIntersectionPointLine(from.bounds.center(), to.bounds.center(), ref.intersection, true); - // Update the reference point - this.updateReferencePointOfLabel(label, intersection, from, to, true); - }.bind(this)); - - /* Update attached nodes visual representation */ - this.refreshAttachedNodes(); - }, - - /** - *@deprecated Use the .createDocker() Method and set the point via the bounds - */ - addDocker: function(position, exDocker){ - var lastDocker; - var result; - this._dockersByPath.any((function(pair){ - return pair.value.any((function(docker, index){ - if (!lastDocker) { - lastDocker = docker; - return false; - } - else { - var point1 = lastDocker.bounds.center(); - var point2 = docker.bounds.center(); - - var additionalIEZoom = 1; - if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) { - var ua = navigator.userAgent; - if (ua.indexOf('MSIE') >= 0) { - //IE 10 and below - var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100); - if (zoom !== 100) { - additionalIEZoom = zoom / 100 - } - } - } - - if (additionalIEZoom !== 1) { - position.x = position.x / additionalIEZoom; - position.y = position.y / additionalIEZoom; - } - - if (ORYX.Core.Math.isPointInLine(position.x, position.y, point1.x, point1.y, point2.x, point2.y, 10)) { - var path = this._paths.find(function(path){ - return path.id === pair.key; - }); - if (path) { - var allowAttr = path.getAttributeNS(NAMESPACE_ORYX, 'allowDockers'); - if (allowAttr && allowAttr.toLowerCase() === "no") { - return true; - } + this.isAttachingAllowed = this.facade.getRules().canConnect({ + sourceShape: this.containmentParentNode, + edgeShape: this.toMoveShapes[0], + targetShape: this.toMoveShapes[0] + }); + + if (this.isAttachingAllowed) { + var point = this.facade.eventCoordinates(event); + this.isAttachingAllowed = this.containmentParentNode.isPointOverOffset(point.x, point.y); + } + } + + if (!this.isAttachingAllowed) { + //check all selected shapes, if they can be added to containmentParentNode + this.isAddingAllowed = this.toMoveShapes.all((function (currentShape) { + if (currentShape instanceof ORYX.Core.Edge || + currentShape instanceof ORYX.Core.Controls.Docker || + this.containmentParentNode === currentShape.parent) { + return true; + } else if (this.containmentParentNode !== currentShape) { + + if (!(this.containmentParentNode instanceof ORYX.Core.Edge) || !noEdges) { + + if (this.facade.getRules().canContain({ + containingShape: this.containmentParentNode, + containedShape: currentShape + })) { + return true; } - - var newDocker = (exDocker) ? exDocker : this.createDocker(this.dockers.indexOf(lastDocker) + 1, position); - newDocker.bounds.centerMoveTo(position); - if(exDocker) - this.add(newDocker, this.dockers.indexOf(lastDocker) + 1); - result = newDocker; - return true; - } - else { - lastDocker = docker; - return false; } } + return false; }).bind(this)); - }).bind(this)); - return result; + } + + if (!this.isAttachingAllowed && !this.isAddingAllowed && + (this.containmentParentNode instanceof ORYX.Core.Edge)) { + options.noEdges = true; + options.underlyingNodes.reverse(); + this.checkRules(options); + } }, - - removeDocker: function(docker){ - if (this.dockers.length > 2 && !(this.dockers.first() === docker)) { - this._dockersByPath.any((function(pair){ - if (pair.value.member(docker)) { - if (docker === pair.value.last()) { - return true; - } - else { - this.remove(docker); - this._dockersByPath[pair.key] = pair.value.without(docker); - this.isChanged = true; - this._dockerChanged(); - return true; + + /** + * Redraw the selected Shapes. + * + */ + refreshSelectedShapes: function () { + // If the selection bounds not initialized, return + if (!this.dragBounds) { + return + } + + // Calculate the offset between the bounds and the old bounds + var upL = this.dragBounds.upperLeft(); + var oldUpL = this.oldDragBounds.upperLeft(); + var offset = { + x: upL.x - oldUpL.x, + y: upL.y - oldUpL.y + }; + + // Instanciate the dragCommand + var commands = [new ORYX.Core.Command.Move(this.toMoveShapes, offset, this.containmentParentNode, this.currentShapes, this)]; + // If the undocked edges command is setted, add this command + if (this._undockedEdgesCommand instanceof ORYX.Core.Command) { + commands.unshift(this._undockedEdgesCommand); + } + // Execute the commands + this.facade.executeCommands(commands); + + // copy the bounds to the old bounds + if (this.dragBounds) + this.oldDragBounds = this.dragBounds.clone(); + + }, + + /** + * Callback for Resize + * + */ + onResize: function (bounds) { + // If the selection bounds not initialized, return + if (!this.dragBounds) { + return + } + + this.dragBounds = bounds; + this.isResizing = true; + + // Update the rectangle + 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 Resizing finished, the Shapes will be resize + if (this.isResizing) { + + var commandClass = ORYX.Core.Command.extend({ + construct: function (shape, newBounds, plugin) { + this.shape = shape; + this.oldBounds = shape.bounds.clone(); + this.newBounds = newBounds; + this.plugin = plugin; + }, + 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 (b1, b2) { + return { + x: b2.a.x - b1.a.x, + y: b2.a.y - b1.a.y, + xs: b2.width() / b1.width(), + ys: b2.height() / b1.height() } + }, + update: function (offset) { + this.shape.getLabels().each(function (label) { + label.changed(); + }); + + var allEdges = [].concat(this.shape.getIncomingShapes()) + .concat(this.shape.getOutgoingShapes()) + // Remove all edges which are included in the selection from the list + .findAll(function (r) { + return r instanceof ORYX.Core.Edge + }.bind(this)) + + this.plugin.layoutEdges(this.shape, allEdges, offset); + + this.plugin.facade.setSelection([this.shape]); + this.plugin.facade.getCanvas().update(); + this.plugin.facade.updateSelection(); } - return false; - }).bind(this)); + }); + + var bounds = this.dragBounds.clone(); + var shape = this.currentShapes[0]; + + if (shape.parent) { + var parentPosition = shape.parent.absoluteXY(); + bounds.moveBy(-parentPosition.x, -parentPosition.y); + } + + var command = new commandClass(shape, bounds, this); + + this.facade.executeCommands([command]); + + this.isResizing = false; + + this.facade.raiseEvent({type: ORYX.CONFIG.EVENT_RESIZE_END}); } }, - - /** - * Removes all dockers from the edge which are on - * the line between two dockers - * @return {Object} Removed dockers in an indicied array - * (key is the removed position of the docker, value is docker themselve) - */ - removeUnusedDockers:function(){ - var marked = $H({}); - - this.dockers.each(function(docker, i){ - if (i==0||i==this.dockers.length-1){ return } - var previous = this.dockers[i-1]; - - /* Do not consider already removed dockers */ - if(marked.values().indexOf(previous) != -1 && this.dockers[i-2]) { - previous = this.dockers[i-2]; - } - var next = this.dockers[i+1]; - - var cp = previous.getDockedShape() && previous.referencePoint ? previous.getAbsoluteReferencePoint() : previous.bounds.center(); - var cn = next.getDockedShape() && next.referencePoint ? next.getAbsoluteReferencePoint() : next.bounds.center(); - var cd = docker.bounds.center(); - - if (ORYX.Core.Math.isPointInLine(cd.x, cd.y, cp.x, cp.y, cn.x, cn.y, 1)){ - marked[i] = docker; - } - }.bind(this)) - - marked.each(function(docker){ - this.removeDocker(docker.value); - }.bind(this)) - - if (marked.values().length > 0){ - this._update(true); - } - - return marked; - }, - + + /** - * Initializes the Edge after loading the SVG representation of the edge. - * @param {SVGDocument} svgDocument + * Prepare the Dragging + * */ - _init: function(svgDocument){ - arguments.callee.$._init.apply(this, arguments); - - var minPointX, minPointY, maxPointX, maxPointY; - - //init markers - var defs = svgDocument.getElementsByTagNameNS(NAMESPACE_SVG, "defs"); - if (defs.length > 0) { - defs = defs[0]; - var markerElements = $A(defs.getElementsByTagNameNS(NAMESPACE_SVG, "marker")); - var marker; - var me = this; - markerElements.each(function(markerElement){ - try { - marker = new ORYX.Core.SVG.SVGMarker(markerElement.cloneNode(true)); - me._markers[marker.id] = marker; - var textElements = $A(marker.element.getElementsByTagNameNS(NAMESPACE_SVG, "text")); - var label; - textElements.each(function(textElement){ - label = new ORYX.Core.SVG.Label({ - textElement: textElement, - shapeId: this.id - }); - me._labels[label.id] = label; - }); - } - catch (e) { - } - }); - } - - - var gs = svgDocument.getElementsByTagNameNS(NAMESPACE_SVG, "g"); - if (gs.length <= 0) { - throw "Edge: No g element found."; - } - var g = gs[0]; - - - g.setAttributeNS(null, "id", null); - - var isFirst = true; - - $A(g.childNodes).each((function(path, index){ - if (ORYX.Editor.checkClassType(path, SVGPathElement)) { - path = path.cloneNode(false); - - var pathId = this.id + "_" + index; - path.setAttributeNS(null, "id", pathId); - this._paths.push(path); - - //check, if markers are set and update the id - var markersByThisPath = []; - var markerUrl = path.getAttributeNS(null, "marker-start"); - - if (markerUrl && markerUrl !== "") { - markerUrl = markerUrl.strip(); - markerUrl = markerUrl.replace(/^url\(#/, ''); - - var markerStartId = this.getValidMarkerId(markerUrl); - path.setAttributeNS(null, "marker-start", "url(#" + markerStartId + ")"); - - markersByThisPath.push(this._markers[markerStartId]); - } - - markerUrl = path.getAttributeNS(null, "marker-mid"); - - if (markerUrl && markerUrl !== "") { - markerUrl = markerUrl.strip(); - markerUrl = markerUrl.replace(/^url\(#/, ''); - var markerMidId = this.getValidMarkerId(markerUrl); - path.setAttributeNS(null, "marker-mid", "url(#" + markerMidId + ")"); - - markersByThisPath.push(this._markers[markerMidId]); - } - - markerUrl = path.getAttributeNS(null, "marker-end"); - - if (markerUrl && markerUrl !== "") { - markerUrl = markerUrl.strip(); - - var markerEndId = this.getValidMarkerId(markerUrl); - path.setAttributeNS(null, "marker-end", "url(#" + markerEndId + ")"); - - markersByThisPath.push(this._markers[markerEndId]); - } - - this._markersByPath[pathId] = markersByThisPath; - - //init dockers - var parser = new PathParser(); - var handler = new ORYX.Core.SVG.PointsPathHandler(); - parser.setHandler(handler); - parser.parsePath(path); - - if (handler.points.length < 4) { - throw "Edge: Path has to have two or more points specified."; - } - - this._dockersByPath[pathId] = []; - - for (var i = 0; i < handler.points.length; i += 2) { - //handler.points.each((function(point, pIndex){ - var x = handler.points[i]; - var y = handler.points[i+1]; - if (isFirst || i > 0) { - var docker = new ORYX.Core.Controls.Docker({ - eventHandlerCallback: this.eventHandlerCallback - }); - docker.bounds.centerMoveTo(x,y); - docker.bounds.registerCallback(this._dockerChangedCallback); - this.add(docker, this.dockers.length); - - //this._dockersByPath[pathId].push(docker); - - //calculate minPoint and maxPoint - if (minPointX) { - minPointX = Math.min(x, minPointX); - minPointY = Math.min(y, minPointY); - } - else { - minPointX = x; - minPointY = y; - } - - if (maxPointX) { - maxPointX = Math.max(x, maxPointX); - maxPointY = Math.max(y, maxPointY); - } - else { - maxPointX = x; - maxPointY = y; - } - } - //}).bind(this)); - } - isFirst = false; + beforeDrag: function () { + + var undockEdgeCommand = ORYX.Core.Command.extend({ + construct: function (moveShapes) { + this.dockers = moveShapes.collect(function (shape) { + return shape instanceof ORYX.Core.Controls.Docker ? { + docker: shape, + dockedShape: shape.getDockedShape(), + refPoint: shape.referencePoint + } : undefined + }).compact(); + }, + execute: function () { + this.dockers.each(function (el) { + el.docker.setDockedShape(undefined); + }) + }, + rollback: function () { + this.dockers.each(function (el) { + el.docker.setDockedShape(el.dockedShape); + el.docker.setReferencePoint(el.refPoint); + //el.docker.update(); + }) } - }).bind(this)); - - this.bounds.set(minPointX, minPointY, maxPointX, maxPointY); - - if (false&&(this.bounds.width() === 0 || this.bounds.height() === 0)) { - var width = this.bounds.width(); - var height = this.bounds.height(); - - this.bounds.extend({ - x: width === 0 ? 2 : 0, - y: height === 0 ? 2 : 0 - }); - - this.bounds.moveBy({ - x: width === 0 ? -1 : 0, - y: height === 0 ? -1 : 0 - }); - - } - - this._oldBounds = this.bounds.clone(); - - //add paths to this.node - this._paths.reverse(); - var paths = []; - this._paths.each((function(path){ - paths.push(this.node.childNodes[0].childNodes[0].childNodes[0].appendChild(path)); - }).bind(this)); - - this._paths = paths; - - //init interaction path - this._paths.each((function(path){ - var iPath = path.cloneNode(false); - iPath.setAttributeNS(null, "id", undefined); - iPath.setAttributeNS(null, "stroke-width", 10); - iPath.setAttributeNS(null, "visibility", "hidden"); - iPath.setAttributeNS(null, "stroke-dasharray", null); - iPath.setAttributeNS(null, "stroke", "black"); - iPath.setAttributeNS(null, "fill", "none"); - iPath.setAttributeNS(null, "title", this.getStencil().title()); - this._interactionPaths.push(this.node.childNodes[0].childNodes[0].childNodes[0].appendChild(iPath)); - }).bind(this)); - - this._paths.reverse(); - this._interactionPaths.reverse(); - - /**initialize labels*/ - var textElems = svgDocument.getElementsByTagNameNS(ORYX.CONFIG.NAMESPACE_SVG, 'text'); - - $A(textElems).each((function(textElem){ - var label = new ORYX.Core.SVG.Label({ - textElement: textElem, - shapeId: this.id - }); - this.node.childNodes[0].childNodes[0].appendChild(label.node); - this._labels[label.id] = label; - - label.registerOnChange(this.layout.bind(this)); - }).bind(this)); - - - this.propertiesChanged.each(function(pair){ - pair.value = true; }); - - - //if(this.dockers.length == 2) { - - - - // } - - //this._update(true); + + this._undockedEdgesCommand = new undockEdgeCommand(this.toMoveShapes); + this._undockedEdgesCommand.execute(); + }, - - getValidMarkerId: function(markerUrl) { - if(markerUrl.indexOf("url(\"#") >= 0) { - // Fix for IE9, additional quotes are added to the 0) { + labels.each(function (label) { + label.hide(); + }); + } + }); + + // Do this recursive for all child shapes + // EXP-NICO use getShapes + shape.getChildren().each((function (value) { + if (value instanceof ORYX.Core.Shape) + this.hideAllLabels(value); + }).bind(this)); }, - + /** - * Adds all necessary markers of this Edge to the SVG document. - * Has to be called, while this.node is part of DOM. + * Finished the Dragging + * */ - addMarkers: function(defs){ - this._markers.each(function(marker){ - if (!defs.ownerDocument.getElementById(marker.value.id)) { - marker.value.element = defs.appendChild(marker.value.element); + afterDrag: function () { + + }, + + /** + * Show all Labels at these shape + * + */ + showAllLabels: function (shape) { + + // Show the label of these shape + //shape.getLabels().each(function(label) { + for (var i = 0; i < shape.length; i++) { + var label = shape[i]; + label.show(); + }//); + // Show all labels at docked shapes + //shape.getAllDockedShapes().each(function(dockedShape) { + var allDockedShapes = shape.getAllDockedShapes() + for (var i = 0; i < allDockedShapes.length; i++) { + var dockedShape = allDockedShapes[i]; + var labels = dockedShape.getLabels(); + if (labels.length > 0) { + labels.each(function (label) { + label.show(); + }); } - }); + }//); + + // Do this recursive + //shape.children.each((function(value) { + for (var i = 0; i < shape.children.length; i++) { + var value = shape.children[i]; + if (value instanceof ORYX.Core.Shape) + this.showAllLabels(value); + }//).bind(this)); }, - + /** - * Removes all necessary markers of this Edge from the SVG document. - * Has to be called, while this.node is part of DOM. + * Intialize Method, if there are new Plugins + * */ - removeMarkers: function(){ - var svgElement = this.node.ownerSVGElement; - if (svgElement) { - var defs = svgElement.getElementsByTagNameNS(NAMESPACE_SVG, "defs"); - if (defs.length > 0) { - defs = defs[0]; - this._markers.each(function(marker){ - var foundMarker = defs.ownerDocument.getElementById(marker.value.id); - if (foundMarker) { - marker.value.element = defs.removeChild(marker.value.element); + /*registryChanged: function(pluginsData) { + // Save all new Plugin, sorted by group and index + this.pluginsData = pluginsData.sortBy( function(value) { + return (value.group + "" + value.index); + }); + },*/ + + /** + * On the Selection-Changed + * + */ + onSelectionChanged: function (event) { + var elements = event.elements; + + // Reset the drag-variables + this.dragEnable = false; + this.dragIntialized = false; + this.resizerSE.hide(); + this.resizerNW.hide(); + + // If there is no elements + if (!elements || elements.length == 0) { + // Hide all things and reset all variables + this.selectedRect.hide(); + this.currentShapes = []; + this.toMoveShapes = []; + this.dragBounds = undefined; + this.oldDragBounds = undefined; + } else { + + // Set the current Shapes + this.currentShapes = elements; + + // Get all shapes with the highest parent in object hierarchy (canvas is the top most parent) + var topLevelElements = this.facade.getCanvas().getShapesWithSharedParent(elements); + this.toMoveShapes = topLevelElements; + + this.toMoveShapes = this.toMoveShapes.findAll(function (shape) { + return shape instanceof ORYX.Core.Node && + (shape.dockers.length === 0 || !elements.member(shape.dockers.first().getDockedShape())) + }); + + elements.each((function (shape) { + if (!(shape instanceof ORYX.Core.Edge)) { + return; + } + + var dks = shape.getDockers(); + + var hasF = elements.member(dks.first().getDockedShape()); + var hasL = elements.member(dks.last().getDockedShape()); + +// if(!hasL) { +// this.toMoveShapes.push(dks.last()); +// } +// if(!hasF){ +// this.toMoveShapes.push(dks.first()) +// } + /* Enable movement of undocked edges */ + if (!hasF && !hasL) { + var isUndocked = !dks.first().getDockedShape() && !dks.last().getDockedShape(); + if (isUndocked) { + this.toMoveShapes = this.toMoveShapes.concat(dks); + } + } + + if (shape.dockers.length > 2 && hasF && hasL) { + this.toMoveShapes = this.toMoveShapes.concat(dks.findAll(function (el, index) { + return index > 0 && index < dks.length - 1 + })); + } + + }).bind(this)); + + // Calculate the new area-bounds of the selection + var newBounds = undefined; + this.toMoveShapes.each(function (value) { + var shape = value; + if (value instanceof ORYX.Core.Controls.Docker) { + /* Get the Shape */ + shape = value.parent; + } + + if (!newBounds) { + newBounds = shape.absoluteBounds(); + } else { + newBounds.include(shape.absoluteBounds()); + } + }.bind(this)); + + if (!newBounds) { + elements.each(function (value) { + if (!newBounds) { + newBounds = value.absoluteBounds(); + } else { + newBounds.include(value.absoluteBounds()); } }); } + + // Set the new bounds + this.dragBounds = newBounds; + this.oldDragBounds = newBounds.clone(); + + // Update and show the rectangle + this.resizeRectangle(newBounds); + this.selectedRect.show(); + + // Show the resize button, if there is only one element and this is resizeable + if (elements.length == 1 && elements[0].isResizable) { + var aspectRatio = elements[0].getStencil().fixedAspectRatio() ? elements[0].bounds.width() / elements[0].bounds.height() : undefined; + this.resizerSE.setBounds(this.dragBounds, elements[0].minimumSize, elements[0].maximumSize, aspectRatio); + this.resizerSE.show(); + this.resizerNW.setBounds(this.dragBounds, elements[0].minimumSize, elements[0].maximumSize, aspectRatio); + this.resizerNW.show(); + } else { + this.resizerSE.setBounds(undefined); + this.resizerNW.setBounds(undefined); + } + + // If Snap-To-Grid is enabled, the Snap-Point will be calculate + if (ORYX.CONFIG.GRID_ENABLED) { + + // Reset all points + this.distPoints = []; + + if (this.distPointTimeout) + window.clearTimeout(this.distPointTimeout) + + this.distPointTimeout = window.setTimeout(function () { + // Get all the shapes, there will consider at snapping + // Consider only those elements who shares the same parent element + var distShapes = this.facade.getCanvas().getChildShapes(true).findAll(function (value) { + var parentShape = value.parent; + while (parentShape) { + if (elements.member(parentShape)) return false; + parentShape = parentShape.parent + } + return true; + }) + + // The current selection will delete from this array + //elements.each(function(shape) { + // distShapes = distShapes.without(shape); + //}); + + // For all these shapes + distShapes.each((function (value) { + if (!(value instanceof ORYX.Core.Edge)) { + var ul = value.absoluteXY(); + var width = value.bounds.width(); + var height = value.bounds.height(); + + // Add the upperLeft, center and lowerRight - Point to the distancePoints + this.distPoints.push({ + ul: { + x: ul.x, + y: ul.y + }, + c: { + x: ul.x + (width / 2), + y: ul.y + (height / 2) + }, + lr: { + x: ul.x + width, + y: ul.y + height + } + }); + } + }).bind(this)); + + }.bind(this), 10) + + + } + } + }, + + /** + * Adjust an Point to the Snap Points + * + */ + snapToGrid: function (position) { + + // Get the current Bounds + var bounds = this.dragBounds; + + var point = {}; + + var ulThres = 6; + var cThres = 10; + var lrThres = 6; + + var scale = this.vLine ? this.vLine.getScale() : 1; + + var ul = {x: (position.x / scale), y: (position.y / scale)}; + var c = {x: (position.x / scale) + (bounds.width() / 2), y: (position.y / scale) + (bounds.height() / 2)}; + var lr = {x: (position.x / scale) + (bounds.width()), y: (position.y / scale) + (bounds.height())}; + + var offsetX, offsetY; + var gridX, gridY; + + // For each distant point + this.distPoints.each(function (value) { + + var x, y, gx, gy; + if (Math.abs(value.c.x - c.x) < cThres) { + x = value.c.x - c.x; + gx = value.c.x; + }/* else if (Math.abs(value.ul.x-ul.x) < ulThres){ + x = value.ul.x-ul.x; + gx = value.ul.x; + } else if (Math.abs(value.lr.x-lr.x) < lrThres){ + x = value.lr.x-lr.x; + gx = value.lr.x; + } */ + + + if (Math.abs(value.c.y - c.y) < cThres) { + y = value.c.y - c.y; + gy = value.c.y; + }/* else if (Math.abs(value.ul.y-ul.y) < ulThres){ + y = value.ul.y-ul.y; + gy = value.ul.y; + } else if (Math.abs(value.lr.y-lr.y) < lrThres){ + y = value.lr.y-lr.y; + gy = value.lr.y; + } */ + + if (x !== undefined) { + offsetX = offsetX === undefined ? x : (Math.abs(x) < Math.abs(offsetX) ? x : offsetX); + if (offsetX === x) + gridX = gx; + } + + if (y !== undefined) { + offsetY = offsetY === undefined ? y : (Math.abs(y) < Math.abs(offsetY) ? y : offsetY); + if (offsetY === y) + gridY = gy; + } + }); + + + if (offsetX !== undefined) { + ul.x += offsetX; + ul.x *= scale; + if (this.vLine && gridX) + this.vLine.update(gridX); + } else { + ul.x = (position.x - (position.x % (ORYX.CONFIG.GRID_DISTANCE / 2))); + if (this.vLine) + this.vLine.hide() + } + + if (offsetY !== undefined) { + ul.y += offsetY; + ul.y *= scale; + if (this.hLine && gridY) + this.hLine.update(gridY); + } else { + ul.y = (position.y - (position.y % (ORYX.CONFIG.GRID_DISTANCE / 2))); + if (this.hLine) + this.hLine.hide(); } + + return ul; + }, + + showGridLine: function () { + }, - + + /** - * Calls when a docker has changed + * Redraw of the Rectangle of the SelectedArea + * @param {Object} bounds */ - _dockerChanged: function(){ - - //this._update(true); - this._dockerUpdated = true; - + resizeRectangle: function (bounds) { + // Resize the Rectangle + this.selectedRect.resize(bounds); + } + +}); + + +ORYX.Plugins.SelectedRect = Clazz.extend({ + + construct: function (parentId) { + + this.parentId = parentId; + + this.node = ORYX.Editor.graft("http://www.w3.org/2000/svg", $(parentId), + ['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(); + }, - - serialize: function(){ - var result = arguments.callee.$.serialize.apply(this); - - //add dockers triple - var value = ""; - this._dockersByPath.each((function(pair){ - pair.value.each(function(docker){ - var position = docker.getDockedShape() && docker.referencePoint ? docker.referencePoint : docker.bounds.center(); - value = value.concat(position.x + " " + position.y + " "); - }); - - value += " # "; - }).bind(this)); - result.push({ - name: 'dockers', - prefix: 'oryx', - value: value, - type: 'literal' - }); - - //add parent triple dependant on the dockedShapes - //TODO change this when canvas becomes a resource -/* var source = this.dockers.first().getDockedShape(); - var target = this.dockers.last().getDockedShape(); - var sharedParent; - if (source && target) { - //get shared parent - while (source.parent) { - source = source.parent; - if (source instanceof ORYX.Core.Canvas) { - sharedParent = source; - break; - } - else { - var targetParent = target.parent; - var found; - while (targetParent) { - if (source === targetParent) { - sharedParent = source; - found = true; - break; - } - else { - targetParent = targetParent.parent; - } - } - if (found) { - break; - } - } - } + + hide: function () { + this.node.setAttributeNS(null, 'display', 'none'); + }, + + show: function () { + this.node.setAttributeNS(null, 'display', ''); + }, + + resize: function (bounds) { + var upL = bounds.upperLeft(); + + var padding = ORYX.CONFIG.SELECTED_AREA_PADDING; + + this.dashedArea.setAttributeNS(null, 'width', bounds.width() + 2 * padding); + this.dashedArea.setAttributeNS(null, 'height', bounds.height() + 2 * padding); + this.node.setAttributeNS(null, 'transform', "translate(" + (upL.x - padding) + ", " + (upL.y - padding) + ")"); + } + + +}); + + +ORYX.Plugins.GridLine = Clazz.extend({ + + construct: function (parentId, direction) { + + if (ORYX.Plugins.GridLine.DIR_HORIZONTAL !== direction && ORYX.Plugins.GridLine.DIR_VERTICAL !== direction) { + direction = ORYX.Plugins.GridLine.DIR_HORIZONTAL } - else - if (source) { - sharedParent = source.parent; - } - else - if (target) { - sharedParent = target.parent; - } -*/ - //if (sharedParent) { -/* result.push({ - name: 'parent', - prefix: 'raziel', - //value: '#' + ERDF.__stripHashes(sharedParent.resourceId), - value: '#' + ERDF.__stripHashes(this.getCanvas().resourceId), - type: 'resource' - });*/ - //} - - //serialize target and source - var lastDocker = this.dockers.last(); - - var target = lastDocker.getDockedShape(); - - if(target) { - result.push({ - name: 'target', - prefix: 'raziel', - value: '#' + ERDF.__stripHashes(target.resourceId), - type: 'resource' - }); - } - + + + this.parent = $(parentId); + this.direction = direction; + 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 { - //result = this.getStencil().serialize(this, result); - var serializeEvent = this.getStencil().serialize(); - - /* - * call serialize callback by reference, result should be found - * in serializeEvent.result - */ - if(serializeEvent.type) { - serializeEvent.shape = this; - serializeEvent.data = result; - serializeEvent.result = undefined; - serializeEvent.forceExecution = true; - - this._delegateEvent(serializeEvent); - - if(serializeEvent.result) { - result = serializeEvent.result; - } - } - } - catch (e) { + return this.parent.parentNode.transform.baseVal.getItem(0).matrix.a; + } catch (e) { + return 1; } - return result; }, - - deserialize: function(data){ - try { - //data = this.getStencil().deserialize(this, data); - - var deserializeEvent = this.getStencil().deserialize(); - - /* - * call serialize callback by reference, result should be found - * in serializeEventInfo.result - */ - if(deserializeEvent.type) { - deserializeEvent.shape = this; - deserializeEvent.data = data; - deserializeEvent.result = undefined; - deserializeEvent.forceExecution = true; - - this._delegateEvent(deserializeEvent); - if(deserializeEvent.result) { - data = deserializeEvent.result; - } - } - } - catch (e) { - } - - // Set the outgoing shapes - var target = data.find(function(ser) {return (ser.prefix+"-"+ser.name) == 'raziel-target'}); - var targetShape; - if(target) { - targetShape = this.getCanvas().getChildShapeByResourceId(target.value); - } - - var outgoing = data.findAll(function(ser){ return (ser.prefix+"-"+ser.name) == 'raziel-outgoing'}); - outgoing.each((function(obj){ - // TODO: Look at Canvas - if(!this.parent) {return}; - - // Set outgoing Shape - var next = this.getCanvas().getChildShapeByResourceId(obj.value); - - if(next){ - if(next == targetShape) { - // If this is an edge, set the last docker to the next shape - this.dockers.last().setDockedShape(next); - this.dockers.last().setReferencePoint({x: next.bounds.width() / 2.0, y: next.bounds.height() / 2.0}); - } else if(next instanceof ORYX.Core.Edge) { - //Set the first docker of the next shape - next.dockers.first().setDockedShape(this); - //next.dockers.first().setReferencePoint({x: this.bounds.width() / 2.0, y: this.bounds.height() / 2.0}); - } /*else if(next.dockers.length > 0) { //next is a node and next has a docker - next.dockers.first().setDockedShape(this); - next.dockers.first().setReferencePoint({x: this.bounds.width() / 2.0, y: this.bounds.height() / 2.0}); - }*/ - } - - }).bind(this)); - - - var oryxDockers = data.find(function(obj){ - return (obj.prefix === "oryx" && - obj.name === "dockers"); - }); - - if (oryxDockers) { - var dataByPath = oryxDockers.value.split("#").without("").without(" "); - - dataByPath.each((function(data, index){ - var values = data.replace(/,/g, " ").split(" ").without(""); - - //for each docker two values must be defined - if (values.length % 2 === 0) { - var path = this._paths[index]; - - if (path) { - if (index === 0) { - while (this._dockersByPath[path.id].length > 2) { - this.removeDocker(this._dockersByPath[path.id][1]); - } - } - else { - while (this._dockersByPath[path.id].length > 1) { - this.removeDocker(this._dockersByPath[path.id][0]); - } - } - - var dockersByPath = this._dockersByPath[path.id]; - - if (index === 0) { - //set position of first docker - var x = parseFloat(values.shift()); - var y = parseFloat(values.shift()); - - if (dockersByPath.first().getDockedShape()) { - dockersByPath.first().setReferencePoint({ - x: x, - y: y - }); - } - else { - dockersByPath.first().bounds.centerMoveTo(x, y); - } - } - - //set position of last docker - y = parseFloat(values.pop()); - x = parseFloat(values.pop()); - - if (dockersByPath.last().getDockedShape()) { - dockersByPath.last().setReferencePoint({ - x: x, - y: y - }); - } else { - dockersByPath.last().bounds.centerMoveTo(x, y); - } - - //add additional dockers - for (var i = 0; i < values.length; i++) { - x = parseFloat(values[i]); - y = parseFloat(values[++i]); - - var newDocker = this.createDocker(); - newDocker.bounds.centerMoveTo(x, y); - - //this.dockers = this.dockers.without(newDocker); - //this.dockers.splice(this.dockers.indexOf(dockersByPath.last()), 0, newDocker); - //dockersByPath.splice(this.dockers.indexOf(dockersByPath.last()), 0, newDocker); - } - } - } - }).bind(this)); + + update: function (pos) { + + if (this.direction === ORYX.Plugins.GridLine.DIR_HORIZONTAL) { + var y = pos instanceof Object ? pos.y : pos; + var cWidth = this.parent.parentNode.parentNode.width.baseVal.value / this.getScale(); + this.line.setAttributeNS(null, 'd', 'M 0 ' + y + ' L ' + cWidth + ' ' + y); } else { - this.alignDockers(); + var x = pos instanceof Object ? pos.x : pos; + var cHeight = this.parent.parentNode.parentNode.height.baseVal.value / this.getScale(); + this.line.setAttributeNS(null, 'd', 'M' + x + ' 0 L ' + x + ' ' + cHeight); + } + + this.show(); + } + + +}); + +ORYX.Plugins.GridLine.DIR_HORIZONTAL = "hor"; +ORYX.Plugins.GridLine.DIR_VERTICAL = "ver"; + +ORYX.Plugins.Resizer = Clazz.extend({ + + construct: function (parentId, orientation, facade) { + + this.parentId = parentId; + this.orientation = orientation; + this.facade = facade; + + 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(); + + // Calculate the Offset + this.scrollNode = this.node.parentNode.parentNode.parentNode; + + }, + + handleMouseDown: function (event) { + this.dragEnable = true; + + this.offsetScroll = {x: this.scrollNode.scrollLeft, y: this.scrollNode.scrollTop}; + + this.offSetPosition = { + x: Event.pointerX(event) - this.position.x, + y: Event.pointerY(event) - this.position.y + }; + + this.resizeStartCallbacks.each((function (value) { + value(this.bounds); + }).bind(this)); + + }, + + handleMouseUp: function (event) { + this.dragEnable = false; + this.containmentParentNode = null; + this.resizeEndCallbacks.each((function (value) { + value(this.bounds); + }).bind(this)); + + }, + + handleMouseMove: function (event) { + if (!this.dragEnable) { + return + } + + if (event.shiftKey || event.ctrlKey) { + this.aspectRatio = this.bounds.width() / this.bounds.height(); + } else { + this.aspectRatio = undefined; + } + + var position = { + x: Event.pointerX(event) - this.offSetPosition.x, + y: Event.pointerY(event) - this.offSetPosition.y + }; + + + position.x -= this.offsetScroll.x - this.scrollNode.scrollLeft; + position.y -= this.offsetScroll.y - this.scrollNode.scrollTop; + + position.x = Math.min(position.x, this.facade.getCanvas().bounds.width()); + position.y = Math.min(position.y, this.facade.getCanvas().bounds.height()); + + var offset = { + x: position.x - this.position.x, + y: position.y - this.position.y + }; + + if (this.aspectRatio) { + // fixed aspect ratio + newAspectRatio = (this.bounds.width() + offset.x) / (this.bounds.height() + offset.y); + if (newAspectRatio > this.aspectRatio) { + offset.x = this.aspectRatio * (this.bounds.height() + offset.y) - this.bounds.width(); + } else if (newAspectRatio < this.aspectRatio) { + offset.y = (this.bounds.width() + offset.x) / this.aspectRatio - this.bounds.height(); + } + } + + // respect minimum and maximum sizes of stencil + if (this.orientation === "northwest") { + + if (this.bounds.width() - offset.x > this.maxSize.width) { + offset.x = -(this.maxSize.width - this.bounds.width()); + if (this.aspectRatio) + offset.y = this.aspectRatio * offset.x; + } + if (this.bounds.width() - offset.x < this.minSize.width) { + offset.x = -(this.minSize.width - this.bounds.width()); + if (this.aspectRatio) + offset.y = this.aspectRatio * offset.x; + } + if (this.bounds.height() - offset.y > this.maxSize.height) { + offset.y = -(this.maxSize.height - this.bounds.height()); + if (this.aspectRatio) + offset.x = offset.y / this.aspectRatio; + } + if (this.bounds.height() - offset.y < this.minSize.height) { + offset.y = -(this.minSize.height - this.bounds.height()); + if (this.aspectRatio) + offset.x = offset.y / this.aspectRatio; + } + + } else { // defaults to southeast + if (this.bounds.width() + offset.x > this.maxSize.width) { + offset.x = this.maxSize.width - this.bounds.width(); + if (this.aspectRatio) + offset.y = this.aspectRatio * offset.x; + } + if (this.bounds.width() + offset.x < this.minSize.width) { + offset.x = this.minSize.width - this.bounds.width(); + if (this.aspectRatio) + offset.y = this.aspectRatio * offset.x; + } + if (this.bounds.height() + offset.y > this.maxSize.height) { + offset.y = this.maxSize.height - this.bounds.height(); + if (this.aspectRatio) + offset.x = offset.y / this.aspectRatio; + } + if (this.bounds.height() + offset.y < this.minSize.height) { + offset.y = this.minSize.height - this.bounds.height(); + if (this.aspectRatio) + offset.x = offset.y / this.aspectRatio; + } } - - arguments.callee.$.deserialize.apply(this, arguments); - - this._changed(); + + if (this.orientation === "northwest") { + this.bounds.extend({x: -offset.x, y: -offset.y}); + this.bounds.moveBy(offset); + } else { // defaults to southeast + this.bounds.extend(offset); + } + + this.update(); + + this.resizeCallbacks.each((function (value) { + value(this.bounds); + }).bind(this)); + + Event.stop(event); + }, - - toString: function(){ - return this.getStencil().title() + " " + this.id; + + registerOnResizeStart: function (callback) { + if (!this.resizeStartCallbacks.member(callback)) { + this.resizeStartCallbacks.push(callback); + } }, - - /** - * @return {ORYX.Core.Shape} Returns last docked shape or null. - */ - getTarget: function(){ - return this.dockers.last() ? this.dockers.last().getDockedShape() : null; + + unregisterOnResizeStart: function (callback) { + if (this.resizeStartCallbacks.member(callback)) { + this.resizeStartCallbacks = this.resizeStartCallbacks.without(callback); + } }, - - /** - * @return {ORYX.Core.Shape} Returns the first docked shape or null - */ - getSource: function() { - return this.dockers.first() ? this.dockers.first().getDockedShape() : null; - }, - - /** - * Checks whether the edge is at least docked to one shape. - * - * @return {boolean} True if edge is docked - */ - isDocked: function() { - var isDocked = false; - this.dockers.each(function(docker) { - if(docker.isDocked()) { - isDocked = true; - throw $break; - } - }); - return isDocked; - }, - - /** - * Calls {@link ORYX.Core.AbstractShape#toJSON} and add a some stencil set information. - */ - toJSON: function() { - var json = arguments.callee.$.toJSON.apply(this, arguments); - - if(this.getTarget()) { - json.target = { - resourceId: this.getTarget().resourceId - }; + + registerOnResizeEnd: function (callback) { + if (!this.resizeEndCallbacks.member(callback)) { + this.resizeEndCallbacks.push(callback); } - - return json; - } -}; -ORYX.Core.Edge = ORYX.Core.Shape.extend(ORYX.Core.Edge); -/* - * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. - * License rights for this program may be obtained from Alfresco Software, Ltd. - * pursuant to a written agreement and any use of this program without such an - * agreement is prohibited. - */ -/* - * All code Copyright 2013 KIS Consultancy all rights reserved - */ + }, -if(!ORYX){ var ORYX = {} } -if(!ORYX.Plugins){ ORYX.Plugins = {} } + unregisterOnResizeEnd: function (callback) { + if (this.resizeEndCallbacks.member(callback)) { + this.resizeEndCallbacks = this.resizeEndCallbacks.without(callback); + } + }, -/** - This abstract plugin class can be used to build plugins on. - It provides some more basic functionality like registering events (on*-handlers)... - @example - ORYX.Plugins.MyPlugin = ORYX.Plugins.AbstractPlugin.extend({ - construct: function() { - // Call super class constructor - arguments.callee.$.construct.apply(this, arguments); - - [...] - }, - [...] - }); - - @class ORYX.Plugins.AbstractPlugin - @constructor Creates a new instance - @author Willi Tscheschner -*/ -ORYX.Plugins.AbstractPlugin = Clazz.extend({ - /** - * The facade which offer editor-specific functionality - * @type Facade - * @memberOf ORYX.Plugins.AbstractPlugin.prototype - */ - facade: null, - - construct: function( facade ){ - this.facade = facade; - - this.facade.registerOnEvent(ORYX.CONFIG.EVENT_LOADED, this.onLoaded.bind(this)); - }, - - /** - Overwrite to handle load event. TODO: Document params!!! - @methodOf ORYX.Plugins.AbstractPlugin.prototype - */ - onLoaded: function(){}, - - /** - Overwrite to handle selection changed event. TODO: Document params!!! - @methodOf ORYX.Plugins.AbstractPlugin.prototype - */ - onSelectionChanged: function(){}, - - /** - Show overlay on given shape. - @methodOf ORYX.Plugins.AbstractPlugin.prototype - @example - showOverlay( - myShape, - { stroke: "green" }, - ORYX.Editor.graft("http://www.w3.org/2000/svg", null, ['path', { - "title": "Click the element to execute it!", - "stroke-width": 2.0, - "stroke": "black", - "d": "M0,-5 L5,0 L0,5 Z", - "line-captions": "round" - }]) - ) - @param {Oryx.XXX.Shape[]} shapes One shape or array of shapes the overlay should be put on - @param {Oryx.XXX.Attributes} attributes some attributes... - @param {Oryx.svg.node} svgNode The svg node which should be used as overlay - @param {String} [svgNode="NW"] The svg node position where the overlay should be placed - */ - showOverlay: function(shapes, attributes, svgNode, svgNodePosition ){ - - if( !(shapes instanceof Array) ){ - shapes = [shapes] - } - - // Define Shapes - shapes = shapes.map(function(shape){ - var el = shape; - if( typeof shape == "string" ){ - el = this.facade.getCanvas().getChildShapeByResourceId( shape ); - el = el || this.facade.getCanvas().getChildById( shape, true ); - } - return el; - }.bind(this)).compact(); - - // Define unified id - if( !this.overlayID ){ - this.overlayID = this.type + ORYX.Editor.provideId(); - } - - this.facade.raiseEvent({ - type : ORYX.CONFIG.EVENT_OVERLAY_SHOW, - id : this.overlayID, - shapes : shapes, - attributes : attributes, - node : svgNode, - nodePosition: svgNodePosition || "NW" - }); - - }, - - /** - Hide current overlay. - @methodOf ORYX.Plugins.AbstractPlugin.prototype - */ - hideOverlay: function(){ - this.facade.raiseEvent({ - type : ORYX.CONFIG.EVENT_OVERLAY_HIDE, - id : this.overlayID - }); - }, - - /** - Does a transformation with the given xslt stylesheet. - @methodOf ORYX.Plugins.AbstractPlugin.prototype - @param {String} data The data (e.g. eRDF) which should be transformed - @param {String} stylesheet URL of a stylesheet which should be used for transforming data. - */ - doTransform: function( data, stylesheet ) { - - if( !stylesheet || !data ){ - return "" - } + registerOnResize: function (callback) { + if (!this.resizeCallbacks.member(callback)) { + this.resizeCallbacks.push(callback); + } + }, - var parser = new DOMParser(); - var parsedData = parser.parseFromString(data, "text/xml"); - source=stylesheet; - new Ajax.Request(source, { - asynchronous: false, - method: 'get', - onSuccess: function(transport){ - xsl = transport.responseText - }.bind(this), - onFailure: (function(transport){ - ORYX.Log.error("XSL load failed" + transport); - }).bind(this) - }); - var xsltProcessor = new XSLTProcessor(); - var domParser = new DOMParser(); - var xslObject = domParser.parseFromString(xsl, "text/xml"); - xsltProcessor.importStylesheet(xslObject); - - try { - - var newData = xsltProcessor.transformToFragment(parsedData, document); - var serializedData = (new XMLSerializer()).serializeToString(newData); - - /* Firefox 2 to 3 problem?! */ - serializedData = !serializedData.startsWith("" + serializedData : serializedData; - - return serializedData; - - }catch (error) { - return -1; + unregisterOnResize: function (callback) { + if (this.resizeCallbacks.member(callback)) { + this.resizeCallbacks = this.resizeCallbacks.without(callback); } - - }, - - /** - * Opens a new window that shows the given XML content. - * @methodOf ORYX.Plugins.AbstractPlugin.prototype - * @param {Object} content The XML content to be shown. - * @example - * openDownloadWindow( "my.xml", "" ); - */ - openXMLWindow: function(content) { - var win = window.open( - 'data:application/xml,' + encodeURIComponent( - content - ), - '_blank', "resizable=yes,width=600,height=600,toolbar=0,scrollbars=yes" - ); - }, - - /** - * Opens a download window for downloading the given content. - * @methodOf ORYX.Plugins.AbstractPlugin.prototype - * @param {String} filename The content's file name - * @param {String} content The content to download - */ - openDownloadWindow: function(filename, content) { - var win = window.open(""); - if (win != null) { - win.document.open(); - win.document.write(""); - var submitForm = win.document.createElement("form"); - win.document.body.appendChild(submitForm); - - var createHiddenElement = function(name, value) { - var newElement = document.createElement("input"); - newElement.name=name; - newElement.type="hidden"; - newElement.value = value; - return newElement - } - - submitForm.appendChild( createHiddenElement("download", content) ); - submitForm.appendChild( createHiddenElement("file", filename) ); - - - submitForm.method = "POST"; - win.document.write(""); - win.document.close(); - submitForm.action= ORYX.PATH + "/download"; - submitForm.submit(); - } - }, - - /** - * Serializes DOM. - * @methodOf ORYX.Plugins.AbstractPlugin.prototype - * @type {String} Serialized DOM - */ - getSerializedDOM: function(){ - // Force to set all resource IDs - var serializedDOM = DataManager.serializeDOM( this.facade ); + }, - //add namespaces - serializedDOM = '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - serializedDOM + - ''; - - return serializedDOM; + hide: function () { + this.node.style.display = "none"; }, - - /** - * Sets the editor in read only mode: Edges/ dockers cannot be moved anymore, - * shapes cannot be selected anymore. - * @methodOf ORYX.Plugins.AbstractPlugin.prototype - */ - enableReadOnlyMode: function(){ - //Edges cannot be moved anymore - this.facade.disableEvent(ORYX.CONFIG.EVENT_MOUSEDOWN); - - // Stop the user from editing the diagram while the plugin is active - this._stopSelectionChange = function(){ - if(this.facade.getSelection().length > 0) { - this.facade.setSelection([]); - } - }; - this.facade.registerOnEvent(ORYX.CONFIG.EVENT_SELECTION_CHANGED, this._stopSelectionChange.bind(this)); + + show: function () { + if (this.bounds) + this.node.style.display = ""; }, - /** - * Disables read only mode, see @see - * @methodOf ORYX.Plugins.AbstractPlugin.prototype - * @see ORYX.Plugins.AbstractPlugin.prototype.enableReadOnlyMode - */ - disableReadOnlyMode: function(){ - // Edges can be moved now again - 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; + + setBounds: function (bounds, min, max, aspectRatio) { + this.bounds = bounds; + + if (!min) + min = {width: ORYX.CONFIG.MINIMUM_SIZE, height: ORYX.CONFIG.MINIMUM_SIZE}; + + if (!max) + max = {width: ORYX.CONFIG.MAXIMUM_SIZE, height: ORYX.CONFIG.MAXIMUM_SIZE}; + + this.minSize = min; + this.maxSize = max; + + this.aspectRatio = aspectRatio; + + this.update(); + }, + + update: function () { + if (!this.bounds) { + return; + } + + var upL = this.bounds.upperLeft(); + + if (this.bounds.width() < this.minSize.width) { + this.bounds.set(upL.x, upL.y, upL.x + this.minSize.width, upL.y + this.bounds.height()); + } + ; + if (this.bounds.height() < this.minSize.height) { + this.bounds.set(upL.x, upL.y, upL.x + this.bounds.width(), upL.y + this.minSize.height); + } + ; + if (this.bounds.width() > this.maxSize.width) { + this.bounds.set(upL.x, upL.y, upL.x + this.maxSize.width, upL.y + this.bounds.height()); + } + ; + if (this.bounds.height() > this.maxSize.height) { + this.bounds.set(upL.x, upL.y, upL.x + this.bounds.width(), upL.y + this.maxSize.height); + } + ; + + var a = this.canvasNode.getScreenCTM(); + + upL.x *= a.a; + upL.y *= a.d; + + var additionalIEZoom = 1; + if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) { + var ua = navigator.userAgent; + if (ua.indexOf('MSIE') >= 0) { + //IE 10 and below + var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100); + if (zoom !== 100) { + additionalIEZoom = zoom / 100 + } + } + } + + if (additionalIEZoom === 1) { + upL.y = upL.y - jQuery("#canvasSection").offset().top + a.f; + upL.x = upL.x - jQuery("#canvasSection").offset().left + a.e; + + } else { + var canvasOffsetLeft = jQuery("#canvasSection").offset().left; + var canvasScrollLeft = jQuery("#canvasSection").scrollLeft(); + var canvasScrollTop = jQuery("#canvasSection").scrollTop(); + + var offset = a.e - (canvasOffsetLeft * additionalIEZoom); + var additionaloffset = 0; + if (offset > 10) { + additionaloffset = (offset / additionalIEZoom) - offset; + } + upL.y = upL.y - (jQuery("#canvasSection").offset().top * additionalIEZoom) + ((canvasScrollTop * additionalIEZoom) - canvasScrollTop) + a.f; + upL.x = upL.x - (canvasOffsetLeft * additionalIEZoom) + additionaloffset + ((canvasScrollLeft * additionalIEZoom) - canvasScrollLeft) + a.e; + } + + if (this.orientation === "northwest") { + upL.x -= 13; + upL.y -= 13; + } else { // defaults to southeast + upL.x += (a.a * this.bounds.width()) + 3; + upL.y += (a.d * this.bounds.height()) + 3; } + + this.position = upL; + + this.node.style.left = this.position.x + "px"; + this.node.style.top = this.position.y + "px"; + } +}); + + +/** + * Implements a Command to move shapes + * + */ +ORYX.Core.Command.Move = ORYX.Core.Command.extend({ + construct: function (moveShapes, offset, parent, selectedShapes, plugin) { + this.moveShapes = moveShapes; + this.selectedShapes = selectedShapes; + this.offset = offset; + this.plugin = plugin; + // Defines the old/new parents for the particular shape + this.newParents = moveShapes.collect(function (t) { + return parent || t.parent + }); + this.oldParents = moveShapes.collect(function (shape) { + return shape.parent + }); + this.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 + } + }); }, - - /** - * Extracts RDF from DOM. - * @methodOf ORYX.Plugins.AbstractPlugin.prototype - * @type {String} Extracted RFD. Null if there are transformation errors. - */ - getRDFFromDOM: function(){ - //convert to RDF - try { - var xsl = ""; - source=ORYX.PATH + "lib/extract-rdf.xsl"; - new Ajax.Request(source, { - asynchronous: false, - method: 'get', - onSuccess: function(transport){ - xsl = transport.responseText - }.bind(this), - onFailure: (function(transport){ - ORYX.Log.error("XSL load failed" + transport); - }).bind(this) - }); - - var domParser = new DOMParser(); - var xmlObject = domParser.parseFromString(this.getSerializedDOM(), "text/xml"); - var xslObject = domParser.parseFromString(xsl, "text/xml"); - var xsltProcessor = new XSLTProcessor(); - xsltProcessor.importStylesheet(xslObject); - var result = xsltProcessor.transformToFragment(xmlObject, document); - - var serializer = new XMLSerializer(); - - return serializer.serializeToString(result); - } catch(e){ - console.log("error serializing " + e); - return ""; - } + execute: function () { + this.dockAllShapes() + // Moves by the offset + this.move(this.offset); + // Addes to the new parents + this.addShapeToParent(this.newParents); + // Set the selection to the current selection + this.selectCurrentShapes(); + this.plugin.facade.getCanvas().update(); + this.plugin.facade.updateSelection(); + }, + rollback: function () { + // Moves by the inverted offset + var offset = {x: -this.offset.x, y: -this.offset.y}; + this.move(offset); + // Addes to the old parents + this.addShapeToParent(this.oldParents); + this.dockAllShapes(true) + + // Set the selection to the current selection + this.selectCurrentShapes(); + this.plugin.facade.getCanvas().update(); + this.plugin.facade.updateSelection(); - }, - - /** - * Checks if a certain stencil set is loaded right now. - * - */ - isStencilSetExtensionLoaded: function(stencilSetExtensionNamespace) { - return this.facade.getStencilSets().values().any( - function(ss){ - return ss.extensions().keys().any( - function(extensionKey) { - return extensionKey == stencilSetExtensionNamespace; - }.bind(this) - ); - }.bind(this) - ); - }, - - /** - * Raises an event so that registered layouters does - * have the posiblility to layout the given shapes - * For further reading, have a look into the AbstractLayouter - * class - * @param {Object} shapes - */ - doLayout: function(shapes){ - // Raises a do layout event - if (this.facade.raiseEvent) - { - this.facade.raiseEvent({ - type : ORYX.CONFIG.EVENT_LAYOUT, - shapes : shapes - }); - } - else - { - this.facade.handleEvents({ - type : ORYX.CONFIG.EVENT_LAYOUT, - shapes : shapes - }); - } - }, - - - /** - * Does a primitive layouting with the incoming/outgoing - * edges (set the dockers to the right position) and if - * necessary, it will be called the real layouting - * @param {ORYX.Core.Node} node - * @param {Array} edges - */ - layoutEdges : function(node, allEdges, offset){ - - if (!this.facade.isExecutingCommands()){ return } - - var Command = ORYX.Core.Command.extend({ - construct: function(edges, node, offset, plugin){ - this.edges = edges; - this.node = node; - this.plugin = plugin; - this.offset = offset; - - // Get the new absolute center - var center = node.absoluteXY(); - this.ulo = {x: center.x - offset.x, y:center.y - offset.y}; - - - }, - execute: function(){ - - if (this.changes){ - this.executeAgain(); - return; - } else { - this.changes = []; - this.edges.each(function(edge){ - this.changes.push({ - edge: edge, - oldDockerPositions: edge.dockers.map(function(r){ return r.bounds.center() }) - }) - }.bind(this)); - } - - // Find all edges, which are related to the node and - // have more than two dockers - this.edges - // Find all edges with more than two dockers - .findAll(function(r){ return r.dockers.length > 2 }.bind(this)) - // For every edge, check second and one before last docker - // if there are horizontal/vertical on the same level - // and if so, align the the bounds - .each(function(edge){ - if (edge.dockers.first().getDockedShape() === this.node){ - var second = edge.dockers[1]; - if (this.align(second.bounds, edge.dockers.first())){ second.update(); } - } else if (edge.dockers.last().getDockedShape() === this.node) { - var beforeLast = edge.dockers[edge.dockers.length-2]; - if (this.align(beforeLast.bounds, edge.dockers.last())){ beforeLast.update(); } - } - edge._update(true); - edge.removeUnusedDockers(); - if (this.isBendPointIncluded(edge)){ - this.plugin.doLayout(edge); - return; - } - }.bind(this)); - - - // Find all edges, which have only to dockers - // and is located horizontal/vertical. - // Do layout with those edges - this.edges - // Find all edges with exactly two dockers - .each(function(edge){ - if (edge.dockers.length == 2){ - var p1 = edge.dockers.first().getAbsoluteReferencePoint() || edge.dockers.first().bounds.center(); - var p2 = edge.dockers.last().getAbsoluteReferencePoint() || edge.dockers.first().bounds.center(); - // Find all horizontal/vertical edges - if (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){ - this.plugin.doLayout(edge); - } - } - }.bind(this)); - - this.edges.each(function(edge, i){ - this.changes[i].dockerPositions = edge.dockers.map(function(r){ return r.bounds.center() }); - }.bind(this)); - - }, - /** - * Align the bounds if the center is - * the same than the old center - * @params {Object} bounds - * @params {Object} bounds2 - */ - align: function(bounds, refDocker){ - - var abRef = refDocker.getAbsoluteReferencePoint() || refDocker.bounds.center(); - - var xdif = bounds.center().x-abRef.x; - var ydif = bounds.center().y-abRef.y; - if (Math.abs(-Math.abs(xdif) + Math.abs(this.offset.x)) < 3 && this.offset.xs === undefined){ - bounds.moveBy({x:-xdif, y:0}) - } - if (Math.abs(-Math.abs(ydif) + Math.abs(this.offset.y)) < 3 && this.offset.ys === undefined){ - bounds.moveBy({y:-ydif, x:0}) - } - - if (this.offset.xs !== undefined || this.offset.ys !== undefined){ - var absPXY = refDocker.getDockedShape().absoluteXY(); - xdif = bounds.center().x-(absPXY.x+((abRef.x-absPXY.x)/this.offset.xs)); - ydif = bounds.center().y-(absPXY.y+((abRef.y-absPXY.y)/this.offset.ys)); - - if (Math.abs(-Math.abs(xdif) + Math.abs(this.offset.x)) < 3){ - bounds.moveBy({x:-(bounds.center().x-abRef.x), y:0}) - } - - if (Math.abs(-Math.abs(ydif) + Math.abs(this.offset.y)) < 3){ - bounds.moveBy({y:-(bounds.center().y-abRef.y), x:0}) + move: function (offset, doLayout) { + + // Move all Shapes by these offset + for (var i = 0; i < this.moveShapes.length; i++) { + var value = this.moveShapes[i]; + value.bounds.moveBy(offset); + + if (value instanceof ORYX.Core.Node) { + + (value.dockers || []).each(function (d) { + d.bounds.moveBy(offset); + }) + + // Update all Dockers of Child shapes + /*var childShapesNodes = value.getChildShapes(true).findAll(function(shape){ return shape instanceof ORYX.Core.Node }); + var childDockedShapes = childShapesNodes.collect(function(shape){ return shape.getAllDockedShapes() }).flatten().uniq(); + var childDockedEdge = childDockedShapes.findAll(function(shape){ return shape instanceof ORYX.Core.Edge }); + childDockedEdge = childDockedEdge.findAll(function(shape){ return shape.getAllDockedShapes().all(function(dsh){ return childShapesNodes.include(dsh) }) }); + var childDockedDockers = childDockedEdge.collect(function(shape){ return shape.dockers }).flatten(); + + for (var j = 0; j < childDockedDockers.length; j++) { + var docker = childDockedDockers[j]; + if (!docker.getDockedShape() && !this.moveShapes.include(docker)) { + //docker.bounds.moveBy(offset); + //docker.update(); } - } - }, - - /** - * Returns a TRUE if there are bend point which overlay the shape - */ - isBendPointIncluded: function(edge){ - // Get absolute bounds - var ab = edge.dockers.first().getDockedShape(); - var bb = edge.dockers.last().getDockedShape(); - - if (ab) { - ab = ab.absoluteBounds(); - ab.widen(5); - } - - if (bb) { - bb = bb.absoluteBounds(); - bb.widen(20); // Wide with 20 because of the arrow from the edge - } - - return edge.dockers - .any(function(docker, i){ - var c = docker.bounds.center(); - // Dont count first and last - return i != 0 && i != edge.dockers.length-1 && - // Check if the point is included to the absolute bounds - ((ab && ab.isIncluded(c)) || (bb && bb.isIncluded(c))) - }) - }, - - removeAllDocker: function(edge){ - edge.dockers.slice(1, edge.dockers.length-1).each(function(docker){ - edge.removeDocker(docker); - }) - }, - executeAgain: function(){ - this.changes.each(function(change){ - // Reset the dockers - this.removeAllDocker(change.edge); - change.dockerPositions.each(function(pos, i){ - if (i==0||i==change.dockerPositions.length-1){ return } - var docker = change.edge.createDocker(undefined, pos); - docker.bounds.centerMoveTo(pos); - docker.update(); - }.bind(this)); - change.edge._update(true); - }.bind(this)); - }, - rollback: function(){ - this.changes.each(function(change){ - // Reset the dockers - this.removeAllDocker(change.edge); - change.oldDockerPositions.each(function(pos, i){ - if (i==0||i==change.oldDockerPositions.length-1){ return } - var docker = change.edge.createDocker(undefined, pos); - docker.bounds.centerMoveTo(pos); - docker.update(); - }.bind(this)); - change.edge._update(true); - }.bind(this)); - } - }); - - this.facade.executeCommands([new Command(allEdges, node, offset, this)]); + }*/ + + + var allEdges = [].concat(value.getIncomingShapes()) + .concat(value.getOutgoingShapes()) + // Remove all edges which are included in the selection from the list + .findAll(function (r) { + return r instanceof ORYX.Core.Edge && !this.moveShapes.any(function (d) { + return d == r || (d instanceof ORYX.Core.Controls.Docker && d.parent == r) + }) + }.bind(this)) + // Remove all edges which are between the node and a node contained in the selection from the list + .findAll(function (r) { + return (r.dockers.first().getDockedShape() == value || !this.moveShapes.include(r.dockers.first().getDockedShape())) && + (r.dockers.last().getDockedShape() == value || !this.moveShapes.include(r.dockers.last().getDockedShape())) + }.bind(this)) + + // Layout all outgoing/incoming edges + this.plugin.layoutEdges(value, allEdges, offset); + + + var allSameEdges = [].concat(value.getIncomingShapes()) + .concat(value.getOutgoingShapes()) + // Remove all edges which are included in the selection from the list + .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)) + // Remove all edges which are included in the selection from the list + .findAll(function (r) { + return this.moveShapes.indexOf(r.dockers.first().getDockedShape()) > i || this.moveShapes.indexOf(r.dockers.last().getDockedShape()) > i + }.bind(this)) + + for (var j = 0; j < allSameEdges.length; j++) { + for (var k = 1; k < allSameEdges[j].dockers.length - 1; k++) { + var docker = allSameEdges[j].dockers[k]; + if (!docker.getDockedShape() && !this.moveShapes.include(docker)) { + docker.bounds.moveBy(offset); + } + } + } + + /*var i=-1; + var nodes = value.getChildShapes(true); + var allEdges = []; + while(++i 0){ - // Do layout - this.layout(toLayout); - } - }, - - /** - * Implementation of layouting a set on shapes - * @param {Object} shapes Given shapes - * @memberOf ORYX.Plugins.AbstractLayouter.prototype - */ - layout: function(shapes){ - throw new Error("Layouter has to implement the layout function.") - } -});/* + } + }, + selectCurrentShapes: function () { + this.plugin.facade.setSelection(this.selectedShapes); + } +}); +/* * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. * License rights for this program may be obtained from Alfresco Software, Ltd. * pursuant to a written agreement and any use of this program without such an @@ -17494,477 +21709,553 @@ ORYX.Plugins.AbstractLayouter = ORYX.Plugins.AbstractPlugin.extend({ * All code Copyright 2013 KIS Consultancy all rights reserved */ -if (!ORYX.Plugins) +if (!ORYX.Plugins) ORYX.Plugins = new Object(); -ORYX.Plugins.Edit = Clazz.extend({ - - construct: function(facade){ - +ORYX.Plugins.DragDocker = Clazz.extend({ + + /** + * Constructor + * @param {Object} Facade: The Facade of the Editor + */ + construct: function (facade) { this.facade = facade; - this.clipboard = new ORYX.Plugins.Edit.ClipBoard(); - - //this.facade.registerOnEvent(ORYX.CONFIG.EVENT_KEYDOWN, this.keyHandler.bind(this)); - - 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 - }); + + // Set the valid and invalid color + this.VALIDCOLOR = ORYX.CONFIG.SELECTION_VALID_COLOR; + this.INVALIDCOLOR = ORYX.CONFIG.SELECTION_INVALID_COLOR; + + // Define Variables + 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; + + // For the Drag and Drop + // Register on MouseDown-Event on a Docker + this.facade.registerOnEvent(ORYX.CONFIG.EVENT_MOUSEDOWN, this.handleMouseDown.bind(this)); + this.facade.registerOnEvent(ORYX.CONFIG.EVENT_DOCKERDRAG, this.handleDockerDrag.bind(this)); + + + // Register on over/out to show / hide a docker + this.facade.registerOnEvent(ORYX.CONFIG.EVENT_MOUSEOVER, this.handleMouseOver.bind(this)); + this.facade.registerOnEvent(ORYX.CONFIG.EVENT_MOUSEOUT, this.handleMouseOut.bind(this)); + + }, - - callEdit: function(fn, args){ - window.setTimeout(function(){ - fn.apply(this, (args instanceof Array ? args : [])); - }.bind(this), 1); - }, - - /** - * Handles the mouse down event and starts the copy-move-paste action, if - * control or meta key is pressed. - */ - handleMouseDown: function(event) { - if(this._controlPressed) { - this._controlPressed = false; - this.editCopy(); -// console.log("copiedEle: %0",this.clipboard.shapesAsJson) -// console.log("mousevent: %o",event) - this.editPaste(); - event.forceExecution = true; - this.facade.raiseEvent(event, this.clipboard.shapesAsJson); - - } - }, - + /** - * The key handler for this plugin. Every action from the set of cut, copy, - * paste and delete should be accessible trough simple keyboard shortcuts. - * This method checks whether any event triggers one of those actions. + * MouseOut Handler * - * @param {Object} event The keyboard event that should be analysed for - * triggering of this plugin. */ -// keyHandler: function(event){ -// //TODO document what event.which is. -// -// ORYX.Log.debug("edit.js handles a keyEvent."); -// -// // assure we have the current event. -// if (!event) -// event = window.event; -// -// -// // get the currently pressed key and state of control key. -// var pressedKey = event.which || event.keyCode; -// var ctrlPressed = event.ctrlKey; -// -// // if the object is to be deleted, do so, and return immediately. -// if ((pressedKey == ORYX.CONFIG.KEY_CODE_DELETE) || -// ((pressedKey == ORYX.CONFIG.KEY_CODE_BACKSPACE) && -// (event.metaKey || event.appleMetaKey))) { -// -// ORYX.Log.debug("edit.js deletes the shape."); -// this.editDelete(); -// return; -// } -// -// // if control key is not pressed, we're not interested anymore. -// if (!ctrlPressed) -// return; -// -// // when ctrl is pressed, switch trough the possibilities. -// switch (pressedKey) { -// -// // cut. -// case ORYX.CONFIG.KEY_CODE_X: -// this.editCut(); -// break; -// -// // copy. -// case ORYX.CONFIG.KEY_CODE_C: -// this.editCopy(); -// break; -// -// // paste. -// case ORYX.CONFIG.KEY_CODE_V: -// this.editPaste(); -// break; -// } -// }, - + handleMouseOut: function (event, uiObj) { + // If there is a Docker, hide this + if (!this.docker && uiObj instanceof ORYX.Core.Controls.Docker) { + uiObj.hide(); + } else if (!this.docker && uiObj instanceof ORYX.Core.Edge) { + uiObj.dockers.each(function (docker) { + docker.hide(); + }); + } + }, + /** - * Returns a list of shapes which should be considered while copying. - * Besides the shapes of given ones, edges and attached nodes are added to the result set. - * If one of the given shape is a child of another given shape, it is not put into the result. + * MouseOver Handler + * */ - getAllShapesToConsider: function(shapes){ - var shapesToConsider = []; // only top-level shapes - var childShapesToConsider = []; // all child shapes of top-level shapes - - shapes.each(function(shape){ - //Throw away these shapes which have a parent in given shapes - isChildShapeOfAnother = shapes.any(function(s2){ - return s2.hasChildShape(shape); - }); - if(isChildShapeOfAnother) return; - - // This shape should be considered - shapesToConsider.push(shape); - // Consider attached nodes (e.g. intermediate events) - if (shape instanceof ORYX.Core.Node) { - var attached = shape.getOutgoingNodes(); - attached = attached.findAll(function(a){ return !shapes.include(a) }); - shapesToConsider = shapesToConsider.concat(attached); - } - - childShapesToConsider = childShapesToConsider.concat(shape.getChildShapes(true)); - }.bind(this)); - - // All edges between considered child shapes should be considered - // Look for these edges having incoming and outgoing in childShapesToConsider - var edgesToConsider = this.facade.getCanvas().getChildEdges().select(function(edge){ - // Ignore if already added - if(shapesToConsider.include(edge)) return false; - // Ignore if there are no docked shapes - if(edge.getAllDockedShapes().size() === 0) return false; - // True if all docked shapes are in considered child shapes - return edge.getAllDockedShapes().all(function(shape){ - // Remember: Edges can have other edges on outgoing, that is why edges must not be included in childShapesToConsider - return shape instanceof ORYX.Core.Edge || childShapesToConsider.include(shape); + handleMouseOver: function (event, uiObj) { + // If there is a Docker, show this + if (!this.docker && uiObj instanceof ORYX.Core.Controls.Docker) { + uiObj.show(); + } else if (!this.docker && uiObj instanceof ORYX.Core.Edge) { + uiObj.dockers.each(function (docker) { + docker.show(); }); - }); - shapesToConsider = shapesToConsider.concat(edgesToConsider); - - return shapesToConsider; + } }, - /** - * Performs the cut operation by first copy-ing and then deleting the - * current selection. + * DockerDrag Handler + * delegates the uiEvent of the drag event to the mouseDown function */ - editCut: function(){ - //TODO document why this returns false. - //TODO document what the magic boolean parameters are supposed to do. - - this.editCopy(false, true); - this.editDelete(true); - return false; + handleDockerDrag: function (event, uiObj) { + this.handleMouseDown(event.uiEvent, uiObj); }, - + /** - * Performs the copy operation. - * @param {Object} will_not_update ?? + * MouseDown Handler + * */ - editCopy: function( will_update, useNoOffset ){ - var selection = this.facade.getSelection(); - - //if the selection is empty, do not remove the previously copied elements - if(selection.length == 0) return; - - this.clipboard.refresh(selection, this.getAllShapesToConsider(selection), this.facade.getCanvas().getStencil().stencilSet().namespace(), useNoOffset); + handleMouseDown: function (event, uiObj) { + // If there is a Docker + if (uiObj instanceof ORYX.Core.Controls.Docker && uiObj.isMovable) { + + /* Buffering shape selection and clear selection*/ + this.shapeSelection = this.facade.getSelection(); + this.facade.setSelection(); + + this.docker = uiObj; + this.initialDockerPosition = this.docker.bounds.center(); + this.outerDockerNotMoved = false; + this.dockerParent = uiObj.parent; + + // Define command arguments + this._commandArg = { + docker: uiObj, + dockedShape: uiObj.getDockedShape(), + refPoint: uiObj.referencePoint || uiObj.bounds.center() + }; + + // Show the Docker + this.docker.show(); + + // If the Dockers Parent is an Edge, + // and the Docker is either the first or last Docker of the Edge + if (uiObj.parent instanceof ORYX.Core.Edge && + (uiObj.parent.dockers.first() == uiObj || uiObj.parent.dockers.last() == uiObj)) { + + // Get the Edge Source or Target + if (uiObj.parent.dockers.first() == uiObj && uiObj.parent.dockers.last().getDockedShape()) { + this.dockerTarget = uiObj.parent.dockers.last().getDockedShape(); + } else if (uiObj.parent.dockers.last() == uiObj && uiObj.parent.dockers.first().getDockedShape()) { + this.dockerSource = uiObj.parent.dockers.first().getDockedShape(); + } + + } else { + // If there parent is not an Edge, undefined the Source and Target + this.dockerSource = undefined; + this.dockerTarget = undefined; + } + + this.isStartDocker = this.docker.parent.dockers.first() === this.docker; + this.isEndDocker = this.docker.parent.dockers.last() === this.docker; + + // add to canvas while dragging + this.facade.getCanvas().add(this.docker.parent); + + // Hide all Labels from Docker + this.docker.parent.getLabels().each(function (label) { + label.hide(); + }); + + var eventCoordinates = this.facade.eventCoordinates(event); + var additionalIEZoom = 1; + if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) { + var ua = navigator.userAgent; + if (ua.indexOf('MSIE') >= 0) { + //IE 10 and below + var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100); + if (zoom !== 100) { + additionalIEZoom = zoom / 100 + } + } + } + + if (additionalIEZoom !== 1) { + eventCoordinates.x = eventCoordinates.x / additionalIEZoom; + eventCoordinates.y = eventCoordinates.y / additionalIEZoom; + } + + // Undocked the Docker from current Shape + if ((!this.isStartDocker && !this.isEndDocker) || !this.docker.isDocked()) { + + this.docker.setDockedShape(undefined); + // Set the Docker to the center of the mouse pointer + this.docker.bounds.centerMoveTo(eventCoordinates); + this.dockerParent._update(); + } else { + this.outerDockerNotMoved = true; + } + + var option = {movedCallback: this.dockerMoved.bind(this), upCallback: this.dockerMovedFinished.bind(this)}; + + this.startEventPos = eventCoordinates; + + // Enable the Docker for Drag'n'Drop, give the mouseMove and mouseUp-Callback with + ORYX.Core.UIEnableDrag(event, uiObj, option); + } + }, + + /** + * Docker MouseMove Handler + * + */ + dockerMoved: function (event) { + this.outerDockerNotMoved = false; + var snapToMagnet = undefined; + + if (this.docker.parent) { + if (this.isStartDocker || this.isEndDocker) { + + // Get the EventPosition and all Shapes on these point + var evPos = this.facade.eventCoordinates(event); + + var additionalIEZoom = 1; + if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) { + var ua = navigator.userAgent; + if (ua.indexOf('MSIE') >= 0) { + //IE 10 and below + var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100); + if (zoom !== 100) { + additionalIEZoom = zoom / 100 + } + } + } + + if (additionalIEZoom !== 1) { + evPos.x = evPos.x / additionalIEZoom; + evPos.y = evPos.y / additionalIEZoom; + } + + if (this.docker.isDocked()) { + /* Only consider start/end dockers if they are moved over a treshold */ + var distanceDockerPointer = + ORYX.Core.Math.getDistancePointToPoint(evPos, this.initialDockerPosition); + if (distanceDockerPointer < this.undockTreshold) { + this.outerDockerNotMoved = true; + return; + } + + /* Undock the docker */ + this.docker.setDockedShape(undefined); + // Set the Docker to the center of the mouse pointer + //this.docker.bounds.centerMoveTo(evPos); + this.dockerParent._update(); + } + + var shapes = this.facade.getCanvas().getAbstractShapesAtPosition(evPos); + + // Get the top level Shape on these, but not the same as Dockers parent + var uiObj = shapes.pop(); + if (this.docker.parent === uiObj) { + uiObj = shapes.pop(); + } + + // If the top level Shape the same as the last Shape, then return + if (this.lastUIObj == uiObj) { + //return; + + // If the top level uiObj instance of Shape and this isn't the parent of the docker + } else if (uiObj instanceof ORYX.Core.Shape) { + + // Ask by the StencilSet if the source, the edge and the target valid connections. + if (this.docker.parent instanceof ORYX.Core.Edge) { + + var highestParent = this.getHighestParentBeforeCanvas(uiObj); + /* Ensure that the shape to dock is not a child shape + * of the same edge. + */ + if (highestParent instanceof ORYX.Core.Edge && this.docker.parent === highestParent) { + this.isValid = false; + this.dockerParent._update(); + return; + } + this.isValid = false; + var curObj = uiObj, orgObj = uiObj; + while (!this.isValid && curObj && !(curObj instanceof ORYX.Core.Canvas)) { + uiObj = curObj; + this.isValid = this.facade.getRules().canConnect({ + sourceShape: this.dockerSource ? // Is there a docked source + this.dockerSource : // than set this + (this.isStartDocker ? // if not and if the Docker is the start docker + uiObj : // take the last uiObj + undefined), // if not set it to undefined; + edgeShape: this.docker.parent, + targetShape: this.dockerTarget ? // Is there a docked target + this.dockerTarget : // than set this + (this.isEndDocker ? // if not and if the Docker is not the start docker + uiObj : // take the last uiObj + undefined) // if not set it to undefined; + }); + curObj = curObj.parent; + } + + // Reset uiObj if no + // valid parent is found + if (!this.isValid) { + uiObj = orgObj; + } + + } else { + this.isValid = this.facade.getRules().canConnect({ + sourceShape: uiObj, + edgeShape: this.docker.parent, + targetShape: this.docker.parent + }); + } + + // If there is a lastUIObj, hide the magnets + if (this.lastUIObj) { + this.hideMagnets(this.lastUIObj); + } + + // If there is a valid connection, show the magnets + if (this.isValid) { + this.showMagnets(uiObj); + } + + // Set the Highlight Rectangle by these value + this.showHighlight(uiObj, this.isValid ? this.VALIDCOLOR : this.INVALIDCOLOR); + + // Buffer the current Shape + this.lastUIObj = uiObj; + } else { + // If there is no top level Shape, then hide the highligting of the last Shape + this.hideHighlight(); + this.lastUIObj ? this.hideMagnets(this.lastUIObj) : null; + this.lastUIObj = undefined; + this.isValid = false; + } + + // Snap to the nearest Magnet + if (this.lastUIObj && this.isValid && !(event.shiftKey || event.ctrlKey)) { + snapToMagnet = this.lastUIObj.magnets.find(function (magnet) { + return magnet.absoluteBounds().isIncluded(evPos); + }); + + if (snapToMagnet) { + this.docker.bounds.centerMoveTo(snapToMagnet.absoluteCenterXY()); + //this.docker.update() + } + } + } + } + // Snap to on the nearest Docker of the same parent + if (!(event.shiftKey || event.ctrlKey) && !snapToMagnet) { + var minOffset = ORYX.CONFIG.DOCKER_SNAP_OFFSET; + var nearestX = minOffset + 1; + var nearestY = minOffset + 1; + + var dockerCenter = this.docker.bounds.center(); + + if (this.docker.parent) { + + this.docker.parent.dockers.each((function (docker) { + if (this.docker == docker) { + return + } + ; + + var center = docker.referencePoint ? docker.getAbsoluteReferencePoint() : docker.bounds.center(); + + nearestX = Math.abs(nearestX) > Math.abs(center.x - dockerCenter.x) ? center.x - dockerCenter.x : nearestX; + nearestY = Math.abs(nearestY) > Math.abs(center.y - dockerCenter.y) ? center.y - dockerCenter.y : nearestY; + + + }).bind(this)); + + if (Math.abs(nearestX) < minOffset || Math.abs(nearestY) < minOffset) { + nearestX = Math.abs(nearestX) < minOffset ? nearestX : 0; + nearestY = Math.abs(nearestY) < minOffset ? nearestY : 0; + + this.docker.bounds.centerMoveTo(dockerCenter.x + nearestX, dockerCenter.y + nearestY); + //this.docker.update() + } else { + + + var previous = this.docker.parent.dockers[Math.max(this.docker.parent.dockers.indexOf(this.docker) - 1, 0)]; + var next = this.docker.parent.dockers[Math.min(this.docker.parent.dockers.indexOf(this.docker) + 1, this.docker.parent.dockers.length - 1)]; + + if (previous && next && previous !== this.docker && next !== this.docker) { + var cp = previous.bounds.center(); + var cn = next.bounds.center(); + var cd = this.docker.bounds.center(); + + // Checks if the point is on the line between previous and next + if (ORYX.Core.Math.isPointInLine(cd.x, cd.y, cp.x, cp.y, cn.x, cn.y, 10)) { + // Get the rise + var raise = (Number(cn.y) - Number(cp.y)) / (Number(cn.x) - Number(cp.x)); + // Calculate the intersection point + var intersecX = ((cp.y - (cp.x * raise)) - (cd.y - (cd.x * (-Math.pow(raise, -1))))) / ((-Math.pow(raise, -1)) - raise); + var intersecY = (cp.y - (cp.x * raise)) + (raise * intersecX); + + if (isNaN(intersecX) || isNaN(intersecY)) { + return; + } - if( will_update ) this.facade.updateSelection(); + this.docker.bounds.centerMoveTo(intersecX, intersecY); + } + } + + } + } + } + //this.facade.getCanvas().update(); + this.dockerParent._update(); }, - + /** - * Performs the paste operation. + * Docker MouseUp Handler + * */ - editPaste: function(){ - // Create a new canvas with childShapes - //and stencilset namespace to be JSON Import conform - var canvas = { - childShapes: this.clipboard.shapesAsJson, - stencilset:{ - namespace:this.clipboard.SSnamespace - } - }; - // Apply json helper to iterate over json object - jQuery.extend(canvas, ORYX.Core.AbstractShape.JSONHelper); - - var childShapeResourceIds = canvas.getChildShapes(true).pluck("resourceId"); - var outgoings = {}; - // Iterate over all shapes - canvas.eachChild(function(shape, parent){ - // Throw away these references where referenced shape isn't copied - shape.outgoing = shape.outgoing.select(function(out){ - return childShapeResourceIds.include(out.resourceId); - }); - shape.outgoing.each(function(out){ - if (!outgoings[out.resourceId]){ outgoings[out.resourceId] = []; } - outgoings[out.resourceId].push(shape); - }); - - return shape; - }.bind(this), true, true); - + dockerMovedFinished: function (event) { - // Iterate over all shapes - canvas.eachChild(function(shape, parent){ - - // Check if there has a valid target - if(shape.target && !(childShapeResourceIds.include(shape.target.resourceId))){ - shape.target = undefined; - shape.targetRemoved = true; + /* Reset to buffered shape selection */ + this.facade.setSelection(this.shapeSelection); + + // Hide the border + this.hideHighlight(); + + // Show all Labels from Docker + this.dockerParent.getLabels().each(function (label) { + label.show(); + //label.update(); + }); + + // If there is a last top level Shape + if (this.lastUIObj && (this.isStartDocker || this.isEndDocker)) { + // If there is a valid connection, the set as a docked Shape to them + 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 + }); } - - // Check if the first docker is removed - if( shape.dockers && - shape.dockers.length >= 1 && - shape.dockers[0].getDocker && - ((shape.dockers[0].getDocker().getDockedShape() && - !childShapeResourceIds.include(shape.dockers[0].getDocker().getDockedShape().resourceId)) || - !shape.getShape().dockers[0].getDockedShape()&&!outgoings[shape.resourceId])) { - - shape.sourceRemoved = true; - } - - return shape; - }.bind(this), true, true); - - // Iterate over top-level shapes - canvas.eachChild(function(shape, parent){ - // All top-level shapes should get an offset in their bounds - // Move the shape occording to COPY_MOVE_OFFSET - if (this.clipboard.useOffset) { - shape.bounds = { - lowerRight: { - x: shape.bounds.lowerRight.x + ORYX.CONFIG.COPY_MOVE_OFFSET, - y: shape.bounds.lowerRight.y + ORYX.CONFIG.COPY_MOVE_OFFSET - }, - upperLeft: { - x: shape.bounds.upperLeft.x + ORYX.CONFIG.COPY_MOVE_OFFSET, - y: shape.bounds.upperLeft.y + ORYX.CONFIG.COPY_MOVE_OFFSET - } - }; - } - // Only apply offset to shapes with a target - if (shape.dockers){ - shape.dockers = shape.dockers.map(function(docker, i){ - // If shape had a target but the copied does not have anyone anymore, - // migrate the relative dockers to absolute ones. - if( (shape.targetRemoved === true && i == shape.dockers.length - 1&&docker.getDocker) || - (shape.sourceRemoved === true && i == 0&&docker.getDocker)){ + this.hideMagnets(this.lastUIObj); + } - docker = docker.getDocker().bounds.center(); - } + // Hide the Docker + this.docker.hide(); - // If it is the first docker and it has a docked shape, - // just return the coordinates - if ((i == 0 && docker.getDocker instanceof Function && - shape.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)))) || - (i == shape.dockers.length - 1 && docker.getDocker instanceof Function && - shape.targetRemoved !== true && (docker.getDocker().getDockedShape() || shape.target))){ - - return { - x: docker.x, - y: docker.y, - getDocker: docker.getDocker - } - } else if (this.clipboard.useOffset) { - return { - x: docker.x + ORYX.CONFIG.COPY_MOVE_OFFSET, - y: docker.y + ORYX.CONFIG.COPY_MOVE_OFFSET, - getDocker: docker.getDocker - }; - } else { - return { - x: docker.x, - y: docker.y, - getDocker: docker.getDocker - }; - } - }.bind(this)); + if (this.outerDockerNotMoved) { + // Get the EventPosition and all Shapes on these point + var evPos = this.facade.eventCoordinates(event); + var shapes = this.facade.getCanvas().getAbstractShapesAtPosition(evPos); - } 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]))){ - - shape.dockers = shape.dockers.map(function(docker, i){ - - if((shape.sourceRemoved === true && i == 0&&docker.getDocker)){ - docker = docker.getDocker().bounds.center(); + /* Remove edges from selection */ + var shapeWithoutEdges = shapes.findAll(function (node) { + return node instanceof ORYX.Core.Node; + }); + shapes = shapeWithoutEdges.length ? shapeWithoutEdges : shapes; + this.facade.setSelection(shapes); + } else { + //Command-Pattern for dragging one docker + var dragDockerCommand = ORYX.Core.Command.extend({ + construct: function (docker, newPos, oldPos, newDockedShape, oldDockedShape, facade) { + this.docker = docker; + this.index = docker.parent.dockers.indexOf(docker); + this.newPosition = newPos; + this.newDockedShape = newDockedShape; + this.oldPosition = oldPos; + this.oldDockedShape = oldDockedShape; + this.facade = facade; + this.index = docker.parent.dockers.indexOf(docker); + this.shape = docker.parent; + + }, + execute: function () { + if (!this.docker.parent) { + this.docker = this.shape.dockers[this.index]; } - - if (this.clipboard.useOffset) { - return { - x: docker.x + ORYX.CONFIG.COPY_MOVE_OFFSET, - y: docker.y + ORYX.CONFIG.COPY_MOVE_OFFSET, - getDocker: docker.getDocker - }; + 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 (d) { + this.shape.add(d.value, Number(d.key)); + this.shape._update(true); + }.bind(this)); + this.facade.updateSelection(); + }, + dock: function (toDockShape, pos) { + // Set the Docker to the new Shape + this.docker.setDockedShape(undefined); + if (toDockShape) { + this.docker.setDockedShape(toDockShape); + this.docker.setReferencePoint(pos); + //this.docker.update(); + //this.docker.parent._update(); } else { - return { - x: docker.x, - y: docker.y, - getDocker: docker.getDocker - }; + this.docker.bounds.centerMoveTo(pos); } - }.bind(this)); + + this.facade.getCanvas().update(); + } + }); + + + if (this.docker.parent) { + // Instanziate the dockCommand + var 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); + this.facade.executeCommands([command]); } - - return shape; - }.bind(this), false, true); + } - this.clipboard.useOffset = true; - this.facade.importJSON(canvas); + // Update all Shapes + //this.facade.updateSelection(); + + // Undefined all variables + this.docker = undefined; + this.dockerParent = undefined; + this.dockerSource = undefined; + this.dockerTarget = undefined; + this.lastUIObj = undefined; }, - + /** - * Performs the delete operation. No more asking. + * Hide the highlighting */ - editDelete: function(){ - var selection = this.facade.getSelection(); - - var clipboard = new ORYX.Plugins.Edit.ClipBoard(); - clipboard.refresh(selection, this.getAllShapesToConsider(selection)); - - var command = new ORYX.Plugins.Edit.DeleteCommand(clipboard , this.facade); - - this.facade.executeCommands([command]); - } -}); + hideHighlight: function () { + this.facade.raiseEvent({type: ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE, highlightId: 'validDockedShape'}); + }, -ORYX.Plugins.Edit.ClipBoard = Clazz.extend({ - construct: function(){ - this.shapesAsJson = []; - this.selection = []; - this.SSnamespace=""; - this.useOffset=true; + /** + * Show the highlighting + * + */ + showHighlight: function (uiObj, color) { + + this.facade.raiseEvent({ + type: ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW, + highlightId: 'validDockedShape', + elements: [uiObj], + color: color + }); }, - isOccupied: function(){ - return this.shapesAsJson.length > 0; + + showMagnets: function (uiObj) { + uiObj.magnets.each(function (magnet) { + magnet.show(); + }); }, - refresh: function(selection, shapes, namespace, useNoOffset){ - this.selection = selection; - this.SSnamespace=namespace; - // Store outgoings, targets and parents to restore them later on - this.outgoings = {}; - this.parents = {}; - this.targets = {}; - this.useOffset = useNoOffset !== true; - - this.shapesAsJson = shapes.map(function(shape){ - var s = shape.toJSON(); - s.parent = {resourceId : shape.getParentShape().resourceId}; - s.parentIndex = shape.getParentShape().getChildShapes().indexOf(shape) - return s; + + hideMagnets: function (uiObj) { + uiObj.magnets.each(function (magnet) { + magnet.hide(); }); + }, + + getHighestParentBeforeCanvas: function (shape) { + if (!(shape instanceof ORYX.Core.Shape)) { + return undefined; + } + + var parent = shape.parent; + while (parent && !(parent.parent instanceof ORYX.Core.Canvas)) { + parent = parent.parent; + } + + return parent; } + }); -ORYX.Plugins.Edit.DeleteCommand = ORYX.Core.Command.extend({ - construct: function(clipboard, facade){ - this.clipboard = clipboard; - this.shapesAsJson = clipboard.shapesAsJson; - this.facade = facade; - - // Store dockers of deleted shapes to restore connections - this.dockers = this.shapesAsJson.map(function(shapeAsJson) { - var shape = shapeAsJson.getShape(); - var incomingDockers = shape.getIncomingShapes().map(function(s){return s.getDockers().last();}); - var outgoingDockers = shape.getOutgoingShapes().map(function(s){return s.getDockers().first();}); - var dockers = shape.getDockers().concat(incomingDockers, outgoingDockers).compact().map(function(docker){ - return { - object: docker, - referencePoint: docker.referencePoint, - dockedShape: docker.getDockedShape() - }; - }); - return dockers; - }).flatten(); - }, - execute: function(){ - this.shapesAsJson.each(function(shapeAsJson){ - // Delete shape - this.facade.deleteShape(shapeAsJson.getShape()); - }.bind(this)); - - this.facade.setSelection([]); - this.facade.getCanvas().update(); - this.facade.updateSelection(); - - }, - rollback: function(){ - this.shapesAsJson.each(function(shapeAsJson) { - var shape = shapeAsJson.getShape(); - var parent = this.facade.getCanvas().getChildShapeByResourceId(shapeAsJson.parent.resourceId) || this.facade.getCanvas(); - parent.add(shape, shape.parentIndex); - }.bind(this)); - - //reconnect shapes - this.dockers.each(function(d) { - d.object.setDockedShape(d.dockedShape); - d.object.setReferencePoint(d.referencePoint); - }.bind(this)); - - this.facade.setSelection(this.selectedShapes); - this.facade.getCanvas().update(); - this.facade.updateSelection(); - - } -});/* +/* * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. * License rights for this program may be obtained from Alfresco Software, Ltd. * pursuant to a written agreement and any use of this program without such an @@ -17974,240 +22265,127 @@ ORYX.Plugins.Edit.DeleteCommand = ORYX.Core.Command.extend({ * All code Copyright 2013 KIS Consultancy all rights reserved */ -/** - * @namespace Oryx name space for plugins - * @name ORYX.Plugins -*/ -if(!ORYX.Plugins) - ORYX.Plugins = new Object(); +if (!ORYX.Plugins) + ORYX.Plugins = new Object(); -/** - * The view plugin offers all of zooming functionality accessible over the - * tool bar. This are zoom in, zoom out, zoom to standard, zoom fit to model. - * - * @class ORYX.Plugins.View - * @extends Clazz - * @param {Object} facade The editor facade for plugins. -*/ -ORYX.Plugins.View = { - /** @lends ORYX.Plugins.View.prototype */ - facade: undefined, - - construct: function(facade, ownPluginData) { - this.facade = facade; - //Standard Values - this.zoomLevel = 1.0; - this.maxFitToScreenLevel=1.5; - this.minZoomLevel = 0.1; - this.maxZoomLevel = 2.5; - this.diff=5; //difference between canvas and view port, s.th. like toolbar?? - - //Read properties - if (ownPluginData !== undefined && ownPluginData !== null) { - ownPluginData.properties.each( function(property) { - if (property.zoomLevel) {this.zoomLevel = Number(1.0);} - if (property.maxFitToScreenLevel) {this.maxFitToScreenLevel=Number(property.maxFitToScreenLevel);} - if (property.minZoomLevel) {this.minZoomLevel = Number(property.minZoomLevel);} - if (property.maxZoomLevel) {this.maxZoomLevel = Number(property.maxZoomLevel);} - }.bind(this)); - } +ORYX.Plugins.AddDocker = Clazz.extend({ - - /* Register zoom in */ - this.facade.offer({ - 'name':ORYX.I18N.View.zoomIn, - 'functionality': this.zoom.bind(this, [1.0 + 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)}); - - /* Register zoom out */ - this.facade.offer({ - 'name':ORYX.I18N.View.zoomOut, - 'functionality': this.zoom.bind(this, [1.0 - 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)}); - - /* Register zoom standard */ - 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) - }); - - /* Register zoom fit to model */ - 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 - }); - }, - - /** - * It sets the zoom level to a fix value and call the zooming function. - * - * @param {Number} zoomLevel - * the zoom level - */ - setAFixZoomLevel : function(zoomLevel) { - this.zoomLevel = zoomLevel; - this._checkZoomLevelRange(); - this.zoom(1); - }, - - /** - * It does the actual zooming. It changes the viewable size of the canvas - * and all to its child elements. - * - * @param {Number} factor - * the factor to adjust the zoom level - */ - zoom: function(factor) { - // TODO: Zoomen auf allen Objekten im SVG-DOM - - this.zoomLevel *= factor; - var scrollNode = this.facade.getCanvas().getHTMLContainer().parentNode.parentNode; - var canvas = this.facade.getCanvas(); - var newWidth = canvas.bounds.width() * this.zoomLevel; - var newHeight = canvas.bounds.height() * this.zoomLevel; - - /* Set new top offset */ - var offsetTop = (canvas.node.parentNode.parentNode.parentNode.offsetHeight - newHeight) / 2.0; - offsetTop = offsetTop > 20 ? offsetTop - 20 : 0; - canvas.node.parentNode.parentNode.style.marginTop = offsetTop + "px"; - offsetTop += 5; - canvas.getHTMLContainer().style.top = offsetTop + "px"; - - /*readjust scrollbar*/ - var newScrollTop= scrollNode.scrollTop - Math.round((canvas.getHTMLContainer().parentNode.getHeight()-newHeight) / 2)+this.diff; - var newScrollLeft= scrollNode.scrollLeft - Math.round((canvas.getHTMLContainer().parentNode.getWidth()-newWidth) / 2)+this.diff; - - /* Set new Zoom-Level */ - canvas.setSize({width: newWidth, height: newHeight}, true); - - /* Set Scale-Factor */ - canvas.node.setAttributeNS(null, "transform", "scale(" +this.zoomLevel+ ")"); - - /* Refresh the Selection */ - this.facade.updateSelection(); - scrollNode.scrollTop=newScrollTop; - scrollNode.scrollLeft=newScrollLeft; - - /* Update the zoom-level*/ - canvas.zoomLevel = this.zoomLevel; - }, - - - /** - * It calculates the zoom level to fit whole model into the visible area - * of the canvas. Than the model gets zoomed and the position of the - * scroll bars are adjusted. - * - */ - zoomFitToModel: function() { - - /* Get the size of the visible area of the canvas */ - var scrollNode = this.facade.getCanvas().getHTMLContainer().parentNode.parentNode; - var visibleHeight = scrollNode.getHeight() - 30; - var visibleWidth = scrollNode.getWidth() - 30; - - var nodes = this.facade.getCanvas().getChildShapes(); - - if(!nodes || nodes.length < 1) { - return false; - } - - /* Calculate size of canvas to fit the model */ - var bounds = nodes[0].absoluteBounds().clone(); - nodes.each(function(node) { - bounds.include(node.absoluteBounds().clone()); - }); - - - /* Set new Zoom Level */ - var scaleFactorWidth = visibleWidth / bounds.width(); - var scaleFactorHeight = visibleHeight / bounds.height(); - - /* Choose the smaller zoom level to fit the whole model */ - var zoomFactor = scaleFactorHeight < scaleFactorWidth ? scaleFactorHeight : scaleFactorWidth; - - /*Test if maximum zoom is reached*/ - if(zoomFactor>this.maxFitToScreenLevel){zoomFactor=this.maxFitToScreenLevel} - /* Do zooming */ - this.setAFixZoomLevel(zoomFactor); - - /* Set scroll bar position */ - scrollNode.scrollTop = Math.round(bounds.upperLeft().y * this.zoomLevel) - 5; - scrollNode.scrollLeft = Math.round(bounds.upperLeft().x * this.zoomLevel) - 5; - - }, - - /** - * It checks if the zoom level is less or equal to the level, which is required - * to schow the whole canvas. - * - * @private - */ - _checkSize:function(){ - var canvasParent=this.facade.getCanvas().getHTMLContainer().parentNode; - var minForCanvas= Math.min((canvasParent.parentNode.getWidth()/canvasParent.getWidth()),(canvasParent.parentNode.getHeight()/canvasParent.getHeight())); - return 1.05 > minForCanvas; - - }, - /** - * It checks if the zoom level is included in the definined zoom - * level range. - * - * @private - */ - _checkZoomLevelRange: function() { - /*var canvasParent=this.facade.getCanvas().getHTMLContainer().parentNode; - var maxForCanvas= Math.max((canvasParent.parentNode.getWidth()/canvasParent.getWidth()),(canvasParent.parentNode.getHeight()/canvasParent.getHeight())); - if(this.zoomLevel > maxForCanvas) { - this.zoomLevel = maxForCanvas; - }*/ - if(this.zoomLevel < this.minZoomLevel) { - this.zoomLevel = this.minZoomLevel; - } - - if(this.zoomLevel > this.maxZoomLevel) { - this.zoomLevel = this.maxZoomLevel; - } - } -}; + /** + * Constructor + * @param {Object} Facade: The Facade of the Editor + */ + construct: function (facade) { + this.facade = facade; + this.enableAdd = false; + this.enableRemove = false; -ORYX.Plugins.View = Clazz.extend(ORYX.Plugins.View); -/* - * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. - * License rights for this program may be obtained from Alfresco Software, Ltd. - * pursuant to a written agreement and any use of this program without such an - * agreement is prohibited. - */ -if(!Signavio){ var Signavio = {} }; - if (!Signavio.Core) { Signavio.Core = {} }; - Signavio.Core.Version = "1.0"; - /* + this.facade.registerOnEvent(ORYX.CONFIG.EVENT_MOUSEDOWN, this.handleMouseDown.bind(this)); + }, + + setEnableAdd: function (enable) { + this.enableAdd = enable; + + if (this.enableAdd) { + jQuery("#add-bendpoint-button").addClass('pressed'); + } else { + jQuery("#add-bendpoint-button").removeClass('pressed'); + jQuery("#add-bendpoint-button").blur(); + } + }, + setEnableRemove: function (enable) { + this.enableRemove = enable; + + if (this.enableRemove) { + jQuery("#remove-bendpoint-button").addClass('pressed'); + } else { + jQuery("#remove-bendpoint-button").removeClass('pressed'); + jQuery("#remove-bendpoint-button").blur(); + } + }, + + enabledAdd: function (enable) { + return this.enableAdd; + }, + enabledRemove: function () { + return this.enableRemove; + }, + + /** + * MouseDown Handler + * + */ + handleMouseDown: function (event, uiObj) { + if (this.enabledAdd() && uiObj instanceof ORYX.Core.Edge) { + this.newDockerCommand({ + edge: uiObj, + position: this.facade.eventCoordinates(event) + }); + this.setEnableAdd(false); + + } else if (this.enabledRemove() && + uiObj instanceof ORYX.Core.Controls.Docker && + uiObj.parent instanceof ORYX.Core.Edge) { + this.newDockerCommand({ + edge: uiObj.parent, + docker: uiObj + }); + this.setEnableRemove(false); + } + document.body.style.cursor = 'default'; + }, + + // Options: edge (required), position (required if add), docker (required if delete) + newDockerCommand: function (options) { + if (!options.edge) + return; + + var commandClass = ORYX.Core.Command.extend({ + construct: function (addEnabled, deleteEnabled, edge, docker, pos, facade) { + this.addEnabled = addEnabled; + this.deleteEnabled = deleteEnabled; + this.edge = edge; + this.docker = docker; + this.pos = pos; + this.facade = facade; + }, + 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 command = new commandClass(this.enabledAdd(), this.enabledRemove(), options.edge, options.docker, options.position, this.facade); + + this.facade.executeCommands([command]); + } +}); + +/* * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. * License rights for this program may be obtained from Alfresco Software, Ltd. * pursuant to a written agreement and any use of this program without such an @@ -18217,358 +22395,205 @@ if(!Signavio){ var Signavio = {} }; * All code Copyright 2013 KIS Consultancy all rights reserved */ -if (!Signavio) { - var Signavio = new Object(); -} +if (!ORYX.Plugins) + ORYX.Plugins = new Object(); -if (!Signavio.Plugins) { - Signavio.Plugins = new Object(); -} +ORYX.Plugins.SelectionFrame = Clazz.extend({ -if (!Signavio.Plugins.Utils) { - Signavio.Plugins.Utils = new Object(); -} + construct: function (facade) { + this.facade = facade; -if (!Signavio.Helper) { - Signavio.Helper = new Object(); -} + // Register on MouseEvents + this.facade.registerOnEvent(ORYX.CONFIG.EVENT_MOUSEDOWN, this.handleMouseDown.bind(this)); + document.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEUP, this.handleMouseUp.bind(this), true); + // Some initiale variables + this.position = {x: 0, y: 0}; + this.size = {width: 0, height: 0}; + this.offsetPosition = {x: 0, y: 0}; -new function() { + // (Un)Register Mouse-Move Event + this.moveCallback = undefined; + this.offsetScroll = {x: 0, y: 0}; + // HTML-Node of Selection-Frame + this.node = ORYX.Editor.graft("http://www.w3.org/1999/xhtml", $('canvasSection'), + ['div', {'class': 'Oryx_SelectionFrame'}]); - /** - * Provides an uniq id - * @overwrite - * @return {String} - * - */ - ORYX.Editor.provideId = function() { - var res = [], hex = '0123456789ABCDEF'; - - for (var i = 0; i < 36; i++) res[i] = Math.floor(Math.random()*0x10); - - res[14] = 4; - res[19] = (res[19] & 0x3) | 0x8; - - for (var i = 0; i < 36; i++) res[i] = hex[res[i]]; - - res[8] = res[13] = res[18] = res[23] = '-'; - - return "sid-" + res.join(''); - }; + this.hide(); + }, + handleMouseDown: function (event, uiObj) { + // If there is the Canvas + if (uiObj instanceof ORYX.Core.Canvas) { + // Calculate the Offset + var scrollNode = uiObj.rootNode.parentNode.parentNode; -}(); + var a = this.facade.getCanvas().node.getScreenCTM(); + this.offsetPosition = { + x: a.e, + y: a.f + }; -/* - * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. - * License rights for this program may be obtained from Alfresco Software, Ltd. - * pursuant to a written agreement and any use of this program without such an - * agreement is prohibited. - */ -/* - * All code Copyright 2013 KIS Consultancy all rights reserved - */ + // Set the new Position + this.setPos({ + x: Event.pointerX(event) - jQuery("#canvasSection").offset().left, + y: Event.pointerY(event) - jQuery("#canvasSection").offset().top + 5 + }); -if (!ORYX.Plugins) { - ORYX.Plugins = new Object(); -} + // Reset the size + this.resize({width: 0, height: 0}); + this.moveCallback = this.handleMouseMove.bind(this); -/** - * This plugin is responsible for displaying loading indicators and to prevent - * the user from accidently unloading the page by, e.g., pressing the backspace - * button and returning to the previous site in history. - * @param {Object} facade The editor plugin facade to register enhancements with. - */ -ORYX.Plugins.Loading = { + // Register Mouse-Move Event + document.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, this.moveCallback, false); - construct: function(facade){ - - this.facade = facade; - - // The parent Node - 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(); + this.offsetScroll = {x: scrollNode.scrollLeft, y: scrollNode.scrollTop}; + + // Show the Frame + this.show(); + } + + Event.stop(event); }, - - enableLoading: function(options){ - if(options.text) - this.node.innerHTML = options.text + "..."; - else - this.node.innerHTML = ORYX.I18N.Loading.waiting; - this.node.removeClassName('StatusIndicator'); - this.node.addClassName('LoadingIndicator'); - this.node.style.display = "block"; - - var pos = this.facade.getCanvas().rootNode.parentNode.parentNode.parentNode.parentNode; - this.node.style.top = pos.offsetTop + 'px'; - this.node.style.left = pos.offsetLeft +'px'; - + handleMouseUp: function (event) { + // If there was an MouseMoving + if (this.moveCallback) { + // Hide the Frame + this.hide(); + + // Unregister Mouse-Move + document.documentElement.removeEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, this.moveCallback, false); + + this.moveCallback = undefined; + + var corrSVG = this.facade.getCanvas().node.getScreenCTM(); + + // Calculate the positions of the Frame + var a = { + 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 b = { + x: a.x + Math.abs(this.size.width), + y: a.y + Math.abs(this.size.height) + }; + + var additionalIEZoom = 1; + if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) { + var ua = navigator.userAgent; + if (ua.indexOf('MSIE') >= 0) { + //IE 10 and below + var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100); + if (zoom !== 100) { + additionalIEZoom = zoom / 100 + } + } + } + + if (additionalIEZoom === 1) { + a.x = a.x - (corrSVG.e - jQuery("#canvasSection").offset().left); + a.y = a.y - (corrSVG.f - jQuery("#canvasSection").offset().top); + b.x = b.x - (corrSVG.e - jQuery("#canvasSection").offset().left); + b.y = b.y - (corrSVG.f - jQuery("#canvasSection").offset().top); + + } else { + var canvasOffsetLeft = jQuery("#canvasSection").offset().left; + var canvasScrollLeft = jQuery("#canvasSection").scrollLeft(); + var canvasScrollTop = jQuery("#canvasSection").scrollTop(); + + var offset = a.e - (canvasOffsetLeft * additionalIEZoom); + var additionaloffset = 0; + if (offset > 10) { + additionaloffset = (offset / additionalIEZoom) - offset; + } + + a.x = a.x - (corrSVG.e - (canvasOffsetLeft * additionalIEZoom) + additionaloffset + ((canvasScrollLeft * additionalIEZoom) - canvasScrollLeft)); + a.y = a.y - (corrSVG.f - (jQuery("#canvasSection").offset().top * additionalIEZoom) + ((canvasScrollTop * additionalIEZoom) - canvasScrollTop)); + b.x = b.x - (corrSVG.e - (canvasOffsetLeft * additionalIEZoom) + additionaloffset + ((canvasScrollLeft * additionalIEZoom) - canvasScrollLeft)); + b.y = b.y - (corrSVG.f - (jQuery("#canvasSection").offset().top * additionalIEZoom) + ((canvasScrollTop * additionalIEZoom) - canvasScrollTop)); + } + + + // Fit to SVG-Coordinates + a.x /= corrSVG.a; + a.y /= corrSVG.d; + b.x /= corrSVG.a; + b.y /= corrSVG.d; + + // Calculate the elements from the childs of the canvas + var elements = this.facade.getCanvas().getChildShapes(true).findAll(function (value) { + var absBounds = value.absoluteBounds(); + + var bA = absBounds.upperLeft(); + var bB = absBounds.lowerRight(); + + if (bA.x > a.x && bA.y > a.y && bB.x < b.x && bB.y < b.y) + return true; + return false; + }); + + // Set the selection + this.facade.setSelection(elements); + } + }, + + handleMouseMove: function (event) { + // Calculate the size + var size = { + width: Event.pointerX(event) - this.position.x - jQuery("#canvasSection").offset().left, + height: Event.pointerY(event) - this.position.y - jQuery("#canvasSection").offset().top + 5 + }; + + var scrollNode = this.facade.getCanvas().rootNode.parentNode.parentNode; + size.width -= this.offsetScroll.x - scrollNode.scrollLeft; + size.height -= this.offsetScroll.y - scrollNode.scrollTop; + + // Set the size + this.resize(size); + + Event.stop(event); }, - - disableLoading: function(){ + + hide: function () { this.node.style.display = "none"; }, - - showStatus: function(options) { - if(options.text) { - this.node.innerHTML = options.text; - this.node.addClassName('StatusIndicator'); - this.node.removeClassName('LoadingIndicator'); - this.node.style.display = 'block'; - - var pos = this.facade.getCanvas().rootNode.parentNode.parentNode.parentNode.parentNode; - - this.node.style.top = pos.offsetTop + 'px'; - this.node.style.left = pos.offsetLeft +'px'; - - var tout = options.timeout ? options.timeout : 2000; - - window.setTimeout((function(){ - - this.disableLoading(); - - }).bind(this), tout); - } - - } -} -ORYX.Plugins.Loading = Clazz.extend(ORYX.Plugins.Loading); -/* - * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. - * License rights for this program may be obtained from Alfresco Software, Ltd. - * pursuant to a written agreement and any use of this program without such an - * agreement is prohibited. - */ -if (!ORYX.Plugins) { - ORYX.Plugins = new Object(); -} + show: function () { + this.node.style.display = ""; + }, -/* - * All code Copyright 2013 KIS Consultancy all rights reserved - */ + setPos: function (pos) { + // Set the Position + this.node.style.top = pos.y + "px"; + this.node.style.left = pos.x + "px"; + this.position = pos; + }, -/** - * This plugin is responsible for resizing the canvas. - * @param {Object} facade The editor plugin facade to register enhancements with. - */ -ORYX.Plugins.CanvasResize = Clazz.extend({ + resize: function (size) { - construct: function(facade){ - - this.facade = facade; - 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( position, shrink ){ - - resizeCanvas = function(position, extentionSize, facade) { - var canvas = facade.getCanvas(); - var b = canvas.bounds; - var scrollNode = facade.getCanvas().getHTMLContainer().parentNode.parentNode; - - if( position == "E" || position == "W"){ - canvas.setSize({width: (b.width() + extentionSize)*canvas.zoomLevel, height: (b.height())*canvas.zoomLevel}) - - } else if( position == "S" || position == "N"){ - canvas.setSize({width: (b.width())*canvas.zoomLevel, height: (b.height() + extentionSize)*canvas.zoomLevel}) - } - - if( position == "N" || position == "W"){ - - var move = position == "N" ? {x: 0, y: extentionSize}: {x: extentionSize, y: 0 }; - - // Move all children - canvas.getChildNodes(false, function(shape){ shape.bounds.moveBy(move) }) - // Move all dockers, when the edge has at least one docked shape - var edges = canvas.getChildEdges().findAll(function(edge){ return edge.getAllDockedShapes().length > 0}) - var dockers = edges.collect(function(edge){ return edge.dockers.findAll(function(docker){ return !docker.getDockedShape() })}).flatten(); - dockers.each(function(docker){ docker.bounds.moveBy(move)}) - } else if( position == "S" ){ - scrollNode.scrollTop += extentionSize; - } else if( position == "E" ){ - scrollNode.scrollLeft += extentionSize; - } - - jQuery(window).trigger('resize'); - - canvas.update(); - facade.updateSelection(); - } - - var commandClass = ORYX.Core.Command.extend({ - construct: function(position, extentionSize, facade){ - this.position = position; - this.extentionSize = extentionSize; - this.facade = facade; - }, - execute: function(){ - resizeCanvas(this.position, this.extentionSize, this.facade); - }, - rollback: function(){ - resizeCanvas(this.position, -this.extentionSize, this.facade); - }, - update:function(){ - } - }); - - var extentionSize = ORYX.CONFIG.CANVAS_RESIZE_INTERVAL; - if(shrink) extentionSize = -extentionSize; - var command = new commandClass(position, extentionSize, this.facade); - - this.facade.executeCommands([command]); - - } - -}); + // Calculate the negative offset + this.setPos(this.position); + this.size = Object.clone(size); + if (size.width < 0) { + this.node.style.left = (this.position.x + size.width) + "px"; + size.width = -size.width; + } + if (size.height < 0) { + this.node.style.top = (this.position.y + size.height) + "px"; + size.height = -size.height; + } -ORYX.Plugins.CanvasResizeButton = Clazz.extend({ - - construct: function(canvas, position, callback){ - this.canvas = canvas; - var parentNode = canvas.getHTMLContainer().parentNode; - - window.myParent=parentNode; - - var actualScrollNode = jQuery('#canvasSection')[0]; - var scrollNode = actualScrollNode; - var canvasNode = jQuery('#canvasSection').find(".ORYX_Editor")[0]; - var svgRootNode = canvasNode.children[0]; - - var iconClass = 'glyphicon glyphicon-chevron-'; - var iconClassShrink = 'glyphicon glyphicon-chevron-'; - if(position == 'N') { - iconClass += 'up'; - iconClassShrink += 'down'; - } else if(position == 'S') { - iconClass += 'down'; - iconClassShrink += 'up'; - } else if(position == 'E') { - iconClass += 'right'; - iconClassShrink += 'left'; - } else if(position == 'W') { - iconClass += 'left'; - iconClassShrink += 'right'; - } - - // The buttons - var idGrow = 'canvas-shrink-' + position; - var idShrink = 'canvas-grow-' + position; - - var buttonGrow = 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]}, - ['i', {'class' : iconClass}] - ]); - var buttonShrink = 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]}, - ['i', {'class' : iconClassShrink}] - ]); - // Defines a callback which gives back - // a boolean if the current mouse event - // is over the particular button area - var offSetWidth = 60; - var isOverOffset = function(event) { - - var isOverButton = event.target.id.indexOf("canvas-shrink") != -1 - || event.target.id.indexOf("canvas-grow") != -1 - || event.target.parentNode.id.indexOf("canvas-shrink") != -1 - || event.target.parentNode.id.indexOf("canvas-grow") != -1; - if(isOverButton) { - if(event.target.id == idGrow || event.target.id == idShrink || - event.target.parentNode.id == idGrow || event.target.parentNode.id == idShrink ) { - return true; - } else { - return false; - } - } - - if(event.target!=parentNode && event.target!=scrollNode&& event.target!=scrollNode.firstChild&& event.target!=svgRootNode&& event.target!=scrollNode){ return false; } - - //if(inCanvas){offSetWidth=30}else{offSetWidth=30*2} - //Safari work around - var X=event.offsetX !== undefined ? event.offsetX : event.layerX; - var Y=event.offsetY !== undefined ? event.offsetY : event.layerY; - - var canvasOffset = 0; - if(canvasNode.clientWidth < actualScrollNode.clientWidth) { - var widthDiff = actualScrollNode.clientWidth - canvasNode.clientWidth; - canvasOffset = widthDiff / 2; - } - - // Adjust to relative location to the actual viewport - Y = Y - actualScrollNode.scrollTop; - X = X - actualScrollNode.scrollLeft; - - - if(position == "N"){ - return Y < offSetWidth; - } else if(position == "W"){ - return X < offSetWidth + canvasOffset; - } else if(position == "E"){ - return actualScrollNode.clientWidth - X < offSetWidth + canvasOffset; - } else if(position == "S"){ - return actualScrollNode.clientHeight - Y < offSetWidth; - } - - return false; - }; - - var showButtons = (function() { - buttonGrow.show(); - - var w = canvas.bounds.width(); - var h = canvas.bounds.height(); - - if(position=="N" && (h - ORYX.CONFIG.CANVAS_RESIZE_INTERVAL > ORYX.CONFIG.CANVAS_MIN_HEIGHT)) buttonShrink.show(); - else if(position=="E" && (w - ORYX.CONFIG.CANVAS_RESIZE_INTERVAL > ORYX.CONFIG.CANVAS_MIN_WIDTH)) buttonShrink.show(); - else if(position=="S" && (h - ORYX.CONFIG.CANVAS_RESIZE_INTERVAL > ORYX.CONFIG.CANVAS_MIN_HEIGHT)) buttonShrink.show(); - else if(position=="W" && (w - ORYX.CONFIG.CANVAS_RESIZE_INTERVAL > ORYX.CONFIG.CANVAS_MIN_WIDTH)) buttonShrink.show(); - else buttonShrink.hide(); - - - }).bind(this); - - var hideButtons = function() { - buttonGrow.hide(); - buttonShrink.hide(); - }; - - // If the mouse move is over the button area, show the button - parentNode.parentNode.addEventListener( ORYX.CONFIG.EVENT_MOUSEMOVE, function(event){ if( isOverOffset(event) ){showButtons();} else {hideButtons()}} , false ); - // If the mouse is over the button, show them - buttonGrow.addEventListener( ORYX.CONFIG.EVENT_MOUSEOVER, function(event){showButtons();}, true ); - buttonShrink.addEventListener( ORYX.CONFIG.EVENT_MOUSEOVER, function(event){showButtons();}, true ); - // If the mouse is out, hide the button - //scrollNode.addEventListener( ORYX.CONFIG.EVENT_MOUSEOUT, function(event){button.hide()}, true ) - parentNode.parentNode.addEventListener( ORYX.CONFIG.EVENT_MOUSEOUT, function(event){hideButtons()} , true ); - //svgRootNode.addEventListener( ORYX.CONFIG.EVENT_MOUSEOUT, function(event){ inCanvas = false } , true ); - - // Hide the button initialy - hideButtons(); - - // Add the callbacks - buttonGrow.addEventListener('click', function(){callback( position ); showButtons();}, true); - buttonShrink.addEventListener('click', function(){callback( position, true ); showButtons();}, true); - - } - + // Set the size + this.node.style.width = size.width + "px"; + this.node.style.height = size.height + "px"; + } }); + /* * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. * License rights for this program may be obtained from Alfresco Software, Ltd. @@ -18579,399 +22604,237 @@ ORYX.Plugins.CanvasResizeButton = Clazz.extend({ * All code Copyright 2013 KIS Consultancy all rights reserved */ -if (!ORYX.Plugins) +if (!ORYX.Plugins) ORYX.Plugins = new Object(); -ORYX.Plugins.RenameShapes = Clazz.extend({ +ORYX.Plugins.ShapeHighlighting = Clazz.extend({ - facade: undefined, - - construct: function(facade){ - - this.facade = facade; - - 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, // F2-Key - keyAction: ORYX.CONFIG.KEY_ACTION_DOWN - } - ], - functionality: this.renamePerF2.bind(this) - }); - - - document.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEDOWN, this.hide.bind(this), true); - }, - - /** - * This method handles the "F2" key down event. The selected shape are looked - * up and the editing of title/name of it gets started. - */ - renamePerF2 : function() { - var selectedShapes = this.facade.getSelection(); - this.actOnDBLClick(undefined, selectedShapes.first()); - }, - - actOnDBLClick: function(evt, shape){ - - if( !(shape instanceof ORYX.Core.Shape) ){ return; } - - // Destroys the old input, if there is one - this.destroy(); - - // Get all properties which where at least one ref to view is set - var props = shape.getStencil().properties().findAll(function(item){ - return (item.refToView() - && item.refToView().length > 0 - && item.directlyEditable()); - }); - // from these, get all properties where write access are and the type is String or Expression - props = 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); }); - - // Get all ref ids - var allRefToViews = props.collect(function(prop){ return prop.refToView(); }).flatten().compact(); - // Get all labels from the shape with the ref ids - var labels = shape.getLabels().findAll(function(label){ return allRefToViews.any(function(toView){ return label.id.endsWith(toView); }); }); - - // If there are no referenced labels --> return - if( labels.length == 0 ){ return; } - - // Define the nearest label - var nearestLabel = labels.length <= 1 ? labels[0] : null; - if( !nearestLabel ){ - nearestLabel = labels.find(function(label){ return label.node == evt.target || label.node == evt.target.parentNode; }); - if( !nearestLabel ){ - - var evtCoord = this.facade.eventCoordinates(evt); - - var additionalIEZoom = 1; - if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) { - var ua = navigator.userAgent; - if (ua.indexOf('MSIE') >= 0) { - //IE 10 and below - var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100); - if (zoom !== 100) { - additionalIEZoom = zoom / 100 - } - } - } - - if (additionalIEZoom !== 1) { - evtCoord.x = evtCoord.x / additionalIEZoom; - evtCoord.y = evtCoord.y / additionalIEZoom; - } + construct: function (facade) { - evtCoord.y += $("editor-header").clientHeight - $("canvasSection").scrollTop - 5; - if (KISBPM.HEADER_CONFIG.showAppTitle == false) - { - evtCoord.y += 61; - } - - evtCoord.x -= $("canvasSection").scrollLeft; - - var trans = this.facade.getCanvas().rootNode.lastChild.getScreenCTM(); - evtCoord.x *= trans.a; - evtCoord.y *= trans.d; - - var diff = labels.collect(function(label){ - var center = this.getCenterPosition( label.node ); - var len = Math.sqrt( Math.pow(center.x - evtCoord.x, 2) + Math.pow(center.y - evtCoord.y, 2)); - return {diff: len, label: label}; - }.bind(this)); - - diff.sort(function(a, b){ return a.diff > b.diff; }); - - nearestLabel = diff[0].label; + this.parentNode = facade.getCanvas().getSvgContainer(); + + // The parent Node + this.node = ORYX.Editor.graft("http://www.w3.org/2000/svg", this.parentNode, + ['g']); + + this.highlightNodes = {}; + + facade.registerOnEvent(ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW, this.setHighlight.bind(this)); + facade.registerOnEvent(ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE, this.hideHighlight.bind(this)); + + }, + + setHighlight: function (options) { + if (options && options.highlightId) { + var node = this.highlightNodes[options.highlightId]; + + if (!node) { + node = ORYX.Editor.graft("http://www.w3.org/2000/svg", this.node, + ['path', { + "stroke-width": 2.0, "fill": "none" + }]); + + this.highlightNodes[options.highlightId] = node; + } + + if (options.elements && options.elements.length > 0) { + + this.setAttributesByStyle(node, options); + this.show(node); + + } else { + + this.hide(node); - } - } - // Get the particular property for the label - var prop = props.find(function(item){ return item.refToView().any(function(toView){ return nearestLabel.id == shape.id + toView; });}); - - // Get the center position from the nearest label - var width = Math.min(Math.max(100, shape.bounds.width()), 200); - var center = this.getCenterPosition( nearestLabel.node, shape ); - center.x -= (width/2); - var propId = prop.prefix() + "-" + prop.id(); - var textInput = document.createElement("textarea"); - textInput.id = 'shapeTextInput'; - textInput.style.position = 'absolute'; - textInput.style.width = width + 'px'; - textInput.style.left = (center.x < 10) ? 10 : center.x + 'px'; - textInput.style.top = (center.y - 15) + 'px'; - textInput.className = 'x-form-textarea x-form-field x_form_text_set_absolute'; - textInput.value = shape.properties[propId]; - this.oldValueText = shape.properties[propId]; - document.getElementById('canvasSection').appendChild(textInput); - this.shownTextField = textInput; - - - // Value change listener needs to be defined now since we reference it in the text field - this.updateValueFunction = function(newValue, oldValue) { - var currentEl = shape; - var facade = this.facade; - - if (oldValue != newValue) { - // Implement the specific command for property change - var commandClass = ORYX.Core.Command.extend({ - construct: function(){ - this.el = currentEl; - this.propId = propId; - this.oldValue = oldValue; - this.newValue = newValue; - this.facade = facade; - }, - execute: function(){ - this.el.setProperty(this.propId, this.newValue); - //this.el.update(); - this.facade.setSelection([this.el]); - this.facade.getCanvas().update(); - this.facade.updateSelection(); - }, - rollback: function(){ - this.el.setProperty(this.propId, this.oldValue); - //this.el.update(); - this.facade.setSelection([this.el]); - this.facade.getCanvas().update(); - this.facade.updateSelection(); - } - }); - // Instantiated the class - var command = new commandClass(); - - // Execute the command - this.facade.executeCommands([command]); - } - }.bind(this); - - jQuery("#shapeTextInput").focus(); - - jQuery("#shapeTextInput").autogrow(); - - // Disable the keydown in the editor (that when hitting the delete button, the shapes not get deleted) - this.facade.disableEvent(ORYX.CONFIG.EVENT_KEYDOWN); - - }, - - getCenterPosition: function(svgNode, shape){ - - if (!svgNode) { return {x:0, y:0}; } - - var scale = this.facade.getCanvas().node.getScreenCTM(); - var absoluteXY = shape.bounds.upperLeft(); - - var hasParent = true; - var searchShape = shape; - while (hasParent) - { - if (searchShape.getParentShape().getStencil().idWithoutNs() === 'BPMNDiagram') - { - hasParent = false; - } - else - { - var parentXY = searchShape.getParentShape().bounds.upperLeft(); - absoluteXY.x += parentXY.x; - absoluteXY.y += parentXY.y; - searchShape = searchShape.getParentShape(); - } - } - - var center = shape.bounds.midPoint(); - center.x += absoluteXY.x + scale.e; - center.y += absoluteXY.y + scale.f; - - center.x *= scale.a; - center.y *= scale.d; - - var additionalIEZoom = 1; - if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) { - var ua = navigator.userAgent; - if (ua.indexOf('MSIE') >= 0) { - //IE 10 and below - var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100); - if (zoom !== 100) { - additionalIEZoom = zoom / 100 - } } + } - - if (additionalIEZoom === 1) { - center.y = center.y - jQuery("#canvasSection").offset().top + 5; - center.x -= jQuery("#canvasSection").offset().left; - + }, + + hideHighlight: function (options) { + if (options && options.highlightId && this.highlightNodes[options.highlightId]) { + this.hide(this.highlightNodes[options.highlightId]); + } + }, + + hide: function (node) { + node.setAttributeNS(null, 'display', 'none'); + }, + + show: function (node) { + node.setAttributeNS(null, 'display', ''); + }, + + setAttributesByStyle: function (node, options) { + + // If the style say, that it should look like a rectangle + if (options.style && options.style == ORYX.CONFIG.SELECTION_HIGHLIGHT_STYLE_RECTANGLE) { + + // Set like this + var bo = options.elements[0].absoluteBounds(); + + var strWidth = options.strokewidth ? options.strokewidth : ORYX.CONFIG.BORDER_OFFSET + + node.setAttributeNS(null, "d", this.getPathRectangle(bo.a, bo.b, strWidth)); + node.setAttributeNS(null, "stroke", options.color ? options.color : ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR); + node.setAttributeNS(null, "stroke-opacity", options.opacity ? options.opacity : 0.2); + node.setAttributeNS(null, "stroke-width", strWidth); + + } else if (options.elements.length == 1 + && options.elements[0] instanceof ORYX.Core.Edge && + options.highlightId != "selection") { + + /* Highlight containment of edge's childs */ + var path = this.getPathEdge(options.elements[0].dockers); + if (path && path.length > 0) { + node.setAttributeNS(null, "d", path); + } + node.setAttributeNS(null, "stroke", options.color ? options.color : ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR); + node.setAttributeNS(null, "stroke-opacity", options.opacity ? options.opacity : 0.2); + node.setAttributeNS(null, "stroke-width", ORYX.CONFIG.OFFSET_EDGE_BOUNDS); + } else { - var canvasOffsetLeft = jQuery("#canvasSection").offset().left; - var canvasScrollLeft = jQuery("#canvasSection").scrollLeft(); - var canvasScrollTop = jQuery("#canvasSection").scrollTop(); - - var offset = scale.e - (canvasOffsetLeft * additionalIEZoom); - var additionaloffset = 0; - if (offset > 10) { - additionaloffset = (offset / additionalIEZoom) - offset; - } - center.y = center.y - (jQuery("#canvasSection").offset().top * additionalIEZoom) + 5 + ((canvasScrollTop * additionalIEZoom) - canvasScrollTop); - center.x = center.x - (canvasOffsetLeft * additionalIEZoom) + additionaloffset + ((canvasScrollLeft * additionalIEZoom) - canvasScrollLeft); - } - - - return center; - }, - - hide: function(e){ - if (this.shownTextField && (!e || e.target !== this.shownTextField)) { - var newValue = this.shownTextField.value; - if (newValue !== this.oldValueText) - { - this.updateValueFunction(newValue, this.oldValueText); - } - this.destroy(); - } - }, - - hideField: function(e){ - if (this.shownTextField) { - this.destroy(); - } - }, - - destroy: function(e){ - var textInputComp = jQuery("#shapeTextInput"); - if( textInputComp ){ - textInputComp.remove(); - delete this.shownTextField; - - this.facade.enableEvent(ORYX.CONFIG.EVENT_KEYDOWN); - } - } -}); -/* - * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. - * License rights for this program may be obtained from Alfresco Software, Ltd. - * pursuant to a written agreement and any use of this program without such an - * agreement is prohibited. - */ -/* - * All code Copyright 2013 KIS Consultancy all rights reserved - */ + // If not, set just the corners + var path = this.getPathByElements(options.elements); + if (path && path.length > 0) { + node.setAttributeNS(null, "d", path); + } + node.setAttributeNS(null, "stroke", options.color ? options.color : ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR); + node.setAttributeNS(null, "stroke-opacity", options.opacity ? options.opacity : 1.0); + node.setAttributeNS(null, "stroke-width", options.strokewidth ? options.strokewidth : 2.0); -if(!ORYX.Plugins) - ORYX.Plugins = new Object(); + } + }, -/** - * Supports EPCs by offering a syntax check and export and import ability.. - * - * - */ -ORYX.Plugins.ProcessLink = Clazz.extend({ + getPathByElements: function (elements) { + if (!elements || elements.length <= 0) { + return undefined + } - facade: undefined, + // Get the padding and the size + var padding = ORYX.CONFIG.SELECTED_AREA_PADDING; - /** - * Offers the plugin functionality: - * - */ - construct: function(facade) { + var path = "" + + // Get thru all Elements + elements.each((function (element) { + if (!element) { + return + } + // Get the absolute Bounds and the two Points + var bounds = element.absoluteBounds(); + bounds.widen(padding) + var a = bounds.upperLeft(); + var b = bounds.lowerRight(); + + path = path + this.getPath(a, b); + + }).bind(this)); + + return path; + + }, + + getPath: function (a, b) { + + return this.getPathCorners(a, b); + + }, + + getPathCorners: function (a, b) { + + var size = ORYX.CONFIG.SELECTION_HIGHLIGHT_SIZE; + + var path = "" + + // Set: Upper left + path = path + "M" + a.x + " " + (a.y + size) + " l0 -" + size + " l" + size + " 0 "; + // Set: Lower left + path = path + "M" + a.x + " " + (b.y - size) + " l0 " + size + " l" + size + " 0 "; + // Set: Lower right + path = path + "M" + b.x + " " + (b.y - size) + " l0 " + size + " l-" + size + " 0 "; + // Set: Upper right + path = path + "M" + b.x + " " + (a.y + size) + " l0 -" + size + " l-" + size + " 0 "; + + return path; + }, + + getPathRectangle: function (a, b, strokeWidth) { + + var size = ORYX.CONFIG.SELECTION_HIGHLIGHT_SIZE; + + var path = "" + var offset = strokeWidth / 2.0; + + // Set: Upper left + path = path + "M" + (a.x + offset) + " " + (a.y); + path = path + " L" + (a.x + offset) + " " + (b.y - offset); + path = path + " L" + (b.x - offset) + " " + (b.y - offset); + path = path + " L" + (b.x - offset) + " " + (a.y + offset); + path = path + " L" + (a.x + offset) + " " + (a.y + offset); + + return path; + }, + + getPathEdge: function (edgeDockers) { + var length = edgeDockers.length; + var path = "M" + edgeDockers[0].bounds.center().x + " " + + edgeDockers[0].bounds.center().y; + + for (i = 1; i < length; i++) { + var dockerPoint = edgeDockers[i].bounds.center(); + path = path + " L" + dockerPoint.x + " " + dockerPoint.y; + } - this.facade = facade; - - this.facade.registerOnEvent(ORYX.CONFIG.EVENT_PROPERTY_CHANGED, this.propertyChanged.bind(this) ); - - }, + return path; + } +}); - /** - * - * @param {Object} option - */ - propertyChanged: function( option, node){ - - if( option.name !== "oryx-refuri" || !node instanceof ORYX.Core.Node ){ return } - - - if( option.value && option.value.length > 0 && option.value != "undefined"){ - - this.show( node, option.value ); - - } else { - this.hide( node ); +ORYX.Plugins.HighlightingSelectedShapes = Clazz.extend({ - } + construct: function (facade) { + this.facade = facade; + this.opacityFull = 0.9; + this.opacityLow = 0.4; - }, - - /** - * Shows the Link for a particular shape with a specific url - * - * @param {Object} shape - * @param {Object} url - */ - show: function( shape, url){ + // Register on Dragging-Events for show/hide of ShapeMenu + //this.facade.registerOnEvent(ORYX.CONFIG.EVENT_DRAGDROP_START, this.hide.bind(this)); + //this.facade.registerOnEvent(ORYX.CONFIG.EVENT_DRAGDROP_END, this.show.bind(this)); + }, - - // Generate the svg-representation of a link - var link = ORYX.Editor.graft("http://www.w3.org/2000/svg", null , - [ 'a', - {'target': '_blank'}, - ['path', - { "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"} - ] - ]); + /** + * On the Selection-Changed + * + */ + onSelectionChanged: function (event) { + if (event.elements && event.elements.length > 1) { + this.facade.raiseEvent({ + type: ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW, + highlightId: 'selection', + elements: event.elements.without(event.subSelection), + color: ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR, + opacity: !event.subSelection ? this.opacityFull : this.opacityLow + }); - var link = 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"}], - ]); + if (event.subSelection) { + this.facade.raiseEvent({ + type: ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW, + highlightId: 'subselection', + elements: [event.subSelection], + color: ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR, + opacity: this.opacityFull + }); + } else { + this.facade.raiseEvent({type: ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE, highlightId: 'subselection'}); + } - /* - * - * [ 'a', - {'target': '_blank'}, - ['path', { "style": "fill:none;stroke-width:0.5px; stroke:#000000", "d": "M7,4 l0,2"}], - ['path', { "style": "fill:none;stroke-width:0.5px; stroke:#000000", "d": "M4,8 l-2,0 l0,6"}], - ['path', { "style": "fill:none;stroke-width:0.5px; stroke:#000000", "d": "M10,8 l2,0 l0,6"}], - ['rect', { "style": "fill:#96ff96;stroke:#000000;stroke-width:1", "width": 6, "height": 4, "x": 4, "y": 0}], - ['rect', { "style": "fill:#ffafff;stroke:#000000;stroke-width:1", "width": 6, "height": 4, "x": 4, "y": 6}], - ['rect', { "style": "fill:#96ff96;stroke:#000000;stroke-width:1", "width": 6, "height": 4, "x": 0, "y": 12}], - ['rect', { "style": "fill:#96ff96;stroke:#000000;stroke-width:1", "width": 6, "height": 4, "x": 8, "y": 12}], - ['rect', { "style": "fill:none;stroke:none;pointer-events:all", "width": 14, "height": 16, "x": 0, "y": 0}] - ]); - */ - - // Set the link with the special namespace - link.setAttributeNS("http://www.w3.org/1999/xlink", "xlink:href", url); - - - // Shows the link in the overlay - this.facade.raiseEvent({ - type: ORYX.CONFIG.EVENT_OVERLAY_SHOW, - id: "arissupport.urlref_" + shape.id, - shapes: [shape], - node: link, - nodePosition: "SE" - }); - - }, - - /** - * Hides the Link for a particular shape - * - * @param {Object} shape - */ - hide: function( shape ){ - - this.facade.raiseEvent({ - type: ORYX.CONFIG.EVENT_OVERLAY_HIDE, - id: "arissupport.urlref_" + shape.id - }); - - } + } else { + this.facade.raiseEvent({type: ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE, highlightId: 'selection'}); + this.facade.raiseEvent({type: ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE, highlightId: 'subselection'}); + } + } });/* * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. * License rights for this program may be obtained from Alfresco Software, Ltd. @@ -18982,2751 +22845,969 @@ ORYX.Plugins.ProcessLink = Clazz.extend({ * All code Copyright 2013 KIS Consultancy all rights reserved */ -Array.prototype.insertFrom = function(from, to){ - to = Math.max(0, to); - from = Math.min( Math.max(0, from), this.length-1 ); - - var el = this[from]; - var old = this.without(el); - var newA = old.slice(0, to); - newA.push(el); - if(old.length > to ){ - newA = newA.concat(old.slice(to)) - }; - return newA; -} +if (!ORYX.Plugins) + ORYX.Plugins = new Object(); -if(!ORYX.Plugins) - ORYX.Plugins = new Object(); +ORYX.Plugins.Overlay = Clazz.extend({ -ORYX.Plugins.Arrangement = ORYX.Plugins.AbstractPlugin.extend({ + facade: undefined, - facade: undefined, + styleNode: undefined, - construct: function(facade) { - this.facade = facade; + construct: function (facade) { - // Z-Ordering - /** Hide for SIGNAVIO - - this.facade.offer({ - 'name':ORYX.I18N.Arrangement.btf, - 'functionality': this.setZLevel.bind(this, this.setToTop), - 'group': ORYX.I18N.Arrangement.groupZ, - 'icon': ORYX.PATH + "images/shape_move_front.png", - 'description': ORYX.I18N.Arrangement.btfDesc, - 'index': 1, - 'minShape': 1}); - - this.facade.offer({ - 'name':ORYX.I18N.Arrangement.btb, - 'functionality': this.setZLevel.bind(this, this.setToBack), - 'group': ORYX.I18N.Arrangement.groupZ, - 'icon': ORYX.PATH + "images/shape_move_back.png", - 'description': ORYX.I18N.Arrangement.btbDesc, - 'index': 2, - 'minShape': 1}); + this.facade = facade; - this.facade.offer({ - 'name':ORYX.I18N.Arrangement.bf, - 'functionality': this.setZLevel.bind(this, this.setForward), - 'group': ORYX.I18N.Arrangement.groupZ, - 'icon': ORYX.PATH + "images/shape_move_forwards.png", - 'description': ORYX.I18N.Arrangement.bfDesc, - 'index': 3, - 'minShape': 1}); + this.changes = []; - this.facade.offer({ - 'name':ORYX.I18N.Arrangement.bb, - 'functionality': this.setZLevel.bind(this, this.setBackward), - 'group': ORYX.I18N.Arrangement.groupZ, - 'icon': ORYX.PATH + "images/shape_move_backwards.png", - 'description': ORYX.I18N.Arrangement.bbDesc, - 'index': 4, - 'minShape': 1}); + this.facade.registerOnEvent(ORYX.CONFIG.EVENT_OVERLAY_SHOW, this.show.bind(this)); + this.facade.registerOnEvent(ORYX.CONFIG.EVENT_OVERLAY_HIDE, this.hide.bind(this)); - // Aligment - this.facade.offer({ - 'name':ORYX.I18N.Arrangement.ab, - 'functionality': this.alignShapes.bind(this, [ORYX.CONFIG.EDITOR_ALIGN_BOTTOM]), - 'group': ORYX.I18N.Arrangement.groupA, - 'icon': ORYX.PATH + "images/shape_align_bottom.png", - 'description': ORYX.I18N.Arrangement.abDesc, - 'index': 1, - 'minShape': 2}); + this.styleNode = document.createElement('style') + this.styleNode.setAttributeNS(null, 'type', 'text/css') + document.getElementsByTagName('head')[0].appendChild(this.styleNode) + }, - this.facade.offer({ - 'name':ORYX.I18N.Arrangement.at, - 'functionality': this.alignShapes.bind(this, [ORYX.CONFIG.EDITOR_ALIGN_TOP]), - 'group': ORYX.I18N.Arrangement.groupA, - 'icon': ORYX.PATH + "images/shape_align_top.png", - 'description': ORYX.I18N.Arrangement.atDesc, - 'index': 3, - 'minShape': 2}); + /** + * Show the overlay for specific nodes + * @param {Object} options + * + * String options.id - MUST - Define the id of the overlay (is needed for the hiding of this overlay) + * ORYX.Core.Shape[] options.shapes - MUST - Define the Shapes for the changes + * attr-name:value options.changes - Defines all the changes which should be shown + * + * + */ + show: function (options) { - this.facade.offer({ - 'name':ORYX.I18N.Arrangement.al, - 'functionality': this.alignShapes.bind(this, [ORYX.CONFIG.EDITOR_ALIGN_LEFT]), - 'group': ORYX.I18N.Arrangement.groupA, - 'icon': ORYX.PATH + "images/shape_align_left.png", - 'description': ORYX.I18N.Arrangement.alDesc, - 'index': 4, - 'minShape': 2}); + // Checks if all arguments are available + if (!options || + !options.shapes || !options.shapes instanceof Array || + !options.id || !options.id instanceof String || options.id.length == 0) { - this.facade.offer({ - 'name':ORYX.I18N.Arrangement.ar, - 'functionality': this.alignShapes.bind(this, [ORYX.CONFIG.EDITOR_ALIGN_RIGHT]), - 'group': ORYX.I18N.Arrangement.groupA, - 'icon': ORYX.PATH + "images/shape_align_right.png", - 'description': ORYX.I18N.Arrangement.arDesc, - 'index': 6, - 'minShape': 2}); + return - **/ - - 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}); - + //if( this.changes[options.id]){ + // this.hide( options ) + //} - 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) ); + // Checked if attributes are setted + if (options.attributes) { - - }, - - onSelectionChanged: function(elemnt){ - var selection = this.facade.getSelection(); - if (selection.length === 1 && selection[0] instanceof ORYX.Core.Edge) { - this.setToTop(selection); - } - }, - - setZLevel:function(callback, event){ - - //Command-Pattern for dragging one docker - var zLevelCommand = ORYX.Core.Command.extend({ - construct: function(callback, elements, facade){ - this.callback = callback; - this.elements = elements; - // For redo, the previous elements get stored - this.elAndIndex = elements.map(function(el){ return {el:el, previous:el.parent.children[el.parent.children.indexOf(el)-1]} }) - this.facade = facade; - }, - execute: function(){ - - // Call the defined z-order callback with the elements - this.callback( this.elements ) - this.facade.setSelection( this.elements ) - }, - rollback: function(){ - - // Sort all elements on the index of there containment - var sortedEl = this.elAndIndex.sortBy( function( el ) { - var value = el.el; - var t = $A(value.node.parentNode.childNodes); - return t.indexOf(value.node); - }); - - // Every element get setted back bevor the old previous element - for(var i=0; i maxSize.width) { - newBounds.a.x = shape.bounds.upperLeft().x - - (maxSize.width - shape.bounds.width())/2; - - newBounds.b.x = shape.bounds.lowerRight().x + (maxSize.width - shape.bounds.width())/2 - } - - /* If the new height of shape exceeds the maximum height, set height value to maximum. */ - if(this.maxHeight > maxSize.height) { - newBounds.a.y = shape.bounds.upperLeft().y - - (maxSize.height - shape.bounds.height())/2; - - newBounds.b.y = shape.bounds.lowerRight().y + (maxSize.height - shape.bounds.height())/2 - } - - /* set bounds of shape */ - shape.bounds.set(newBounds); - - }, - execute: function(){ - // align each shape according to the way that was specified. - this.elements.each(function(shape, index) { - this.orgPos[index] = shape.bounds.upperLeft(); - - var relBounds = this.bounds.clone(); - var newCoordinates; - if (shape.parent && !(shape.parent instanceof ORYX.Core.Canvas) ) { - var upL = shape.parent.absoluteBounds().upperLeft(); - relBounds.moveBy(-upL.x, -upL.y); - } - - switch (this.way) { - // align the shapes in the requested way. - case ORYX.CONFIG.EDITOR_ALIGN_BOTTOM: - newCoordinates = { - x: shape.bounds.upperLeft().x, - y: relBounds.b.y - shape.bounds.height() - }; break; - - case ORYX.CONFIG.EDITOR_ALIGN_MIDDLE: - newCoordinates = { - x: shape.bounds.upperLeft().x, - y: (relBounds.a.y + relBounds.b.y - shape.bounds.height()) / 2 - }; break; - - case ORYX.CONFIG.EDITOR_ALIGN_TOP: - newCoordinates = { - x: shape.bounds.upperLeft().x, - y: relBounds.a.y - }; break; - - case ORYX.CONFIG.EDITOR_ALIGN_LEFT: - newCoordinates = { - x: relBounds.a.x, - y: shape.bounds.upperLeft().y - }; break; - - case ORYX.CONFIG.EDITOR_ALIGN_CENTER: - newCoordinates = { - x: (relBounds.a.x + relBounds.b.x - shape.bounds.width()) / 2, - y: shape.bounds.upperLeft().y - }; break; - - case ORYX.CONFIG.EDITOR_ALIGN_RIGHT: - newCoordinates = { - x: relBounds.b.x - shape.bounds.width(), - y: shape.bounds.upperLeft().y - }; break; - - case ORYX.CONFIG.EDITOR_ALIGN_SIZE: - if(shape.isResizable) { - this.orgPos[index] = {a: shape.bounds.upperLeft(), b: shape.bounds.lowerRight()}; - this.setBounds(shape, shape.maximumSize); - } - break; - } - - if (newCoordinates){ - var offset = { - x: shape.bounds.upperLeft().x - newCoordinates.x, - y: shape.bounds.upperLeft().y - newCoordinates.y - } - // Set the new position - shape.bounds.moveTo(newCoordinates); - this.plugin.layoutEdges(shape, shape.getAllDockedShapes(),offset); - //shape.update() - } - }.bind(this)); - - //this.facade.getCanvas().update(); - //this.facade.updateSelection(); - }, - rollback: function(){ - this.elements.each(function(shape, index) { - if (this.way == ORYX.CONFIG.EDITOR_ALIGN_SIZE) { - if(shape.isResizable) {shape.bounds.set(this.orgPos[index]);} - } else {shape.bounds.moveTo(this.orgPos[index]);} - }.bind(this)); - - //this.facade.getCanvas().update(); - //this.facade.updateSelection(); - } - }) - - var command = new commandClass(elements, bounds, maxHeight, maxWidth, parseInt(way), this); - - this.facade.executeCommands([command]); - } -});/* - * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. - * License rights for this program may be obtained from Alfresco Software, Ltd. - * pursuant to a written agreement and any use of this program without such an - * agreement is prohibited. - */ -/* - * All code Copyright 2013 KIS Consultancy all rights reserved - */ + _temp.svg.setAttributeNS(null, "transform", "translate(" + x + ", " + y + ")") -if (!ORYX.Plugins) - ORYX.Plugins = new Object(); + }.bind(this) -ORYX.Plugins.Save = Clazz.extend({ - - facade: undefined, - - processURI: undefined, - - changeSymbol : "*", - - construct: function(facade){ - this.facade = facade; - - document.addEventListener("keydown", function(e){ - if (e.ctrlKey&&e.keyCode === 83){ - Event.stop(e); - } - }, false); - - window.onbeforeunload = this.onUnLoad.bind(this); - - this.changeDifference = 0; - - // Register on event for executing commands --> store all commands in a stack - // --> Execute - 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) ); - // --> Saved from other places in the editor - this.facade.registerOnEvent(ORYX.CONFIG.EVENT_SAVED, function(){ this.changeDifference = 0; this.updateTitle(); }.bind(this) ); - - // --> Rollback - this.facade.registerOnEvent(ORYX.CONFIG.EVENT_UNDO_ROLLBACK, function(){ this.changeDifference--; this.updateTitle(); }.bind(this) ); - - //TODO very critical for load time performance!!! - //this.serializedDOM = DataManager.__persistDOM(this.facade); - - this.hasChanges = this._hasChanges.bind(this); - }, - - updateTitle: function(){ - - var value = window.document.title || document.getElementsByTagName("title")[0].childNodes[0].nodeValue; - - if (this.changeDifference === 0 && value.startsWith(this.changeSymbol)){ - window.document.title = value.slice(1); - } else if (this.changeDifference !== 0 && !value.startsWith(this.changeSymbol)){ - window.document.title = this.changeSymbol + "" + value; - } - }, - - _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; - } - } -}); -/* - * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. - * License rights for this program may be obtained from Alfresco Software, Ltd. - * pursuant to a written agreement and any use of this program without such an - * agreement is prohibited. - */ -/* - * All code Copyright 2013 KIS Consultancy all rights reserved - */ + _temp.element = el; + _temp.callback(); -if(!ORYX.Plugins) - ORYX.Plugins = new Object(); + b.registerCallback(_temp.callback); -ORYX.Plugins.DragDropResize = ORYX.Plugins.AbstractPlugin.extend({ + } - /** - * Constructor - * @param {Object} Facade: The Facade of the Editor - */ - construct: function(facade) { - this.facade = facade; - - // Initialize variables - this.currentShapes = []; // Current selected Shapes - //this.pluginsData = []; // Available Plugins - this.toMoveShapes = []; // Shapes there will be moved - this.distPoints = []; // Distance Points for Snap on Grid - this.isResizing = false; // Flag: If there was currently resized - this.dragEnable = false; // Flag: If Dragging is enabled - this.dragIntialized = false; // Flag: If the Dragging is initialized - this.edgesMovable = true; // Flag: If an edge is docked it is not movable - this.offSetPosition = {x: 0, y: 0}; // Offset of the Dragging - this.faktorXY = {x: 1, y: 1}; // The Current Zoom-Faktor - this.containmentParentNode; // the current future parent node for the dragged shapes - this.isAddingAllowed = false; // flag, if adding current selected shapes to containmentParentNode is allowed - this.isAttachingAllowed = false; // flag, if attaching to the current shape is allowed - - this.callbackMouseMove = this.handleMouseMove.bind(this); - this.callbackMouseUp = this.handleMouseUp.bind(this); - - // Get the SVG-Containernode - var containerNode = this.facade.getCanvas().getSvgContainer(); - - // Create the Selected Rectangle in the SVG - this.selectedRect = new ORYX.Plugins.SelectedRect(containerNode); - - // Show grid line if enabled - if (ORYX.CONFIG.SHOW_GRIDLINE) { - this.vLine = new ORYX.Plugins.GridLine(containerNode, ORYX.Plugins.GridLine.DIR_VERTICAL); - this.hLine = new ORYX.Plugins.GridLine(containerNode, ORYX.Plugins.GridLine.DIR_HORIZONTAL); - } - - // Get a HTML-ContainerNode - containerNode = this.facade.getCanvas().getHTMLContainer(); - - this.scrollNode = this.facade.getCanvas().rootNode.parentNode.parentNode; - - // Create the southeastern button for resizing - this.resizerSE = new ORYX.Plugins.Resizer(containerNode, "southeast", this.facade); - this.resizerSE.registerOnResize(this.onResize.bind(this)); // register the resize callback - this.resizerSE.registerOnResizeEnd(this.onResizeEnd.bind(this)); // register the resize end callback - this.resizerSE.registerOnResizeStart(this.onResizeStart.bind(this)); // register the resize start callback - - // Create the northwestern button for resizing - this.resizerNW = new ORYX.Plugins.Resizer(containerNode, "northwest", this.facade); - this.resizerNW.registerOnResize(this.onResize.bind(this)); // register the resize callback - this.resizerNW.registerOnResizeEnd(this.onResizeEnd.bind(this)); // register the resize end callback - this.resizerNW.registerOnResizeStart(this.onResizeStart.bind(this)); // register the resize start callback - - // For the Drag and Drop - // Register on MouseDown-Event on a Shape - this.facade.registerOnEvent(ORYX.CONFIG.EVENT_MOUSEDOWN, this.handleMouseDown.bind(this)); - }, - /** - * On Mouse Down - * - */ - handleMouseDown: function(event, uiObj) { - // If the selection Bounds not intialized and the uiObj is not member of current selectio - // then return - if(!this.dragBounds || !this.currentShapes.member(uiObj) || !this.toMoveShapes.length) {return;}; - - // Start Dragging - this.dragEnable = true; - this.dragIntialized = true; - this.edgesMovable = true; - - // Calculate the current zoom factor - var a = this.facade.getCanvas().node.getScreenCTM(); - this.faktorXY.x = a.a; - this.faktorXY.y = a.d; - - var eventX = Event.pointerX(event); - var eventY = Event.pointerY(event); - - // Set the offset position of dragging - var upL = this.dragBounds.upperLeft(); - this.offSetPosition = { - x: eventX - (upL.x * this.faktorXY.x), - y: eventY - (upL.y * this.faktorXY.y)}; - - this.offsetScroll = {x:this.scrollNode.scrollLeft,y:this.scrollNode.scrollTop}; - - // Register on Global Mouse-MOVE Event - document.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, this.callbackMouseMove, false); - // Register on Global Mouse-UP Event - document.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEUP, this.callbackMouseUp, true); - - return; - }, + options._temps.push(_temp) - /** - * On Key Mouse Up - * - */ - handleMouseUp: function(event) { - - //disable containment highlighting - 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 Dragging is finished - if(this.dragEnable) { - - // and update the current selection - if(!this.dragIntialized) { - - // Do Method after Dragging - this.afterDrag(); - - // Check if the Shape is allowed to dock to the other Shape - if ( this.isAttachingAllowed && - this.toMoveShapes.length == 1 && this.toMoveShapes[0] instanceof ORYX.Core.Node && - this.toMoveShapes[0].dockers.length > 0) { - - // Get the position and the docker - var position = this.facade.eventCoordinates( event ); - var docker = this.toMoveShapes[0].dockers[0]; - - - - //Command-Pattern for dragging several Shapes - var dockCommand = ORYX.Core.Command.extend({ - construct: function(docker, position, newDockedShape, facade){ - this.docker = docker; - this.newPosition = position; - this.newDockedShape = newDockedShape; - this.newParent = newDockedShape.parent || facade.getCanvas(); - this.oldPosition = docker.parent.bounds.center(); - this.oldDockedShape = docker.getDockedShape(); - this.oldParent = docker.parent.parent || facade.getCanvas(); - this.facade = facade; - - if( this.oldDockedShape ){ - this.oldPosition = docker.parent.absoluteBounds().center(); - } - - }, - execute: function(){ - this.dock( this.newDockedShape, this.newParent, this.newPosition ); - - // Raise Event for having the docked shape on top of the other shape - this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_ARRANGEMENT_TOP, excludeCommand: true}) - }, - rollback: function(){ - this.dock( this.oldDockedShape, this.oldParent, this.oldPosition ); - }, - dock:function( toDockShape, parent, pos ){ - // Add to the same parent Shape - parent.add( this.docker.parent ) - - - // Set the Docker to the new Shape - this.docker.setDockedShape( undefined ); - this.docker.bounds.centerMoveTo( pos ) - this.docker.setDockedShape( toDockShape ); - //this.docker.update(); - - this.facade.setSelection( [this.docker.parent] ); - this.facade.getCanvas().update(); - this.facade.updateSelection(); - - - } - }); - - // Instanziate the dockCommand - var commands = [new dockCommand(docker, position, this.containmentParentNode, this.facade)]; - this.facade.executeCommands(commands); - - - // Check if adding is allowed to the other Shape - } else if( this.isAddingAllowed ) { - - - // Refresh all Shapes --> Set the new Bounds - this.refreshSelectedShapes(); - - } - - this.facade.updateSelection(); - - //this.currentShapes.each(function(shape) {shape.update()}) - // Raise Event: Dragging is finished - this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_DRAGDROP_END}); - } - - if (this.vLine) - this.vLine.hide(); - if (this.hLine) - this.hLine.hide(); - } + }.bind(this)) - // Disable - this.dragEnable = false; - - // UnRegister on Global Mouse-UP/-Move Event - document.documentElement.removeEventListener(ORYX.CONFIG.EVENT_MOUSEUP, this.callbackMouseUp, true); - document.documentElement.removeEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, this.callbackMouseMove, false); - - return; - }, + } - /** - * On Key Mouse Move - * - */ - handleMouseMove: function(event) { - // If dragging is not enabled, go return - if(!this.dragEnable) { return }; - // If Dragging is initialized - if(this.dragIntialized) { - // Raise Event: Drag will be started - this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_DRAGDROP_START}); - this.dragIntialized = false; - - // And hide the resizers and the highlighting - this.resizerSE.hide(); - this.resizerNW.hide(); - - // if only edges are selected, containmentParentNode must be the canvas - this._onlyEdges = this.currentShapes.all(function(currentShape) { - return (currentShape instanceof ORYX.Core.Edge); - }); - - // Do method before Drag - this.beforeDrag(); - - this._currentUnderlyingNodes = []; - - } - - // Calculate the new position - var position = { - x: Event.pointerX(event) - this.offSetPosition.x, - y: Event.pointerY(event) - this.offSetPosition.y} - - position.x -= this.offsetScroll.x - this.scrollNode.scrollLeft; - position.y -= this.offsetScroll.y - this.scrollNode.scrollTop; - - // If not the Control-Key are pressed - var modifierKeyPressed = event.shiftKey || event.ctrlKey; - if(ORYX.CONFIG.GRID_ENABLED && !modifierKeyPressed) { - // Snap the current position to the nearest Snap-Point - position = this.snapToGrid(position); - } else { - if (this.vLine) - this.vLine.hide(); - if (this.hLine) - this.hLine.hide(); - } + // Store the changes + if (!this.changes[options.id]) { + this.changes[options.id] = []; + } - // Adjust the point by the zoom faktor - position.x /= this.faktorXY.x; - position.y /= this.faktorXY.y; + this.changes[options.id].push(options); - // Set that the position is not lower than zero - position.x = Math.max( 0 , position.x) - position.y = Math.max( 0 , position.y) + }, - // Set that the position is not bigger than the canvas - var c = this.facade.getCanvas(); - position.x = Math.min( c.bounds.width() - this.dragBounds.width(), position.x) - position.y = Math.min( c.bounds.height() - this.dragBounds.height(), position.y) - + /** + * Hide the overlay with the spefic id + * @param {Object} options + */ + hide: function (options) { - // Drag this bounds - this.dragBounds.moveTo(position); + // Checks if all arguments are available + if (!options || + !options.id || !options.id instanceof String || options.id.length == 0 || + !this.changes[options.id]) { - // Update all selected shapes and the selection rectangle - //this.refreshSelectedShapes(); - this.resizeRectangle(this.dragBounds); + return - this.isAttachingAllowed = false; + } - //check, if a node can be added to the underlying node - var eventCoordinates = this.facade.eventCoordinates(event); - - var additionalIEZoom = 1; - if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) { - var ua = navigator.userAgent; - if (ua.indexOf('MSIE') >= 0) { - //IE 10 and below - var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100); - if (zoom !== 100) { - additionalIEZoom = zoom / 100 + + // Delete all added attributes + // FOR EACH - Shape + this.changes[options.id].each(function (option) { + + option.shapes.each(function (el, index) { + + // Checks if the node is a Shape + if (!el instanceof ORYX.Core.Shape) { + return } - } - } - - if (additionalIEZoom !== 1) { - eventCoordinates.x = eventCoordinates.x / additionalIEZoom; - eventCoordinates.y = eventCoordinates.y / additionalIEZoom; - } - - var underlyingNodes = $A(this.facade.getCanvas().getAbstractShapesAtPosition(eventCoordinates)); - - var checkIfAttachable = this.toMoveShapes.length == 1 && this.toMoveShapes[0] instanceof ORYX.Core.Node && this.toMoveShapes[0].dockers.length > 0 - checkIfAttachable = checkIfAttachable && underlyingNodes.length != 1 - - - if (!checkIfAttachable && - underlyingNodes.length === this._currentUnderlyingNodes.length && - underlyingNodes.all(function(node, index){return this._currentUnderlyingNodes[index] === node}.bind(this))) { - - return - - } else if(this._onlyEdges) { - - this.isAddingAllowed = true; - this.containmentParentNode = this.facade.getCanvas(); - - } else { - - /* Check the containment and connection rules */ - var options = { - event : event, - underlyingNodes : underlyingNodes, - checkIfAttachable : checkIfAttachable - }; - this.checkRules(options); - - } - - this._currentUnderlyingNodes = underlyingNodes.reverse(); - - //visualize the containment result - 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 - }); + this.deleteAttributes(el.node) - } else { + }.bind(this)); - 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" - }); - } - - // Stop the Event - //Event.stop(event); - return; - }, - -// /** -// * Rollbacks the docked shape of an edge, if the edge is not movable. -// */ -// redockEdges: function() { -// this._undockedEdgesCommand.dockers.each(function(el){ -// el.docker.setDockedShape(el.dockedShape); -// el.docker.setReferencePoint(el.refPoint); -// }) -// }, - - /** - * Checks the containment and connection rules for the selected shapes. - */ - checkRules : function(options) { - var event = options.event; - var underlyingNodes = options.underlyingNodes; - var checkIfAttachable = options.checkIfAttachable; - var noEdges = options.noEdges; - - //get underlying node that is not the same than one of the currently selected shapes or - // a child of one of the selected shapes with the highest z Order. - // The result is a shape or the canvas - this.containmentParentNode = underlyingNodes.reverse().find((function(node) { - return (node instanceof ORYX.Core.Canvas) || - (((node instanceof ORYX.Core.Node) || ((node instanceof ORYX.Core.Edge) && !noEdges)) - && (!(this.currentShapes.member(node) || - this.currentShapes.any(function(shape) { - return (shape.children.length > 0 && shape.getChildNodes(true).member(node)); - })))); - }).bind(this)); - - if( checkIfAttachable ){ - - this.isAttachingAllowed = this.facade.getRules().canConnect({ - sourceShape: this.containmentParentNode, - edgeShape: this.toMoveShapes[0], - targetShape: this.toMoveShapes[0] - }); - - if ( this.isAttachingAllowed ) { - var point = this.facade.eventCoordinates(event); - this.isAttachingAllowed = this.containmentParentNode.isPointOverOffset( point.x, point.y ); - } - } - - if( !this.isAttachingAllowed ){ - //check all selected shapes, if they can be added to containmentParentNode - this.isAddingAllowed = this.toMoveShapes.all((function(currentShape) { - if(currentShape instanceof ORYX.Core.Edge || - currentShape instanceof ORYX.Core.Controls.Docker || - this.containmentParentNode === currentShape.parent) { - return true; - } else if(this.containmentParentNode !== currentShape) { - - if(!(this.containmentParentNode instanceof ORYX.Core.Edge) || !noEdges) { - - if(this.facade.getRules().canContain({containingShape:this.containmentParentNode, - containedShape:currentShape})) { - return true; - } - } - } - return false; - }).bind(this)); - } - - if(!this.isAttachingAllowed && !this.isAddingAllowed && - (this.containmentParentNode instanceof ORYX.Core.Edge)) { - options.noEdges = true; - options.underlyingNodes.reverse(); - this.checkRules(options); - } - }, - - /** - * Redraw the selected Shapes. - * - */ - refreshSelectedShapes: function() { - // If the selection bounds not initialized, return - if(!this.dragBounds) {return} - - // Calculate the offset between the bounds and the old bounds - var upL = this.dragBounds.upperLeft(); - var oldUpL = this.oldDragBounds.upperLeft(); - var offset = { - x: upL.x - oldUpL.x, - y: upL.y - oldUpL.y }; - - // Instanciate the dragCommand - var commands = [new ORYX.Core.Command.Move(this.toMoveShapes, offset, this.containmentParentNode, this.currentShapes, this)]; - // If the undocked edges command is setted, add this command - if( this._undockedEdgesCommand instanceof ORYX.Core.Command ){ - commands.unshift( this._undockedEdgesCommand ); - } - // Execute the commands - this.facade.executeCommands( commands ); + if (option._temps) { + + option._temps.each(function (tmp) { + // Delete the added Node, if there is one + if (tmp.svg && tmp.svg.parentNode) { + tmp.svg.parentNode.removeChild(tmp.svg) + } + + // If + if (tmp.callback && tmp.element) { + // It has to be unregistered from the edge + tmp.element.bounds.unregisterCallback(tmp.callback) + } + + }.bind(this)) + + } + + + }.bind(this)); + - // copy the bounds to the old bounds - if( this.dragBounds ) - this.oldDragBounds = this.dragBounds.clone(); + this.changes[options.id] = null; - }, - - /** - * Callback for Resize - * - */ - onResize: function(bounds) { - // If the selection bounds not initialized, return - if(!this.dragBounds) {return} - - this.dragBounds = bounds; - this.isResizing = true; - - // Update the rectangle - 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 Resizing finished, the Shapes will be resize - if(this.isResizing) { - - var commandClass = ORYX.Core.Command.extend({ - construct: function(shape, newBounds, plugin){ - this.shape = shape; - this.oldBounds = shape.bounds.clone(); - this.newBounds = newBounds; - this.plugin = plugin; - }, - 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(b1, b2){ - return { - x: b2.a.x - b1.a.x, - y: b2.a.y - b1.a.y, - xs: b2.width()/b1.width(), - ys: b2.height()/b1.height() - } - }, - update:function(offset){ - this.shape.getLabels().each(function(label) { - label.changed(); - }); - - var allEdges = [].concat(this.shape.getIncomingShapes()) - .concat(this.shape.getOutgoingShapes()) - // Remove all edges which are included in the selection from the list - .findAll(function(r){ return r instanceof ORYX.Core.Edge }.bind(this)) - - this.plugin.layoutEdges(this.shape, allEdges, offset); - - this.plugin.facade.setSelection([this.shape]); - this.plugin.facade.getCanvas().update(); - this.plugin.facade.updateSelection(); - } - }); - - var bounds = this.dragBounds.clone(); - var shape = this.currentShapes[0]; - - if(shape.parent) { - var parentPosition = shape.parent.absoluteXY(); - bounds.moveBy(-parentPosition.x, -parentPosition.y); - } - - var command = new commandClass(shape, bounds, this); - - this.facade.executeCommands([command]); - - this.isResizing = false; - - this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_RESIZE_END}); - } - }, - + }, - /** - * Prepare the Dragging - * - */ - beforeDrag: function(){ - - var undockEdgeCommand = ORYX.Core.Command.extend({ - construct: function(moveShapes){ - this.dockers = moveShapes.collect(function(shape){ return shape instanceof ORYX.Core.Controls.Docker ? {docker:shape, dockedShape:shape.getDockedShape(), refPoint:shape.referencePoint} : undefined }).compact(); - }, - execute: function(){ - this.dockers.each(function(el){ - el.docker.setDockedShape(undefined); - }) - }, - rollback: function(){ - this.dockers.each(function(el){ - el.docker.setDockedShape(el.dockedShape); - el.docker.setReferencePoint(el.refPoint); - //el.docker.update(); - }) - } - }); - - this._undockedEdgesCommand = new undockEdgeCommand( this.toMoveShapes ); - this._undockedEdgesCommand.execute(); - - }, - hideAllLabels: function(shape) { - - // Hide all labels from the shape - shape.getLabels().each(function(label) { - label.hide(); - }); - // Hide all labels from docked shapes - shape.getAllDockedShapes().each(function(dockedShape) { - var labels = dockedShape.getLabels(); - if(labels.length > 0) { - labels.each(function(label) { - label.hide(); - }); - } - }); + /** + * Set the given css attributes to that node + * @param {HTMLElement} node + * @param {Object} attributes + */ + setAttributes: function (node, attributes) { - // Do this recursive for all child shapes - // EXP-NICO use getShapes - shape.getChildren().each((function(value) { - if(value instanceof ORYX.Core.Shape) - this.hideAllLabels(value); - }).bind(this)); - }, - /** - * Finished the Dragging - * - */ - afterDrag: function(){ - - }, + // Get all the childs from ME + var childs = this.getAllChilds(node.firstChild.firstChild) - /** - * Show all Labels at these shape - * - */ - showAllLabels: function(shape) { - - // Show the label of these shape - //shape.getLabels().each(function(label) { - for(var i=0; i 0) { - labels.each(function(label) { - label.show(); - }); - } - }//); - - // Do this recursive - //shape.children.each((function(value) { - for(var i=0; i 2 && hasF && hasL){ - this.toMoveShapes = this.toMoveShapes.concat(dks.findAll(function(el,index){ return index > 0 && index < dks.length-1})); - } - - }).bind(this)); - - // Calculate the new area-bounds of the selection - var newBounds = undefined; - this.toMoveShapes.each(function(value) { - var shape = value; - if(value instanceof ORYX.Core.Controls.Docker) { - /* Get the Shape */ - shape = value.parent; - } - - if(!newBounds){ - newBounds = shape.absoluteBounds(); - } - else { - newBounds.include(shape.absoluteBounds()); - } - }.bind(this)); - - if(!newBounds){ - elements.each(function(value){ - if(!newBounds) { - newBounds = value.absoluteBounds(); - } else { - newBounds.include(value.absoluteBounds()); - } - }); - } - - // Set the new bounds - this.dragBounds = newBounds; - this.oldDragBounds = newBounds.clone(); - - // Update and show the rectangle - this.resizeRectangle(newBounds); - this.selectedRect.show(); - - // Show the resize button, if there is only one element and this is resizeable - if(elements.length == 1 && elements[0].isResizable) { - var aspectRatio = elements[0].getStencil().fixedAspectRatio() ? elements[0].bounds.width() / elements[0].bounds.height() : undefined; - this.resizerSE.setBounds(this.dragBounds, elements[0].minimumSize, elements[0].maximumSize, aspectRatio); - this.resizerSE.show(); - this.resizerNW.setBounds(this.dragBounds, elements[0].minimumSize, elements[0].maximumSize, aspectRatio); - this.resizerNW.show(); - } else { - this.resizerSE.setBounds(undefined); - this.resizerNW.setBounds(undefined); - } + var attr = $H(attributes); + var attrValue = attr.toJSON().gsub(',', ';').gsub('"', ''); + var attrMarkerValue = attributes.stroke ? attrValue.slice(0, attrValue.length - 1) + "; fill:" + attributes.stroke + ";}" : attrValue; + var attrTextValue; + if (attributes.fill) { + var copyAttr = Object.clone(attributes); + copyAttr.fill = "black"; + attrTextValue = $H(copyAttr).toJSON().gsub(',', ';').gsub('"', ''); + } - // If Snap-To-Grid is enabled, the Snap-Point will be calculate - if(ORYX.CONFIG.GRID_ENABLED) { - - // Reset all points - this.distPoints = []; - - if (this.distPointTimeout) - window.clearTimeout(this.distPointTimeout) - - this.distPointTimeout = window.setTimeout(function(){ - // Get all the shapes, there will consider at snapping - // Consider only those elements who shares the same parent element - var distShapes = this.facade.getCanvas().getChildShapes(true).findAll(function(value){ - var parentShape = value.parent; - while(parentShape){ - if(elements.member(parentShape)) return false; - parentShape = parentShape.parent - } - return true; - }) - - // The current selection will delete from this array - //elements.each(function(shape) { - // distShapes = distShapes.without(shape); - //}); - - // For all these shapes - distShapes.each((function(value) { - if(!(value instanceof ORYX.Core.Edge)) { - var ul = value.absoluteXY(); - var width = value.bounds.width(); - var height = value.bounds.height(); - - // Add the upperLeft, center and lowerRight - Point to the distancePoints - this.distPoints.push({ - ul: { - x: ul.x, - y: ul.y - }, - c: { - x: ul.x + (width / 2), - y: ul.y + (height / 2) - }, - lr: { - x: ul.x + width, - y: ul.y + height - } - }); - } - }).bind(this)); - - }.bind(this), 10) + // Create the CSS-Tags Style out of the ids and the attributes + csstags = ids.collect(function (s, i) { + return "#" + s + " * " + (!i ? attrValue : attrMarkerValue) + "" + (attrTextValue ? " #" + s + " text * " + attrTextValue : "") + }) + // Join all the tags + var s = csstags.join(" ") + "\n" - } - } - }, + // And add to the end of the style tag + this.styleNode.appendChild(document.createTextNode(s)); - /** - * Adjust an Point to the Snap Points - * - */ - snapToGrid: function(position) { - - // Get the current Bounds - var bounds = this.dragBounds; - - var point = {}; - - var ulThres = 6; - var cThres = 10; - var lrThres = 6; - - var scale = this.vLine ? this.vLine.getScale() : 1; - - var ul = { x: (position.x/scale), y: (position.y/scale)}; - var c = { x: (position.x/scale) + (bounds.width()/2), y: (position.y/scale) + (bounds.height()/2)}; - var lr = { x: (position.x/scale) + (bounds.width()), y: (position.y/scale) + (bounds.height())}; - - var offsetX, offsetY; - var gridX, gridY; - - // For each distant point - this.distPoints.each(function(value) { - - var x, y, gx, gy; - if (Math.abs(value.c.x-c.x) < cThres){ - x = value.c.x-c.x; - gx = value.c.x; - }/* else if (Math.abs(value.ul.x-ul.x) < ulThres){ - x = value.ul.x-ul.x; - gx = value.ul.x; - } else if (Math.abs(value.lr.x-lr.x) < lrThres){ - x = value.lr.x-lr.x; - gx = value.lr.x; - } */ - - if (Math.abs(value.c.y-c.y) < cThres){ - y = value.c.y-c.y; - gy = value.c.y; - }/* else if (Math.abs(value.ul.y-ul.y) < ulThres){ - y = value.ul.y-ul.y; - gy = value.ul.y; - } else if (Math.abs(value.lr.y-lr.y) < lrThres){ - y = value.lr.y-lr.y; - gy = value.lr.y; - } */ + }, - if (x !== undefined) { - offsetX = offsetX === undefined ? x : (Math.abs(x) < Math.abs(offsetX) ? x : offsetX); - if (offsetX === x) - gridX = gx; - } + /** + * Deletes all attributes which are + * added in a special style sheet for that node + * @param {HTMLElement} node + */ + deleteAttributes: function (node) { - if (y !== undefined) { - offsetY = offsetY === undefined ? y : (Math.abs(y) < Math.abs(offsetY) ? y : offsetY); - if (offsetY === y) - gridY = gy; - } - }); - - - if (offsetX !== undefined) { - ul.x += offsetX; - ul.x *= scale; - if (this.vLine&&gridX) - this.vLine.update(gridX); - } else { - ul.x = (position.x - (position.x % (ORYX.CONFIG.GRID_DISTANCE/2))); - if (this.vLine) - this.vLine.hide() - } - - if (offsetY !== undefined) { - ul.y += offsetY; - ul.y *= scale; - if (this.hLine&&gridY) - this.hLine.update(gridY); - } else { - ul.y = (position.y - (position.y % (ORYX.CONFIG.GRID_DISTANCE/2))); - if (this.hLine) - this.hLine.hide(); - } - - return ul; - }, - - showGridLine: function(){ - - }, + // Get all children which contains the node id + var delEl = $A(this.styleNode.childNodes) + .findAll(function (e) { + return e.textContent.include('#' + node.id) + }); + + // Remove all of them + delEl.each(function (el) { + el.parentNode.removeChild(el); + }); + }, + getAllChilds: function (node) { + + var childs = $A(node.childNodes) + + $A(node.childNodes).each(function (e) { + childs.push(this.getAllChilds(e)) + }.bind(this)) + + return childs.flatten(); + } - /** - * Redraw of the Rectangle of the SelectedArea - * @param {Object} bounds - */ - resizeRectangle: function(bounds) { - // Resize the Rectangle - this.selectedRect.resize(bounds); - } }); +/* + * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +/* + * All code Copyright 2013 KIS Consultancy all rights reserved + */ +if (!ORYX.Plugins) + ORYX.Plugins = new Object(); -ORYX.Plugins.SelectedRect = Clazz.extend({ +ORYX.Plugins.KeysMove = ORYX.Plugins.AbstractPlugin.extend({ + + facade: undefined, - construct: function(parentId) { + construct: function (facade) { - this.parentId = parentId; + this.facade = facade; + this.copyElements = []; - this.node = ORYX.Editor.graft("http://www.w3.org/2000/svg", $(parentId), - ['g']); + //this.facade.registerOnEvent(ORYX.CONFIG.EVENT_KEYDOWN, this.keyHandler.bind(this)); - 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'}]); + // SELECT ALL + 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.hide(); + // MOVE LEFT SMALL + 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) + }); - }, + // MOVE LEFT + 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) + }); - hide: function() { - this.node.setAttributeNS(null, 'display', 'none'); - }, + // MOVE RIGHT SMALL + 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) + }); - show: function() { - this.node.setAttributeNS(null, 'display', ''); - }, + // MOVE RIGHT + 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) + }); - resize: function(bounds) { - var upL = bounds.upperLeft(); + // MOVE UP SMALL + 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) + }); - var padding = ORYX.CONFIG.SELECTED_AREA_PADDING; + // MOVE UP + 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.dashedArea.setAttributeNS(null, 'width', bounds.width() + 2*padding); - this.dashedArea.setAttributeNS(null, 'height', bounds.height() + 2*padding); - this.node.setAttributeNS(null, 'transform', "translate("+ (upL.x - padding) +", "+ (upL.y - padding) +")"); - } + // MOVE DOWN SMALL + 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) + }); + // MOVE DOWN + 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) + }); -}); + }, + /** + * Select all shapes in the editor + * + */ + selectAll: function (e) { + Event.stop(e.event); + this.facade.setSelection(this.facade.getCanvas().getChildShapes(true)) + }, -ORYX.Plugins.GridLine = Clazz.extend({ - - construct: function(parentId, direction) { + move: function (key, far, e) { - if (ORYX.Plugins.GridLine.DIR_HORIZONTAL !== direction && ORYX.Plugins.GridLine.DIR_VERTICAL !== direction) { - direction = ORYX.Plugins.GridLine.DIR_HORIZONTAL - } - - - this.parent = $(parentId); - this.direction = direction; - this.node = ORYX.Editor.graft("http://www.w3.org/2000/svg", this.parent, - ['g']); + Event.stop(e.event); - 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'}]); + // calculate the distance to move the objects and get the selection. + var distance = far ? 20 : 5; + var selection = this.facade.getSelection(); + var currentSelection = this.facade.getSelection(); + var p = {x: 0, y: 0}; + + // switch on the key pressed and populate the point to move by. + switch (key) { + + case ORYX.CONFIG.KEY_CODE_LEFT: + p.x = -1 * distance; + break; + case ORYX.CONFIG.KEY_CODE_RIGHT: + p.x = distance; + break; + case ORYX.CONFIG.KEY_CODE_UP: + p.y = -1 * distance; + break; + case ORYX.CONFIG.KEY_CODE_DOWN: + p.y = distance; + break; + } - this.hide(); + // move each shape in the selection by the point calculated and update it. + selection = selection.findAll(function (shape) { + // Check if this shape is docked to an shape in the selection + if (shape instanceof ORYX.Core.Node && shape.dockers.length == 1 && selection.include(shape.dockers.first().getDockedShape())) { + return false + } - }, + // Check if any of the parent shape is included in the selection + var s = shape.parent; + do { + if (selection.include(s)) { + return false + } + } while (s = s.parent); - hide: function() { - this.node.setAttributeNS(null, 'display', 'none'); - }, + // Otherwise, return true + return true; - show: function() { - this.node.setAttributeNS(null, 'display', ''); - }, + }); - getScale: function(){ - try { - return this.parent.parentNode.transform.baseVal.getItem(0).matrix.a; - } catch(e) { - return 1; - } - }, - - update: function(pos) { - - if (this.direction === ORYX.Plugins.GridLine.DIR_HORIZONTAL) { - var y = pos instanceof Object ? pos.y : pos; - var cWidth = this.parent.parentNode.parentNode.width.baseVal.value/this.getScale(); - this.line.setAttributeNS(null, 'd', 'M 0 '+y+ ' L '+cWidth+' '+y); - } else { - var x = pos instanceof Object ? pos.x : pos; - var cHeight = this.parent.parentNode.parentNode.height.baseVal.value/this.getScale(); - this.line.setAttributeNS(null, 'd', 'M'+x+ ' 0 L '+x+' '+cHeight); - } - - this.show(); - } + /* Edges must not be movable, if only edges are selected and at least + * one of them is docked. + */ + var edgesMovable = true; + var onlyEdgesSelected = selection.all(function (shape) { + if (shape instanceof ORYX.Core.Edge) { + if (shape.isDocked()) { + edgesMovable = false; + } + return true; + } + return false; + }); + if (onlyEdgesSelected && !edgesMovable) { + /* Abort moving shapes */ + return; + } -}); + selection = selection.map(function (shape) { + if (shape instanceof ORYX.Core.Node) { + /*if( shape.dockers.length == 1 ){ + return shape.dockers.first() + } else {*/ + return shape + //} + } else if (shape instanceof ORYX.Core.Edge) { -ORYX.Plugins.GridLine.DIR_HORIZONTAL = "hor"; -ORYX.Plugins.GridLine.DIR_VERTICAL = "ver"; + var dockers = shape.dockers; -ORYX.Plugins.Resizer = Clazz.extend({ + if (selection.include(shape.dockers.first().getDockedShape())) { + dockers = dockers.without(shape.dockers.first()) + } - construct: function(parentId, orientation, facade) { + if (selection.include(shape.dockers.last().getDockedShape())) { + dockers = dockers.without(shape.dockers.last()) + } - this.parentId = parentId; - this.orientation = orientation; - this.facade = facade; - - this.node = ORYX.Editor.graft("http://www.w3.org/1999/xhtml", $('canvasSection'), - ['div', {'class': 'resizer_'+ this.orientation, style:'left:0px; top:0px;position:absolute;'}]); + return dockers - 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); + } else { + return null + } - this.dragEnable = false; - this.offSetPosition = {x: 0, y: 0}; - this.bounds = undefined; + }).flatten().compact(); - this.canvasNode = this.facade.getCanvas().node; + if (selection.size() > 0) { - this.minSize = undefined; - this.maxSize = undefined; - - this.aspectRatio = undefined; + //Stop moving at canvas borders + var selectionBounds = [this.facade.getCanvas().bounds.lowerRight().x, + this.facade.getCanvas().bounds.lowerRight().y, + 0, + 0]; + selection.each(function (s) { + selectionBounds[0] = Math.min(selectionBounds[0], s.bounds.upperLeft().x); + selectionBounds[1] = Math.min(selectionBounds[1], s.bounds.upperLeft().y); + selectionBounds[2] = Math.max(selectionBounds[2], s.bounds.lowerRight().x); + selectionBounds[3] = Math.max(selectionBounds[3], s.bounds.lowerRight().y); + }); + if (selectionBounds[0] + p.x < 0) + p.x = -selectionBounds[0]; + if (selectionBounds[1] + p.y < 0) + p.y = -selectionBounds[1]; + if (selectionBounds[2] + p.x > this.facade.getCanvas().bounds.lowerRight().x) + p.x = this.facade.getCanvas().bounds.lowerRight().x - selectionBounds[2]; + if (selectionBounds[3] + p.y > this.facade.getCanvas().bounds.lowerRight().y) + p.y = this.facade.getCanvas().bounds.lowerRight().y - selectionBounds[3]; + + if (p.x != 0 || p.y != 0) { + // Instantiate the moveCommand + var commands = [new ORYX.Core.Command.Move(selection, p, null, currentSelection, this)]; + // Execute the commands + this.facade.executeCommands(commands); + } - this.resizeCallbacks = []; - this.resizeStartCallbacks = []; - this.resizeEndCallbacks = []; - this.hide(); - - // Calculate the Offset - this.scrollNode = this.node.parentNode.parentNode.parentNode; + } + }, - }, + getUndockedCommant: function (shapes) { + + var undockEdgeCommand = ORYX.Core.Command.extend({ + construct: function (moveShapes) { + this.dockers = moveShapes.collect(function (shape) { + return shape instanceof ORYX.Core.Controls.Docker ? { + docker: shape, + dockedShape: shape.getDockedShape(), + refPoint: shape.referencePoint + } : undefined + }).compact(); + }, + execute: function () { + this.dockers.each(function (el) { + el.docker.setDockedShape(undefined); + }) + }, + rollback: function () { + this.dockers.each(function (el) { + el.docker.setDockedShape(el.dockedShape); + el.docker.setReferencePoint(el.refPoint); + //el.docker.update(); + }) + } + }); - handleMouseDown: function(event) { - this.dragEnable = true; - - this.offsetScroll = {x:this.scrollNode.scrollLeft,y:this.scrollNode.scrollTop}; - - this.offSetPosition = { - x: Event.pointerX(event) - this.position.x, - y: Event.pointerY(event) - this.position.y}; - - this.resizeStartCallbacks.each((function(value) { - value(this.bounds); - }).bind(this)); + command = new undockEdgeCommand(shapes); + command.execute(); + return command; + }, - }, +// /** +// * The key handler for this plugin. Every action from the set of cut, copy, +// * paste and delete should be accessible trough simple keyboard shortcuts. +// * This method checks whether any event triggers one of those actions. +// * +// * @param {Object} event The keyboard event that should be analysed for +// * triggering of this plugin. +// */ +// keyHandler: function(event){ +// //TODO document what event.which is. +// +// ORYX.Log.debug("keysMove.js handles a keyEvent."); +// +// // assure we have the current event. +// if (!event) +// event = window.event; +// +// // get the currently pressed key and state of control key. +// var pressedKey = event.which || event.keyCode; +// var ctrlPressed = event.ctrlKey; +// +// // if the key is one of the arrow keys, forward to move and return. +// if ([ORYX.CONFIG.KEY_CODE_LEFT, ORYX.CONFIG.KEY_CODE_RIGHT, +// ORYX.CONFIG.KEY_CODE_UP, ORYX.CONFIG.KEY_CODE_DOWN].include(pressedKey)) { +// +// this.move(pressedKey, !ctrlPressed); +// return; +// } +// +// } - handleMouseUp: function(event) { - this.dragEnable = false; - this.containmentParentNode = null; - this.resizeEndCallbacks.each((function(value) { - value(this.bounds); - }).bind(this)); - - }, +}); +/* + * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. + * License rights for this program may be obtained from Alfresco Software, Ltd. + * pursuant to a written agreement and any use of this program without such an + * agreement is prohibited. + */ +/* + * All code Copyright 2013 KIS Consultancy all rights reserved + */ - handleMouseMove: function(event) { - if(!this.dragEnable) { return } - - if(event.shiftKey || event.ctrlKey) { - this.aspectRatio = this.bounds.width() / this.bounds.height(); - } else { - this.aspectRatio = undefined; - } +if (!ORYX.Plugins) { + ORYX.Plugins = {} +} +if (!ORYX.Plugins.Layouter) { + ORYX.Plugins.Layouter = {} +} - var position = { - x: Event.pointerX(event) - this.offSetPosition.x, - y: Event.pointerY(event) - this.offSetPosition.y}; - - - position.x -= this.offsetScroll.x - this.scrollNode.scrollLeft; - position.y -= this.offsetScroll.y - this.scrollNode.scrollTop; - - position.x = Math.min( position.x, this.facade.getCanvas().bounds.width()); - position.y = Math.min( position.y, this.facade.getCanvas().bounds.height()); - - var offset = { - x: position.x - this.position.x, - y: position.y - this.position.y - }; - - if(this.aspectRatio) { - // fixed aspect ratio - newAspectRatio = (this.bounds.width()+offset.x) / (this.bounds.height()+offset.y); - if(newAspectRatio>this.aspectRatio) { - offset.x = this.aspectRatio * (this.bounds.height()+offset.y) - this.bounds.width(); - } else if(newAspectRatio this.maxSize.width) { - offset.x = -(this.maxSize.width - this.bounds.width()); - if(this.aspectRatio) - offset.y = this.aspectRatio * offset.x; - } - if(this.bounds.width()-offset.x < this.minSize.width) { - offset.x = -(this.minSize.width - this.bounds.width()); - if(this.aspectRatio) - offset.y = this.aspectRatio * offset.x; - } - if(this.bounds.height()-offset.y > this.maxSize.height) { - offset.y = -(this.maxSize.height - this.bounds.height()); - if(this.aspectRatio) - offset.x = offset.y / this.aspectRatio; - } - if(this.bounds.height()-offset.y < this.minSize.height) { - offset.y = -(this.minSize.height - this.bounds.height()); - if(this.aspectRatio) - offset.x = offset.y / this.aspectRatio; - } - - } else { // defaults to southeast - if(this.bounds.width()+offset.x > this.maxSize.width) { - offset.x = this.maxSize.width - this.bounds.width(); - if(this.aspectRatio) - offset.y = this.aspectRatio * offset.x; - } - if(this.bounds.width()+offset.x < this.minSize.width) { - offset.x = this.minSize.width - this.bounds.width(); - if(this.aspectRatio) - offset.y = this.aspectRatio * offset.x; - } - if(this.bounds.height()+offset.y > this.maxSize.height) { - offset.y = this.maxSize.height - this.bounds.height(); - if(this.aspectRatio) - offset.x = offset.y / this.aspectRatio; - } - if(this.bounds.height()+offset.y < this.minSize.height) { - offset.y = this.minSize.height - this.bounds.height(); - if(this.aspectRatio) - offset.x = offset.y / this.aspectRatio; - } - } +new function () { + + /** + * Edge layouter is an implementation to layout an edge + * @class ORYX.Plugins.Layouter.EdgeLayouter + * @author Willi Tscheschner + */ + ORYX.Plugins.Layouter.EdgeLayouter = ORYX.Plugins.AbstractLayouter.extend({ + + /** + * Layout only Edges + */ + 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"], - if(this.orientation==="northwest") { - this.bounds.extend({x:-offset.x, y:-offset.y}); - this.bounds.moveBy(offset); - } else { // defaults to southeast - this.bounds.extend(offset); - } + /** + * Layout a set on edges + * @param {Object} edges + */ + layout: function (edges) { + edges.each(function (edge) { + this.doLayout(edge) + }.bind(this)) + }, - this.update(); + /** + * Layout one edge + * @param {Object} edge + */ + doLayout: function (edge) { + // Get from and to node + var from = edge.getIncomingNodes()[0]; + var to = edge.getOutgoingNodes()[0]; + + // Return if one is null + if (!from || !to) { + return + } - this.resizeCallbacks.each((function(value) { - value(this.bounds); - }).bind(this)); + var positions = this.getPositions(from, to, edge); - Event.stop(event); + if (positions.length > 0) { + this.setDockers(edge, positions[0].a, positions[0].b); + } - }, - - registerOnResizeStart: function(callback) { - if(!this.resizeStartCallbacks.member(callback)) { - this.resizeStartCallbacks.push(callback); - } - }, - - unregisterOnResizeStart: function(callback) { - if(this.resizeStartCallbacks.member(callback)) { - this.resizeStartCallbacks = this.resizeStartCallbacks.without(callback); - } - }, + }, - registerOnResizeEnd: function(callback) { - if(!this.resizeEndCallbacks.member(callback)) { - this.resizeEndCallbacks.push(callback); - } - }, - - unregisterOnResizeEnd: function(callback) { - if(this.resizeEndCallbacks.member(callback)) { - this.resizeEndCallbacks = this.resizeEndCallbacks.without(callback); - } - }, - - registerOnResize: function(callback) { - if(!this.resizeCallbacks.member(callback)) { - this.resizeCallbacks.push(callback); - } - }, + /** + * Returns a set on positions which are not containt either + * in the bounds in from or to. + * @param {Object} from Shape where the edge is come from + * @param {Object} to Shape where the edge is leading to + * @param {Object} edge Edge between from and to + */ + getPositions: function (from, to, edge) { + + // Get absolute bounds + var ab = from.absoluteBounds(); + var bb = to.absoluteBounds(); + + // Get center from and to + var a = ab.center(); + var b = bb.center(); + + var am = ab.midPoint(); + var bm = bb.midPoint(); + + // Get first and last reference point + var first = Object.clone(edge.dockers.first().referencePoint); + var last = Object.clone(edge.dockers.last().referencePoint); + // Get the absolute one + var aFirst = edge.dockers.first().getAbsoluteReferencePoint(); + var aLast = edge.dockers.last().getAbsoluteReferencePoint(); + + // IF ------> + // or | + // V + // Do nothing + if (Math.abs(aFirst.x - aLast.x) < 1 || Math.abs(aFirst.y - aLast.y) < 1) { + return [] + } - unregisterOnResize: function(callback) { - if(this.resizeCallbacks.member(callback)) { - this.resizeCallbacks = this.resizeCallbacks.without(callback); - } - }, + // Calc center position, between a and b + // depending on there weight + var m = {} + m.x = a.x < b.x ? + (((b.x - bb.width() / 2) - (a.x + ab.width() / 2)) / 2) + (a.x + ab.width() / 2) : + (((a.x - ab.width() / 2) - (b.x + bb.width() / 2)) / 2) + (b.x + bb.width() / 2); - hide: function() { - this.node.style.display = "none"; - }, + m.y = a.y < b.y ? + (((b.y - bb.height() / 2) - (a.y + ab.height() / 2)) / 2) + (a.y + ab.height() / 2) : + (((a.y - ab.height() / 2) - (b.y + bb.height() / 2)) / 2) + (b.y + bb.height() / 2); - show: function() { - if(this.bounds) - this.node.style.display = ""; - }, - setBounds: function(bounds, min, max, aspectRatio) { - this.bounds = bounds; + // Enlarge both bounds with 10 + ab.widen(5); // Wide the from less than + bb.widen(20);// the to because of the arrow from the edge - if(!min) - min = {width: ORYX.CONFIG.MINIMUM_SIZE, height: ORYX.CONFIG.MINIMUM_SIZE}; + var positions = []; + var off = this.getOffset.bind(this); - if(!max) - max = {width: ORYX.CONFIG.MAXIMUM_SIZE, height: ORYX.CONFIG.MAXIMUM_SIZE}; + // Checks ----+ + // | + // V + if (!ab.isIncluded(b.x, a.y) && !bb.isIncluded(b.x, a.y)) { + positions.push({ + a: {x: b.x + off(last, bm, "x"), y: a.y + off(first, am, "y")}, + z: this.getWeight(from, a.x < b.x ? "r" : "l", to, a.y < b.y ? "t" : "b", edge) + }); + } - this.minSize = min; - this.maxSize = max; - - this.aspectRatio = aspectRatio; + // Checks | + // +---> + if (!ab.isIncluded(a.x, b.y) && !bb.isIncluded(a.x, b.y)) { + positions.push({ + a: {x: a.x + off(first, am, "x"), y: b.y + off(last, bm, "y")}, + z: this.getWeight(from, a.y < b.y ? "b" : "t", to, a.x < b.x ? "l" : "r", edge) + }); + } - this.update(); - }, + // Checks --+ + // | + // +---> + if (!ab.isIncluded(m.x, a.y) && !bb.isIncluded(m.x, b.y)) { + positions.push({ + a: {x: m.x, y: a.y + off(first, am, "y")}, + b: {x: m.x, y: b.y + off(last, bm, "y")}, + z: this.getWeight(from, "r", to, "l", edge, a.x > b.x) + }); + } - update: function() { - if(!this.bounds) { return; } - - var upL = this.bounds.upperLeft(); - - if(this.bounds.width() < this.minSize.width) { this.bounds.set(upL.x, upL.y, upL.x + this.minSize.width, upL.y + this.bounds.height());}; - if(this.bounds.height() < this.minSize.height) { this.bounds.set(upL.x, upL.y, upL.x + this.bounds.width(), upL.y + this.minSize.height);}; - if(this.bounds.width() > this.maxSize.width) { this.bounds.set(upL.x, upL.y, upL.x + this.maxSize.width, upL.y + this.bounds.height());}; - if(this.bounds.height() > this.maxSize.height) { this.bounds.set(upL.x, upL.y, upL.x + this.bounds.width(), upL.y + this.maxSize.height);}; - - var a = this.canvasNode.getScreenCTM(); - - upL.x *= a.a; - upL.y *= a.d; - - var additionalIEZoom = 1; - if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) { - var ua = navigator.userAgent; - if (ua.indexOf('MSIE') >= 0) { - //IE 10 and below - var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100); - if (zoom !== 100) { - additionalIEZoom = zoom / 100 - } + // Checks | + // +---+ + // | + // V + if (!ab.isIncluded(a.x, m.y) && !bb.isIncluded(b.x, m.y)) { + positions.push({ + a: {x: a.x + off(first, am, "x"), y: m.y}, + b: {x: b.x + off(last, bm, "x"), y: m.y}, + z: this.getWeight(from, "b", to, "t", edge, a.y > b.y) + }); } - } - - if (additionalIEZoom === 1) { - upL.y = upL.y - jQuery("#canvasSection").offset().top + a.f; - upL.x = upL.x - jQuery("#canvasSection").offset().left + a.e; - - } else { - var canvasOffsetLeft = jQuery("#canvasSection").offset().left; - var canvasScrollLeft = jQuery("#canvasSection").scrollLeft(); - var canvasScrollTop = jQuery("#canvasSection").scrollTop(); - - var offset = a.e - (canvasOffsetLeft * additionalIEZoom); - var additionaloffset = 0; - if (offset > 10) { - additionaloffset = (offset / additionalIEZoom) - offset; - } - upL.y = upL.y - (jQuery("#canvasSection").offset().top * additionalIEZoom) + ((canvasScrollTop * additionalIEZoom) - canvasScrollTop) + a.f; - upL.x = upL.x - (canvasOffsetLeft * additionalIEZoom) + additionaloffset + ((canvasScrollLeft * additionalIEZoom) - canvasScrollLeft) + a.e; - } - - if(this.orientation==="northwest") { - upL.x -= 13; - upL.y -= 13; - } else { // defaults to southeast - upL.x += (a.a * this.bounds.width()) + 3 ; - upL.y += (a.d * this.bounds.height()) + 3; - } - - this.position = upL; - this.node.style.left = this.position.x + "px"; - this.node.style.top = this.position.y + "px"; - } -}); + // Sort DESC of weights + return positions.sort(function (a, b) { + return a.z < b.z ? 1 : (a.z == b.z ? -1 : -1) + }); + }, + /** + * Returns a offset for the pos to the center of the bounds + * + * @param {Object} val + * @param {Object} pos2 + * @param {String} dir Direction x|y + */ + getOffset: function (pos, pos2, dir) { + return pos[dir] - pos2[dir]; + }, + /** + * Returns a value which shows the weight for this configuration + * + * @param {Object} from Shape which is coming from + * @param {String} d1 Direction where is goes + * @param {Object} to Shape which goes to + * @param {String} d2 Direction where it comes to + * @param {Object} edge Edge between from and to + * @param {Boolean} reverse Reverse the direction (e.g. "r" -> "l") + */ + getWeight: function (from, d1, to, d2, edge, reverse) { -/** - * Implements a Command to move shapes - * - */ -ORYX.Core.Command.Move = ORYX.Core.Command.extend({ - construct: function(moveShapes, offset, parent, selectedShapes, plugin){ - this.moveShapes = moveShapes; - this.selectedShapes = selectedShapes; - this.offset = offset; - this.plugin = plugin; - // Defines the old/new parents for the particular shape - this.newParents = moveShapes.collect(function(t){ return parent || t.parent }); - this.oldParents = moveShapes.collect(function(shape){ return shape.parent }); - this.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} }); - }, - execute: function(){ - this.dockAllShapes() - // Moves by the offset - this.move( this.offset); - // Addes to the new parents - this.addShapeToParent( this.newParents ); - // Set the selection to the current selection - this.selectCurrentShapes(); - this.plugin.facade.getCanvas().update(); - this.plugin.facade.updateSelection(); - }, - rollback: function(){ - // Moves by the inverted offset - var offset = { x:-this.offset.x, y:-this.offset.y }; - this.move( offset ); - // Addes to the old parents - this.addShapeToParent( this.oldParents ); - this.dockAllShapes(true) - - // Set the selection to the current selection - this.selectCurrentShapes(); - this.plugin.facade.getCanvas().update(); - this.plugin.facade.updateSelection(); - - }, - move:function(offset, doLayout){ - - // Move all Shapes by these offset - for(var i=0; i i || this.moveShapes.indexOf(r.dockers.last().getDockedShape()) > i}.bind(this)) - - for (var j = 0; j < allSameEdges.length; j++) { - for (var k = 1; k < allSameEdges[j].dockers.length-1; k++) { - var docker = allSameEdges[j].dockers[k]; - if (!docker.getDockedShape() && !this.moveShapes.include(docker)) { - docker.bounds.moveBy(offset); - } - } - } - - /*var i=-1; - var nodes = value.getChildShapes(true); - var allEdges = []; - while(++i= 0) { - //IE 10 and below - var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100); - if (zoom !== 100) { - additionalIEZoom = zoom / 100 - } + var weight = 0; + // Get rules for from "out" and to "in" + var dr1 = this.facade.getRules().getLayoutingRules(from, edge)["out"]; + var dr2 = this.facade.getRules().getLayoutingRules(to, edge)["in"]; + + var fromWeight = dr1[d1]; + var toWeight = dr2[d2]; + + + /** + * Return a true if the center 1 is in the same direction than center 2 + * @param {Object} direction + * @param {Object} center1 + * @param {Object} center2 + */ + var sameDirection = function (direction, center1, center2) { + switch (direction) { + case "t": + return Math.abs(center1.x - center2.x) < 2 && center1.y < center2.y + case "r": + return center1.x > center2.x && Math.abs(center1.y - center2.y) < 2 + case "b": + return Math.abs(center1.x - center2.x) < 2 && center1.y > center2.y + case "l": + return center1.x < center2.x && Math.abs(center1.y - center2.y) < 2 + default: + return false; } } - - if (additionalIEZoom !== 1) { - eventCoordinates.x = eventCoordinates.x / additionalIEZoom; - eventCoordinates.y = eventCoordinates.y / additionalIEZoom; - } - - // Undocked the Docker from current Shape - if ((!this.isStartDocker && !this.isEndDocker) || !this.docker.isDocked()) { - - this.docker.setDockedShape(undefined); - // Set the Docker to the center of the mouse pointer - this.docker.bounds.centerMoveTo(eventCoordinates); - this.dockerParent._update(); - } else { - this.outerDockerNotMoved = true; - } - - var option = {movedCallback: this.dockerMoved.bind(this), upCallback: this.dockerMovedFinished.bind(this)}; - - this.startEventPos = eventCoordinates; - - // Enable the Docker for Drag'n'Drop, give the mouseMove and mouseUp-Callback with - ORYX.Core.UIEnableDrag(event, uiObj, option); - } - }, - - /** - * Docker MouseMove Handler - * - */ - dockerMoved: function(event) { - this.outerDockerNotMoved = false; - var snapToMagnet = undefined; - - if (this.docker.parent) { - if (this.isStartDocker || this.isEndDocker) { - - // Get the EventPosition and all Shapes on these point - var evPos = this.facade.eventCoordinates(event); - - var additionalIEZoom = 1; - if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) { - var ua = navigator.userAgent; - if (ua.indexOf('MSIE') >= 0) { - //IE 10 and below - var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100); - if (zoom !== 100) { - additionalIEZoom = zoom / 100 - } - } - } - - if (additionalIEZoom !== 1) { - evPos.x = evPos.x / additionalIEZoom; - evPos.y = evPos.y / additionalIEZoom; - } - - if(this.docker.isDocked()) { - /* Only consider start/end dockers if they are moved over a treshold */ - var distanceDockerPointer = - ORYX.Core.Math.getDistancePointToPoint(evPos, this.initialDockerPosition); - if(distanceDockerPointer < this.undockTreshold) { - this.outerDockerNotMoved = true; - return; - } - - /* Undock the docker */ - this.docker.setDockedShape(undefined); - // Set the Docker to the center of the mouse pointer - //this.docker.bounds.centerMoveTo(evPos); - this.dockerParent._update(); - } - - var shapes = this.facade.getCanvas().getAbstractShapesAtPosition(evPos); - - // Get the top level Shape on these, but not the same as Dockers parent - var uiObj = shapes.pop(); - if (this.docker.parent === uiObj) { - uiObj = shapes.pop(); - } - - // If the top level Shape the same as the last Shape, then return - if (this.lastUIObj == uiObj) { - //return; - - // If the top level uiObj instance of Shape and this isn't the parent of the docker - } - else - if (uiObj instanceof ORYX.Core.Shape) { - - // Ask by the StencilSet if the source, the edge and the target valid connections. - if (this.docker.parent instanceof ORYX.Core.Edge) { - - var highestParent = this.getHighestParentBeforeCanvas(uiObj); - /* Ensure that the shape to dock is not a child shape - * of the same edge. - */ - if (highestParent instanceof ORYX.Core.Edge && this.docker.parent === highestParent) - { - this.isValid = false; - this.dockerParent._update(); - return; - } - this.isValid = false; - var curObj = uiObj, orgObj = uiObj; - while (!this.isValid && curObj && !(curObj instanceof ORYX.Core.Canvas)) - { - uiObj = curObj; - this.isValid = this.facade.getRules().canConnect({ - sourceShape: this.dockerSource ? // Is there a docked source - this.dockerSource : // than set this - (this.isStartDocker ? // if not and if the Docker is the start docker - uiObj : // take the last uiObj - undefined), // if not set it to undefined; - edgeShape: this.docker.parent, - targetShape: this.dockerTarget ? // Is there a docked target - this.dockerTarget : // than set this - (this.isEndDocker ? // if not and if the Docker is not the start docker - uiObj : // take the last uiObj - undefined) // if not set it to undefined; - }); - curObj = curObj.parent; - } - - // Reset uiObj if no - // valid parent is found - if (!this.isValid){ - uiObj = orgObj; - } - - } - else { - this.isValid = this.facade.getRules().canConnect({ - sourceShape: uiObj, - edgeShape: this.docker.parent, - targetShape: this.docker.parent - }); - } - - // If there is a lastUIObj, hide the magnets - if (this.lastUIObj) { - this.hideMagnets(this.lastUIObj); - } - - // If there is a valid connection, show the magnets - if (this.isValid) { - this.showMagnets(uiObj); - } - - // Set the Highlight Rectangle by these value - this.showHighlight(uiObj, this.isValid ? this.VALIDCOLOR : this.INVALIDCOLOR); - - // Buffer the current Shape - this.lastUIObj = uiObj; - } - else { - // If there is no top level Shape, then hide the highligting of the last Shape - this.hideHighlight(); - this.lastUIObj ? this.hideMagnets(this.lastUIObj) : null; - this.lastUIObj = undefined; - this.isValid = false; - } - - // Snap to the nearest Magnet - if (this.lastUIObj && this.isValid && !(event.shiftKey || event.ctrlKey)) { - snapToMagnet = this.lastUIObj.magnets.find(function(magnet){ - return magnet.absoluteBounds().isIncluded(evPos); - }); - - if (snapToMagnet) { - this.docker.bounds.centerMoveTo(snapToMagnet.absoluteCenterXY()); - //this.docker.update() - } - } - } - } - // Snap to on the nearest Docker of the same parent - if(!(event.shiftKey || event.ctrlKey) && !snapToMagnet) { - var minOffset = ORYX.CONFIG.DOCKER_SNAP_OFFSET; - var nearestX = minOffset + 1; - var nearestY = minOffset + 1; - - var dockerCenter = this.docker.bounds.center(); - - if (this.docker.parent) { - - this.docker.parent.dockers.each((function(docker){ - if (this.docker == docker) { - return - }; - - var center = docker.referencePoint ? docker.getAbsoluteReferencePoint() : docker.bounds.center(); - - nearestX = Math.abs(nearestX) > Math.abs(center.x - dockerCenter.x) ? center.x - dockerCenter.x : nearestX; - nearestY = Math.abs(nearestY) > Math.abs(center.y - dockerCenter.y) ? center.y - dockerCenter.y : nearestY; - - - }).bind(this)); - - if (Math.abs(nearestX) < minOffset || Math.abs(nearestY) < minOffset) { - nearestX = Math.abs(nearestX) < minOffset ? nearestX : 0; - nearestY = Math.abs(nearestY) < minOffset ? nearestY : 0; - - this.docker.bounds.centerMoveTo(dockerCenter.x + nearestX, dockerCenter.y + nearestY); - //this.docker.update() - } else { - - - - var previous = this.docker.parent.dockers[Math.max(this.docker.parent.dockers.indexOf(this.docker)-1, 0)]; - var next = this.docker.parent.dockers[Math.min(this.docker.parent.dockers.indexOf(this.docker)+1, this.docker.parent.dockers.length-1)]; - - if (previous && next && previous !== this.docker && next !== this.docker){ - var cp = previous.bounds.center(); - var cn = next.bounds.center(); - var cd = this.docker.bounds.center(); - - // Checks if the point is on the line between previous and next - if (ORYX.Core.Math.isPointInLine(cd.x, cd.y, cp.x, cp.y, cn.x, cn.y, 10)) { - // Get the rise - var raise = (Number(cn.y)-Number(cp.y))/(Number(cn.x)-Number(cp.x)); - // Calculate the intersection point - var intersecX = ((cp.y-(cp.x*raise))-(cd.y-(cd.x*(-Math.pow(raise,-1)))))/((-Math.pow(raise,-1))-raise); - var intersecY = (cp.y-(cp.x*raise))+(raise*intersecX); - - if(isNaN(intersecX) || isNaN(intersecY)) {return;} - - this.docker.bounds.centerMoveTo(intersecX, intersecY); - } - } - - } - } - } - //this.facade.getCanvas().update(); - this.dockerParent._update(); - }, - - /** - * Docker MouseUp Handler - * - */ - dockerMovedFinished: function(event) { - - /* Reset to buffered shape selection */ - this.facade.setSelection(this.shapeSelection); - - // Hide the border - this.hideHighlight(); - - // Show all Labels from Docker - this.dockerParent.getLabels().each(function(label){ - label.show(); - //label.update(); - }); - - // If there is a last top level Shape - if(this.lastUIObj && (this.isStartDocker || this.isEndDocker)){ - // If there is a valid connection, the set as a docked Shape to them - 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); - } - - // Hide the Docker - this.docker.hide(); - - if(this.outerDockerNotMoved) { - // Get the EventPosition and all Shapes on these point - var evPos = this.facade.eventCoordinates(event); - var shapes = this.facade.getCanvas().getAbstractShapesAtPosition(evPos); - - /* Remove edges from selection */ - var shapeWithoutEdges = shapes.findAll(function(node) { - return node instanceof ORYX.Core.Node; - }); - shapes = shapeWithoutEdges.length ? shapeWithoutEdges : shapes; - this.facade.setSelection(shapes); - } else { - //Command-Pattern for dragging one docker - var dragDockerCommand = ORYX.Core.Command.extend({ - construct: function(docker, newPos, oldPos, newDockedShape, oldDockedShape, facade){ - this.docker = docker; - this.index = docker.parent.dockers.indexOf(docker); - this.newPosition = newPos; - this.newDockedShape = newDockedShape; - this.oldPosition = oldPos; - this.oldDockedShape = oldDockedShape; - this.facade = facade; - this.index = docker.parent.dockers.indexOf(docker); - this.shape = docker.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(d){ - this.shape.add(d.value, Number(d.key)); - this.shape._update(true); - }.bind(this)); - this.facade.updateSelection(); - }, - dock:function( toDockShape, pos ){ - // Set the Docker to the new Shape - this.docker.setDockedShape( undefined ); - if( toDockShape ){ - this.docker.setDockedShape( toDockShape ); - this.docker.setReferencePoint( pos ); - //this.docker.update(); - //this.docker.parent._update(); - } else { - this.docker.bounds.centerMoveTo( pos ); - } - - this.facade.getCanvas().update(); - } - }); - - - if (this.docker.parent){ - // Instanziate the dockCommand - var 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); - this.facade.executeCommands( [command] ); - } - } - - // Update all Shapes - //this.facade.updateSelection(); - - // Undefined all variables - this.docker = undefined; - this.dockerParent = undefined; - this.dockerSource = undefined; - this.dockerTarget = undefined; - this.lastUIObj = undefined; - }, - - /** - * Hide the highlighting - */ - hideHighlight: function() { - this.facade.raiseEvent({type:ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE, highlightId:'validDockedShape'}); - }, - /** - * Show the highlighting - * - */ - showHighlight: function(uiObj, color) { - - this.facade.raiseEvent({ - type: ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW, - highlightId:'validDockedShape', - elements: [uiObj], - color: color - }); - }, - - showMagnets: function(uiObj){ - uiObj.magnets.each(function(magnet) { - magnet.show(); - }); - }, - - hideMagnets: function(uiObj){ - uiObj.magnets.each(function(magnet) { - magnet.hide(); - }); - }, - - getHighestParentBeforeCanvas: function(shape) { - if(!(shape instanceof ORYX.Core.Shape)) {return undefined;} - - var parent = shape.parent; - while(parent && !(parent.parent instanceof ORYX.Core.Canvas)) { - parent = parent.parent; - } - - return parent; - } + // Check if there are same incoming edges from 'from' + var sameIncomingFrom = from + .getIncomingShapes() + .findAll(function (a) { + return a instanceof ORYX.Core.Edge + }) + .any(function (e) { + return sameDirection(d1, e.dockers[e.dockers.length - 2].bounds.center(), e.dockers.last().bounds.center()); + }); -}); + // Check if there are same outgoing edges from 'to' + var sameOutgoingTo = to + .getOutgoingShapes() + .findAll(function (a) { + return a instanceof ORYX.Core.Edge + }) + .any(function (e) { + return sameDirection(d2, e.dockers[1].bounds.center(), e.dockers.first().bounds.center()); + }); -/* - * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. - * License rights for this program may be obtained from Alfresco Software, Ltd. - * pursuant to a written agreement and any use of this program without such an - * agreement is prohibited. - */ -/* - * All code Copyright 2013 KIS Consultancy all rights reserved - */ + // If there are equivalent edges, set 0 + //fromWeight = sameIncomingFrom ? 0 : fromWeight; + //toWeight = sameOutgoingTo ? 0 : toWeight; -if(!ORYX.Plugins) - ORYX.Plugins = new Object(); + // Get the sum of "out" and the direction plus "in" and the direction + return (sameIncomingFrom || sameOutgoingTo ? 0 : fromWeight + toWeight); + }, -ORYX.Plugins.AddDocker = Clazz.extend({ + /** + * Removes all current dockers from the node + * (except the start and end) and adds two new + * dockers, on the position a and b. + * @param {Object} edge + * @param {Object} a + * @param {Object} b + */ + setDockers: function (edge, a, b) { + if (!edge) { + return + } - /** - * Constructor - * @param {Object} Facade: The Facade of the Editor - */ - construct: function(facade) { - this.facade = facade; - this.enableAdd = false; - this.enableRemove = false; - - this.facade.registerOnEvent(ORYX.CONFIG.EVENT_MOUSEDOWN, this.handleMouseDown.bind(this)); - }, - - setEnableAdd: function(enable){ - this.enableAdd = enable; - - if(this.enableAdd) { - jQuery("#add-bendpoint-button").addClass('pressed'); - } else { - jQuery("#add-bendpoint-button").removeClass('pressed'); - jQuery("#add-bendpoint-button").blur(); - } - }, - setEnableRemove: function(enable){ - this.enableRemove = enable; - - if(this.enableRemove) { - jQuery("#remove-bendpoint-button").addClass('pressed'); - } else { - jQuery("#remove-bendpoint-button").removeClass('pressed'); - jQuery("#remove-bendpoint-button").blur(); - } - }, - - enabledAdd: function(enable){ - return this.enableAdd; - }, - enabledRemove: function(){ - return this.enableRemove; - }, - - /** - * MouseDown Handler - * - */ - handleMouseDown: function(event, uiObj) { - if (this.enabledAdd() && uiObj instanceof ORYX.Core.Edge) { - this.newDockerCommand({ - edge: uiObj, - position: this.facade.eventCoordinates(event) + // Remove all dockers (implicit, + // start and end dockers will not removed) + edge.dockers.each(function (r) { + edge.removeDocker(r); }); - this.setEnableAdd(false); - - } else if (this.enabledRemove() && - uiObj instanceof ORYX.Core.Controls.Docker && - uiObj.parent instanceof ORYX.Core.Edge) { - this.newDockerCommand({ - edge: uiObj.parent, - docker: uiObj + + // For a and b (if exists), create + // a new docker and set position + [a, b].compact().each(function (pos) { + var docker = edge.createDocker(undefined, pos); + docker.bounds.centerMoveTo(pos); }); - this.setEnableRemove(false); - } - document.body.style.cursor = 'default'; - }, - - // Options: edge (required), position (required if add), docker (required if delete) - newDockerCommand: function(options){ - if(!options.edge) - return; - var commandClass = ORYX.Core.Command.extend({ - construct: function(addEnabled, deleteEnabled, edge, docker, pos, facade){ - this.addEnabled = addEnabled; - this.deleteEnabled = deleteEnabled; - this.edge = edge; - this.docker = docker; - this.pos = pos; - this.facade = facade; - }, - 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 command = new commandClass(this.enabledAdd(), this.enabledRemove(), options.edge, options.docker, options.position, this.facade); - - this.facade.executeCommands([command]); - } -}); + // Update all dockers from the edge + edge.dockers.each(function (docker) { + docker.update() + }) + + // Update edge + //edge.refresh(); + edge._update(true); + } + }); + + +}() /* * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. * License rights for this program may be obtained from Alfresco Software, Ltd. @@ -21737,2211 +23818,873 @@ ORYX.Plugins.AddDocker = Clazz.extend({ * All code Copyright 2013 KIS Consultancy all rights reserved */ -if(!ORYX.Plugins) - ORYX.Plugins = new Object(); +if (!ORYX.Plugins) + ORYX.Plugins = new Object(); - ORYX.Plugins.SelectionFrame = Clazz.extend({ +new function () { - construct: function(facade) { - this.facade = facade; + ORYX.Plugins.BPMN2_0 = { - // Register on MouseEvents - this.facade.registerOnEvent(ORYX.CONFIG.EVENT_MOUSEDOWN, this.handleMouseDown.bind(this)); - document.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEUP, this.handleMouseUp.bind(this), true); + /** + * Constructor + * @param {Object} Facade: The Facade of the Editor + */ + construct: function (facade) { + this.facade = facade; - // Some initiale variables - this.position = {x:0, y:0}; - this.size = {width:0, height:0}; - this.offsetPosition = {x: 0, y: 0}; + 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)); - // (Un)Register Mouse-Move Event - this.moveCallback = undefined; - this.offsetScroll = {x:0,y:0}; - // HTML-Node of Selection-Frame - this.node = ORYX.Editor.graft("http://www.w3.org/1999/xhtml", $('canvasSection'), - ['div', {'class':'Oryx_SelectionFrame'}]); + this.facade.registerOnEvent(ORYX.CONFIG.EVENT_LOADED, this.afterLoad.bind(this)); - this.hide(); - }, - handleMouseDown: function(event, uiObj) { - // If there is the Canvas - if( uiObj instanceof ORYX.Core.Canvas ) { - // Calculate the Offset - var scrollNode = uiObj.rootNode.parentNode.parentNode; - - var a = this.facade.getCanvas().node.getScreenCTM(); - this.offsetPosition = { - x: a.e, - y: a.f - }; - - // Set the new Position - this.setPos({ - x: Event.pointerX(event) - jQuery("#canvasSection").offset().left, - y: Event.pointerY(event) - jQuery("#canvasSection").offset().top + 5 - }); - - // Reset the size - this.resize({width:0, height:0}); - this.moveCallback = this.handleMouseMove.bind(this); - - // Register Mouse-Move Event - document.documentElement.addEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, this.moveCallback, false); - - this.offsetScroll = {x:scrollNode.scrollLeft,y:scrollNode.scrollTop}; - - // Show the Frame - this.show(); - } + this.namespace = undefined; + }, - Event.stop(event); - }, + /** + * Force to update every pool + */ + afterLoad: function () { + this.facade.getCanvas().getChildNodes().each(function (shape) { + if (shape.getStencil().id().endsWith("Pool")) { + this.handleLayoutPool({ + shape: shape + }); + } + }.bind(this)) + }, - handleMouseUp: function(event) { - // If there was an MouseMoving - if(this.moveCallback) { - // Hide the Frame - this.hide(); - - // Unregister Mouse-Move - document.documentElement.removeEventListener(ORYX.CONFIG.EVENT_MOUSEMOVE, this.moveCallback, false); - - this.moveCallback = undefined; - - var corrSVG = this.facade.getCanvas().node.getScreenCTM(); - - // Calculate the positions of the Frame - var a = { - 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 b = { - x: a.x + Math.abs(this.size.width), - y: a.y + Math.abs(this.size.height) - }; - - var additionalIEZoom = 1; - if (!isNaN(screen.logicalXDPI) && !isNaN(screen.systemXDPI)) { - var ua = navigator.userAgent; - if (ua.indexOf('MSIE') >= 0) { - //IE 10 and below - var zoom = Math.round((screen.deviceXDPI / screen.logicalXDPI) * 100); - if (zoom !== 100) { - additionalIEZoom = zoom / 100 + /** + * If a pool is selected and contains no lane, + * a lane is created automagically + */ + onSelectionChanged: function (event) { + var selection = event.elements; + + if (selection && selection.length === 1) { + var namespace = this.getNamespace(); + var shape = selection[0]; + if (shape.getStencil().idWithoutNs() === "Pool") { + if (shape.getChildNodes().length === 0) { + // create a lane inside the selected pool + var option = { + type: namespace + "Lane", + position: {x: 0, y: 0}, + namespace: shape.getStencil().namespace(), + parent: shape + }; + this.facade.createShape(option); + this.facade.getCanvas().update(); + this.facade.setSelection([shape]); } } } - - if (additionalIEZoom === 1) { - a.x = a.x - (corrSVG.e - jQuery("#canvasSection").offset().left); - a.y = a.y - (corrSVG.f - jQuery("#canvasSection").offset().top); - b.x = b.x - (corrSVG.e - jQuery("#canvasSection").offset().left); - b.y = b.y - (corrSVG.f - jQuery("#canvasSection").offset().top); - - } else { - var canvasOffsetLeft = jQuery("#canvasSection").offset().left; - var canvasScrollLeft = jQuery("#canvasSection").scrollLeft(); - var canvasScrollTop = jQuery("#canvasSection").scrollTop(); - - var offset = a.e - (canvasOffsetLeft * additionalIEZoom); - var additionaloffset = 0; - if (offset > 10) { - additionaloffset = (offset / additionalIEZoom) - offset; - } - - a.x = a.x - (corrSVG.e - (canvasOffsetLeft * additionalIEZoom) + additionaloffset + ((canvasScrollLeft * additionalIEZoom) - canvasScrollLeft)); - a.y = a.y - (corrSVG.f - (jQuery("#canvasSection").offset().top * additionalIEZoom) + ((canvasScrollTop * additionalIEZoom) - canvasScrollTop)); - b.x = b.x - (corrSVG.e - (canvasOffsetLeft * additionalIEZoom) + additionaloffset + ((canvasScrollLeft * additionalIEZoom) - canvasScrollLeft)); - b.y = b.y - (corrSVG.f - (jQuery("#canvasSection").offset().top * additionalIEZoom) + ((canvasScrollTop * additionalIEZoom) - canvasScrollTop)); - } - - - - // Fit to SVG-Coordinates - a.x /= corrSVG.a; a.y /= corrSVG.d; - b.x /= corrSVG.a; b.y /= corrSVG.d; - - // Calculate the elements from the childs of the canvas - var elements = this.facade.getCanvas().getChildShapes(true).findAll(function(value) { - var absBounds = value.absoluteBounds(); - - var bA = absBounds.upperLeft(); - var bB = absBounds.lowerRight(); - - if(bA.x > a.x && bA.y > a.y && bB.x < b.x && bB.y < b.y) - return true; - return false; - }); - - // Set the selection - this.facade.setSelection(elements); - } - }, - - handleMouseMove: function(event) { - // Calculate the size - var size = { - width : Event.pointerX(event) - this.position.x - jQuery("#canvasSection").offset().left, - height : Event.pointerY(event) - this.position.y - jQuery("#canvasSection").offset().top + 5 - }; - - var scrollNode = this.facade.getCanvas().rootNode.parentNode.parentNode; - size.width -= this.offsetScroll.x - scrollNode.scrollLeft; - size.height -= this.offsetScroll.y - scrollNode.scrollTop; - - // Set the size - this.resize(size); - - Event.stop(event); - }, - - hide: function() { - this.node.style.display = "none"; - }, - - show: function() { - this.node.style.display = ""; - }, - setPos: function(pos) { - // Set the Position - this.node.style.top = pos.y + "px"; - this.node.style.left = pos.x + "px"; - this.position = pos; - }, - - resize: function(size) { - - // Calculate the negative offset - this.setPos(this.position); - this.size = Object.clone(size); - - if(size.width < 0) { - this.node.style.left = (this.position.x + size.width) + "px"; - size.width = - size.width; - } - if(size.height < 0) { - this.node.style.top = (this.position.y + size.height) + "px"; - size.height = - size.height; - } + // Preventing selection of all lanes but not the pool + if (selection.any(function (s) { + return s instanceof ORYX.Core.Node && s.getStencil().id().endsWith("Lane") + })) { + var lanes = selection.findAll(function (s) { + return s instanceof ORYX.Core.Node && s.getStencil().id().endsWith("Lane") + }); - // Set the size - this.node.style.width = size.width + "px"; - this.node.style.height = size.height + "px"; - } + var pools = []; + var unselectLanes = []; + lanes.each(function (lane) { + pools.push(this.getParentPool(lane)) + }.bind(this)); -}); + pools = pools.uniq().findAll(function (pool) { + var childLanes = this.getLanes(pool, true); + if (childLanes.all(function (lane) { + return lanes.include(lane) + })) { + unselectLanes = unselectLanes.concat(childLanes); + return true; + } else if (selection.include(pool) && childLanes.any(function (lane) { + return lanes.include(lane) + })) { + unselectLanes = unselectLanes.concat(childLanes); + return true; + } else { + return false; + } + }.bind(this)) + if (unselectLanes.length > 0 && pools.length > 0) { + selection = selection.without.apply(selection, unselectLanes); + selection = selection.concat(pools); + this.facade.setSelection(selection.uniq()); + } + } + }, -/* - * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. - * License rights for this program may be obtained from Alfresco Software, Ltd. - * pursuant to a written agreement and any use of this program without such an - * agreement is prohibited. - */ -/* - * All code Copyright 2013 KIS Consultancy all rights reserved - */ + handleShapeRemove: function (option) { -if(!ORYX.Plugins) - ORYX.Plugins = new Object(); + var sh = option.shape; + var parent = option.parent; -ORYX.Plugins.ShapeHighlighting = Clazz.extend({ + if (sh instanceof ORYX.Core.Node && sh.getStencil().idWithoutNs() === "Lane" && this.facade.isExecutingCommands()) { - construct: function(facade) { - - this.parentNode = facade.getCanvas().getSvgContainer(); - - // The parent Node - this.node = ORYX.Editor.graft("http://www.w3.org/2000/svg", this.parentNode, - ['g']); + var pool = this.getParentPool(parent); + if (pool && pool.parent) { - this.highlightNodes = {}; - - facade.registerOnEvent(ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW, this.setHighlight.bind(this)); - facade.registerOnEvent(ORYX.CONFIG.EVENT_HIGHLIGHT_HIDE, this.hideHighlight.bind(this)); + var isLeafFn = function (leaf) { + return !leaf.getChildNodes().any(function (r) { + return r.getStencil().idWithoutNs() === "Lane" + }); + } - }, + var isLeaf = isLeafFn(sh); + var parentHasMoreLanes = parent.getChildNodes().any(function (r) { + return r.getStencil().idWithoutNs() === "Lane" + }); - setHighlight: function(options) { - if(options && options.highlightId){ - var node = this.highlightNodes[options.highlightId]; - - if(!node){ - node= ORYX.Editor.graft("http://www.w3.org/2000/svg", this.node, - ['path', { - "stroke-width": 2.0, "fill":"none" - }]); - - this.highlightNodes[options.highlightId] = node; - } + if (isLeaf && parentHasMoreLanes) { - if(options.elements && options.elements.length > 0) { - - this.setAttributesByStyle( node, options ); - this.show(node); - - } else { - - this.hide(node); - - } - - } - }, - - hideHighlight: function(options) { - if(options && options.highlightId && this.highlightNodes[options.highlightId]){ - this.hide(this.highlightNodes[options.highlightId]); - } - }, - - hide: function(node) { - node.setAttributeNS(null, 'display', 'none'); - }, + var command = new ResizeLanesCommand(sh, parent, pool, this); + this.facade.executeCommands([command]); - show: function(node) { - node.setAttributeNS(null, 'display', ''); - }, - - setAttributesByStyle: function( node, options ){ - - // If the style say, that it should look like a rectangle - if( options.style && options.style == ORYX.CONFIG.SELECTION_HIGHLIGHT_STYLE_RECTANGLE ){ - - // Set like this - var bo = options.elements[0].absoluteBounds(); - - var strWidth = options.strokewidth ? options.strokewidth : ORYX.CONFIG.BORDER_OFFSET - - node.setAttributeNS(null, "d", this.getPathRectangle( bo.a, bo.b , strWidth ) ); - node.setAttributeNS(null, "stroke", options.color ? options.color : ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR); - node.setAttributeNS(null, "stroke-opacity", options.opacity ? options.opacity : 0.2); - node.setAttributeNS(null, "stroke-width", strWidth); - - } else if(options.elements.length == 1 - && options.elements[0] instanceof ORYX.Core.Edge && - options.highlightId != "selection") { - - /* Highlight containment of edge's childs */ - var path = this.getPathEdge(options.elements[0].dockers); - if (path && path.length > 0) - { - node.setAttributeNS(null, "d", path); - } - node.setAttributeNS(null, "stroke", options.color ? options.color : ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR); - node.setAttributeNS(null, "stroke-opacity", options.opacity ? options.opacity : 0.2); - node.setAttributeNS(null, "stroke-width", ORYX.CONFIG.OFFSET_EDGE_BOUNDS); - - }else { - // If not, set just the corners - var path = this.getPathByElements(options.elements); - if (path && path.length > 0) - { - node.setAttributeNS(null, "d", path); - } - node.setAttributeNS(null, "stroke", options.color ? options.color : ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR); - node.setAttributeNS(null, "stroke-opacity", options.opacity ? options.opacity : 1.0); - node.setAttributeNS(null, "stroke-width", options.strokewidth ? options.strokewidth : 2.0); - - } - }, - - getPathByElements: function(elements){ - if(!elements || elements.length <= 0) {return undefined} - - // Get the padding and the size - var padding = ORYX.CONFIG.SELECTED_AREA_PADDING; - - var path = "" - - // Get thru all Elements - elements.each((function(element) { - if(!element) {return} - // Get the absolute Bounds and the two Points - var bounds = element.absoluteBounds(); - bounds.widen(padding) - var a = bounds.upperLeft(); - var b = bounds.lowerRight(); - - path = path + this.getPath(a ,b); - - }).bind(this)); + } else if (!isLeaf && + !this.facade.getSelection().any(function (select) { // Find one of the selection, which is a lane and child of "sh" and is a leaf lane + return select instanceof ORYX.Core.Node && select.getStencil().idWithoutNs() === "Lane" && + select.isParent(sh) && isLeafFn(select); + })) { - return path; - - }, + var Command = ORYX.Core.Command.extend({ + construct: function (shape, facade) { + this.children = shape.getChildNodes(true); + this.facade = facade; + }, + execute: function () { + this.children.each(function (child) { + child.bounds.moveBy(30, 0) + }); + //this.facade.getCanvas().update(); + }, + rollback: function () { + this.children.each(function (child) { + child.bounds.moveBy(-30, 0) + }) + //this.facade.getCanvas().update(); + } + }); + this.facade.executeCommands([new Command(sh, this.facade)]); - getPath: function(a, b){ - - return this.getPathCorners(a, b); - - }, - - getPathCorners: function(a, b){ - - var size = ORYX.CONFIG.SELECTION_HIGHLIGHT_SIZE; - - var path = "" - - // Set: Upper left - path = path + "M" + a.x + " " + (a.y + size) + " l0 -" + size + " l" + size + " 0 "; - // Set: Lower left - path = path + "M" + a.x + " " + (b.y - size) + " l0 " + size + " l" + size + " 0 "; - // Set: Lower right - path = path + "M" + b.x + " " + (b.y - size) + " l0 " + size + " l-" + size + " 0 "; - // Set: Upper right - path = path + "M" + b.x + " " + (a.y + size) + " l0 -" + size + " l-" + size + " 0 "; - - return path; - }, - - getPathRectangle: function(a, b, strokeWidth){ - - var size = ORYX.CONFIG.SELECTION_HIGHLIGHT_SIZE; - - var path = "" - var offset = strokeWidth / 2.0; - - // Set: Upper left - path = path + "M" + (a.x + offset) + " " + (a.y); - path = path + " L" + (a.x + offset) + " " + (b.y - offset); - path = path + " L" + (b.x - offset) + " " + (b.y - offset); - path = path + " L" + (b.x - offset) + " " + (a.y + offset); - path = path + " L" + (a.x + offset) + " " + (a.y + offset); - - return path; - }, - - getPathEdge: function(edgeDockers) { - var length = edgeDockers.length; - var path = "M" + edgeDockers[0].bounds.center().x + " " - + edgeDockers[0].bounds.center().y; - - for(i=1; i 1) { - this.facade.raiseEvent({ - type: ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW, - highlightId:'selection', - elements: event.elements.without(event.subSelection), - color: ORYX.CONFIG.SELECTION_HIGHLIGHT_COLOR, - opacity: !event.subSelection ? this.opacityFull : this.opacityLow - }); - - if(event.subSelection){ - this.facade.raiseEvent({ - type: ORYX.CONFIG.EVENT_HIGHLIGHT_SHOW, - highlightId:'subselection', - elements: [event.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'}); - } - } -});/* - * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. - * License rights for this program may be obtained from Alfresco Software, Ltd. - * pursuant to a written agreement and any use of this program without such an - * agreement is prohibited. - */ -/* - * All code Copyright 2013 KIS Consultancy all rights reserved - */ + hashedSubProcesses: {}, -if (!ORYX.Plugins) - ORYX.Plugins = new Object(); + hashChildShapes: function (shape) { + var children = shape.getChildNodes(); + children.each(function (child) { + if (this.hashedSubProcesses[child.id]) { + this.hashedSubProcesses[child.id] = child.absoluteXY(); + this.hashedSubProcesses[child.id].width = child.bounds.width(); + this.hashedSubProcesses[child.id].height = child.bounds.height(); + this.hashChildShapes(child); + } + }.bind(this)); + }, -ORYX.Plugins.Overlay = Clazz.extend({ + /** + * Handle the layouting of a sub process. + * Mainly to adjust the child dockers of a sub process. + * + */ + handleSubProcess: function (option) { - facade: undefined, - - styleNode: undefined, - - construct: function(facade){ - - this.facade = facade; + var sh = option.shape; - this.changes = []; + if (!this.hashedSubProcesses[sh.id]) { + this.hashedSubProcesses[sh.id] = sh.absoluteXY(); + this.hashedSubProcesses[sh.id].width = sh.bounds.width(); + this.hashedSubProcesses[sh.id].height = sh.bounds.height(); + return; + } - this.facade.registerOnEvent(ORYX.CONFIG.EVENT_OVERLAY_SHOW, this.show.bind(this)); - this.facade.registerOnEvent(ORYX.CONFIG.EVENT_OVERLAY_HIDE, this.hide.bind(this)); + var offset = sh.absoluteXY(); + offset.x -= this.hashedSubProcesses[sh.id].x; + offset.y -= this.hashedSubProcesses[sh.id].y; - this.styleNode = document.createElement('style') - this.styleNode.setAttributeNS(null, 'type', 'text/css') - - document.getElementsByTagName('head')[0].appendChild( this.styleNode ) + var resized = this.hashedSubProcesses[sh.id].width !== sh.bounds.width() || this.hashedSubProcesses[sh.id].height !== sh.bounds.height(); - }, - - /** - * Show the overlay for specific nodes - * @param {Object} options - * - * String options.id - MUST - Define the id of the overlay (is needed for the hiding of this overlay) - * ORYX.Core.Shape[] options.shapes - MUST - Define the Shapes for the changes - * attr-name:value options.changes - Defines all the changes which should be shown - * - * - */ - show: function( options ){ - - // Checks if all arguments are available - if( !options || - !options.shapes || !options.shapes instanceof Array || - !options.id || !options.id instanceof String || options.id.length == 0) { - - return - - } - - //if( this.changes[options.id]){ - // this.hide( options ) - //} - - - // Checked if attributes are setted - if( options.attributes ){ - - // FOR EACH - Shape - options.shapes.each(function(el){ - - // Checks if the node is a Shape - if( !el instanceof ORYX.Core.Shape){ return } - - this.setAttributes( el.node , options.attributes ) - - }.bind(this)) - - } - - var isSVG = true - try { - isSVG = options.node && options.node instanceof SVGElement; - } catch(e){} - - // Checks if node is setted and if this is an SVGElement - if ( options.node && isSVG) { - - options["_temps"] = [] - - // FOR EACH - Node - options.shapes.each(function(el, index){ - - // Checks if the node is a Shape - if( !el instanceof ORYX.Core.Shape){ return } - - var _temp = {} - _temp.svg = options.dontCloneNode ? options.node : options.node.cloneNode( true ); - - // Add the svg node to the ORYX-Shape - el.node.firstChild.appendChild( _temp.svg ) - - // If - if (el instanceof ORYX.Core.Edge && !options.nodePosition) { - options['nodePosition'] = "START" - } - - // If the node position is setted, it has to be transformed - if( options.nodePosition ){ - - var b = el.bounds; - var p = options.nodePosition.toUpperCase(); - - // Check the values of START and END - if( el instanceof ORYX.Core.Node && p == "START"){ - p = "NW"; - } else if(el instanceof ORYX.Core.Node && p == "END"){ - p = "SE"; - } else if(el instanceof ORYX.Core.Edge && p == "START"){ - b = el.getDockers().first().bounds - } else if(el instanceof ORYX.Core.Edge && p == "END"){ - b = el.getDockers().last().bounds - } + this.hashedSubProcesses[sh.id] = sh.absoluteXY(); + this.hashedSubProcesses[sh.id].width = sh.bounds.width(); + this.hashedSubProcesses[sh.id].height = sh.bounds.height(); + this.hashChildShapes(sh); - // Create a callback for the changing the position - // depending on the position string - _temp.callback = function(){ - - var x = 0; var y = 0; - - if( p == "NW" ){ - // Do Nothing - } else if( p == "N" ) { - x = b.width() / 2; - } else if( p == "NE" ) { - x = b.width(); - } else if( p == "E" ) { - x = b.width(); y = b.height() / 2; - } else if( p == "SE" ) { - x = b.width(); y = b.height(); - } else if( p == "S" ) { - x = b.width() / 2; y = b.height(); - } else if( p == "SW" ) { - y = b.height(); - } else if( p == "W" ) { - y = b.height() / 2; - } else if( p == "START" || p == "END") { - x = b.width() / 2; y = b.height() / 2; - } else { - return - } - - if( el instanceof ORYX.Core.Edge){ - x += b.upperLeft().x ; y += b.upperLeft().y ; - } - - _temp.svg.setAttributeNS(null, "transform", "translate(" + x + ", " + y + ")") - - }.bind(this) - - _temp.element = el; - _temp.callback(); - - b.registerCallback( _temp.callback ); - - } - - - options._temps.push( _temp ) - - }.bind(this)) - - - - } - - - // Store the changes - if( !this.changes[options.id] ){ - this.changes[options.id] = []; - } - - this.changes[options.id].push( options ); - - }, - - /** - * Hide the overlay with the spefic id - * @param {Object} options - */ - hide: function( options ){ - - // Checks if all arguments are available - if( !options || - !options.id || !options.id instanceof String || options.id.length == 0 || - !this.changes[options.id]) { - - return - - } - - - // Delete all added attributes - // FOR EACH - Shape - this.changes[options.id].each(function(option){ - - option.shapes.each(function(el, index){ - - // Checks if the node is a Shape - if( !el instanceof ORYX.Core.Shape){ return } - - this.deleteAttributes( el.node ) - - }.bind(this)); - - - if( option._temps ){ - - option._temps.each(function(tmp){ - // Delete the added Node, if there is one - if( tmp.svg && tmp.svg.parentNode ){ - tmp.svg.parentNode.removeChild( tmp.svg ) - } - - // If - if( tmp.callback && tmp.element){ - // It has to be unregistered from the edge - tmp.element.bounds.unregisterCallback( tmp.callback ) - } - - }.bind(this)) - - } - - - }.bind(this)); - - this.changes[options.id] = null; - - - }, - - - /** - * Set the given css attributes to that node - * @param {HTMLElement} node - * @param {Object} attributes - */ - setAttributes: function( node, attributes ) { - - - // Get all the childs from ME - var childs = this.getAllChilds( node.firstChild.firstChild ) - - var ids = [] - - // Add all Attributes which have relation to another node in this document and concate the pure id out of it - // This is for example important for the markers of a edge - childs.each(function(e){ ids.push( $A(e.attributes).findAll(function(attr){ return attr.nodeValue.startsWith('url(#')}) )}) - ids = ids.flatten().compact(); - ids = ids.collect(function(s){return s.nodeValue}).uniq(); - ids = ids.collect(function(s){return s.slice(5, s.length-1)}) - - // Add the node ID to the id - ids.unshift( node.id + ' .me') - - var attr = $H(attributes); - var attrValue = attr.toJSON().gsub(',', ';').gsub('"', ''); - var attrMarkerValue = attributes.stroke ? attrValue.slice(0, attrValue.length-1) + "; fill:" + attributes.stroke + ";}" : attrValue; - var attrTextValue; - if( attributes.fill ){ - var copyAttr = Object.clone(attributes); - copyAttr.fill = "black"; - attrTextValue = $H(copyAttr).toJSON().gsub(',', ';').gsub('"', ''); - } - - // Create the CSS-Tags Style out of the ids and the attributes - csstags = ids.collect(function(s, i){return "#" + s + " * " + (!i? attrValue : attrMarkerValue) + "" + (attrTextValue ? " #" + s + " text * " + attrTextValue : "") }) - - // Join all the tags - var s = csstags.join(" ") + "\n" - - // And add to the end of the style tag - this.styleNode.appendChild(document.createTextNode(s)); - - - }, - - /** - * Deletes all attributes which are - * added in a special style sheet for that node - * @param {HTMLElement} node - */ - deleteAttributes: function( node ) { - - // Get all children which contains the node id - var delEl = $A(this.styleNode.childNodes) - .findAll(function(e){ return e.textContent.include( '#' + node.id ) }); - - // Remove all of them - delEl.each(function(el){ - el.parentNode.removeChild(el); - }); - }, - - getAllChilds: function( node ){ - - var childs = $A(node.childNodes) - - $A(node.childNodes).each(function( e ){ - childs.push( this.getAllChilds( e ) ) - }.bind(this)) - - return childs.flatten(); - } - - -}); -/* - * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. - * License rights for this program may be obtained from Alfresco Software, Ltd. - * pursuant to a written agreement and any use of this program without such an - * agreement is prohibited. - */ -/* - * All code Copyright 2013 KIS Consultancy all rights reserved - */ + // Move dockers only if currently is not resizing + if (this.facade.isExecutingCommands() && !resized) { + this.moveChildDockers(sh, offset); + } + }, -if (!ORYX.Plugins) - ORYX.Plugins = new Object(); + moveChildDockers: function (shape, offset) { -ORYX.Plugins.KeysMove = ORYX.Plugins.AbstractPlugin.extend({ + if (!offset.x && !offset.y) { + return; + } - facade: undefined, - - construct: function(facade){ - - this.facade = facade; - this.copyElements = []; - - //this.facade.registerOnEvent(ORYX.CONFIG.EVENT_KEYDOWN, this.keyHandler.bind(this)); + var children = shape.getChildNodes(true); - // SELECT ALL - this.facade.offer({ - keyCodes: [{ - metaKeys: [ORYX.CONFIG.META_KEY_META_CTRL], - keyCode: 65, - keyAction: ORYX.CONFIG.KEY_ACTION_DOWN - } - ], - functionality: this.selectAll.bind(this) - }); - - // MOVE LEFT SMALL - 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) - }); - - // MOVE LEFT - 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) - }); - - // MOVE RIGHT SMALL - 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) - }); - - // MOVE RIGHT - 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) - }); - - // MOVE UP SMALL - 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) - }); - - // MOVE UP - 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) - }); - - // MOVE DOWN SMALL - 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) - }); - - // MOVE DOWN - 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) - }); - - - }, - - /** - * Select all shapes in the editor - * - */ - selectAll: function(e){ - Event.stop(e.event); - this.facade.setSelection(this.facade.getCanvas().getChildShapes(true)) - }, - - move: function(key, far, e) { - - Event.stop(e.event); - - // calculate the distance to move the objects and get the selection. - var distance = far? 20 : 5; - var selection = this.facade.getSelection(); - var currentSelection = this.facade.getSelection(); - var p = {x: 0, y: 0}; - - // switch on the key pressed and populate the point to move by. - switch(key) { - - case ORYX.CONFIG.KEY_CODE_LEFT: - p.x = -1*distance; - break; - case ORYX.CONFIG.KEY_CODE_RIGHT: - p.x = distance; - break; - case ORYX.CONFIG.KEY_CODE_UP: - p.y = -1*distance; - break; - case ORYX.CONFIG.KEY_CODE_DOWN: - p.y = distance; - break; - } - - // move each shape in the selection by the point calculated and update it. - selection = selection.findAll(function(shape){ - // Check if this shape is docked to an shape in the selection - if(shape instanceof ORYX.Core.Node && shape.dockers.length == 1 && selection.include( shape.dockers.first().getDockedShape() )){ - return false - } - - // Check if any of the parent shape is included in the selection - var s = shape.parent; - do{ - if(selection.include(s)){ - return false - } - }while(s = s.parent); - - // Otherwise, return true - return true; - - }); - - /* Edges must not be movable, if only edges are selected and at least - * one of them is docked. - */ - var edgesMovable = true; - var onlyEdgesSelected = selection.all(function(shape) { - if(shape instanceof ORYX.Core.Edge) { - if(shape.isDocked()) { - edgesMovable = false; - } - return true; - } - return false; - }); - - if(onlyEdgesSelected && !edgesMovable) { - /* Abort moving shapes */ - return; - } - - selection = selection.map(function(shape){ - if( shape instanceof ORYX.Core.Node ){ - /*if( shape.dockers.length == 1 ){ - return shape.dockers.first() - } else {*/ - return shape - //} - } else if( shape instanceof ORYX.Core.Edge ) { - - var dockers = shape.dockers; - - if( selection.include( shape.dockers.first().getDockedShape() ) ){ - dockers = dockers.without( shape.dockers.first() ) - } - - if( selection.include( shape.dockers.last().getDockedShape() ) ){ - dockers = dockers.without( shape.dockers.last() ) - } - - return dockers - - } else { - return null - } - - }).flatten().compact(); - - if (selection.size() > 0) { - - //Stop moving at canvas borders - var selectionBounds = [ this.facade.getCanvas().bounds.lowerRight().x, - this.facade.getCanvas().bounds.lowerRight().y, - 0, - 0 ]; - selection.each(function(s) { - selectionBounds[0] = Math.min(selectionBounds[0], s.bounds.upperLeft().x); - selectionBounds[1] = Math.min(selectionBounds[1], s.bounds.upperLeft().y); - selectionBounds[2] = Math.max(selectionBounds[2], s.bounds.lowerRight().x); - selectionBounds[3] = Math.max(selectionBounds[3], s.bounds.lowerRight().y); - }); - if(selectionBounds[0]+p.x < 0) - p.x = -selectionBounds[0]; - if(selectionBounds[1]+p.y < 0) - p.y = -selectionBounds[1]; - if(selectionBounds[2]+p.x > this.facade.getCanvas().bounds.lowerRight().x) - p.x = this.facade.getCanvas().bounds.lowerRight().x - selectionBounds[2]; - if(selectionBounds[3]+p.y > this.facade.getCanvas().bounds.lowerRight().y) - p.y = this.facade.getCanvas().bounds.lowerRight().y - selectionBounds[3]; - - if(p.x!=0 || p.y!=0) { - // Instantiate the moveCommand - var commands = [new ORYX.Core.Command.Move(selection, p, null, currentSelection, this)]; - // Execute the commands - this.facade.executeCommands(commands); - } - - } - }, - - getUndockedCommant: function(shapes){ - - var undockEdgeCommand = ORYX.Core.Command.extend({ - construct: function(moveShapes){ - this.dockers = moveShapes.collect(function(shape){ return shape instanceof ORYX.Core.Controls.Docker ? {docker:shape, dockedShape:shape.getDockedShape(), refPoint:shape.referencePoint} : undefined }).compact(); - }, - execute: function(){ - this.dockers.each(function(el){ - el.docker.setDockedShape(undefined); - }) - }, - rollback: function(){ - this.dockers.each(function(el){ - el.docker.setDockedShape(el.dockedShape); - el.docker.setReferencePoint(el.refPoint); - //el.docker.update(); - }) - } - }); - - command = new undockEdgeCommand( shapes ); - command.execute(); - return command; - }, - -// /** -// * The key handler for this plugin. Every action from the set of cut, copy, -// * paste and delete should be accessible trough simple keyboard shortcuts. -// * This method checks whether any event triggers one of those actions. -// * -// * @param {Object} event The keyboard event that should be analysed for -// * triggering of this plugin. -// */ -// keyHandler: function(event){ -// //TODO document what event.which is. -// -// ORYX.Log.debug("keysMove.js handles a keyEvent."); -// -// // assure we have the current event. -// if (!event) -// event = window.event; -// -// // get the currently pressed key and state of control key. -// var pressedKey = event.which || event.keyCode; -// var ctrlPressed = event.ctrlKey; -// -// // if the key is one of the arrow keys, forward to move and return. -// if ([ORYX.CONFIG.KEY_CODE_LEFT, ORYX.CONFIG.KEY_CODE_RIGHT, -// ORYX.CONFIG.KEY_CODE_UP, ORYX.CONFIG.KEY_CODE_DOWN].include(pressedKey)) { -// -// this.move(pressedKey, !ctrlPressed); -// return; -// } -// -// } - -}); -/* - * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. - * License rights for this program may be obtained from Alfresco Software, Ltd. - * pursuant to a written agreement and any use of this program without such an - * agreement is prohibited. - */ -/* - * All code Copyright 2013 KIS Consultancy all rights reserved - */ + // Get all nodes + var dockers = children + // Get all incoming and outgoing edges + .map(function (node) { + return [].concat(node.getIncomingShapes()) + .concat(node.getOutgoingShapes()) + }) + // Flatten all including arrays into one + .flatten() + // Get every edge only once + .uniq() + // Get all dockers + .map(function (edge) { + return edge.dockers.length > 2 ? + edge.dockers.slice(1, edge.dockers.length - 1) : + []; + }) + // Flatten the dockers lists + .flatten(); -if(!ORYX.Plugins) { ORYX.Plugins = {} } -if(!ORYX.Plugins.Layouter) { ORYX.Plugins.Layouter = {} } + var abs = shape.absoluteBounds(); + abs.moveBy(-offset.x, -offset.y) + var obj = {}; + dockers.each(function (docker) { -new function(){ - - /** - * Edge layouter is an implementation to layout an edge - * @class ORYX.Plugins.Layouter.EdgeLayouter - * @author Willi Tscheschner - */ - ORYX.Plugins.Layouter.EdgeLayouter = ORYX.Plugins.AbstractLayouter.extend({ - - /** - * Layout only Edges - */ - 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 a set on edges - * @param {Object} edges - */ - layout: function(edges){ - edges.each(function(edge){ - this.doLayout(edge) - }.bind(this)) - }, - - /** - * Layout one edge - * @param {Object} edge - */ - doLayout: function(edge){ - // Get from and to node - var from = edge.getIncomingNodes()[0]; - var to = edge.getOutgoingNodes()[0]; - - // Return if one is null - if (!from || !to) { return } - - var positions = this.getPositions(from, to, edge); - - if (positions.length > 0){ - this.setDockers(edge, positions[0].a, positions[0].b); - } - - }, - - /** - * Returns a set on positions which are not containt either - * in the bounds in from or to. - * @param {Object} from Shape where the edge is come from - * @param {Object} to Shape where the edge is leading to - * @param {Object} edge Edge between from and to - */ - getPositions : function(from, to, edge){ - - // Get absolute bounds - var ab = from.absoluteBounds(); - var bb = to.absoluteBounds(); - - // Get center from and to - var a = ab.center(); - var b = bb.center(); - - var am = ab.midPoint(); - var bm = bb.midPoint(); - - // Get first and last reference point - var first = Object.clone(edge.dockers.first().referencePoint); - var last = Object.clone(edge.dockers.last().referencePoint); - // Get the absolute one - var aFirst = edge.dockers.first().getAbsoluteReferencePoint(); - var aLast = edge.dockers.last().getAbsoluteReferencePoint(); - - // IF ------> - // or | - // V - // Do nothing - if (Math.abs(aFirst.x-aLast.x) < 1 || Math.abs(aFirst.y-aLast.y) < 1) { - return [] - } - - // Calc center position, between a and b - // depending on there weight - var m = {} - m.x = a.x < b.x ? - (((b.x - bb.width()/2) - (a.x + ab.width()/2))/2) + (a.x + ab.width()/2): - (((a.x - ab.width()/2) - (b.x + bb.width()/2))/2) + (b.x + bb.width()/2); - - m.y = a.y < b.y ? - (((b.y - bb.height()/2) - (a.y + ab.height()/2))/2) + (a.y + ab.height()/2): - (((a.y - ab.height()/2) - (b.y + bb.height()/2))/2) + (b.y + bb.height()/2); - - - // Enlarge both bounds with 10 - ab.widen(5); // Wide the from less than - bb.widen(20);// the to because of the arrow from the edge - - var positions = []; - var off = this.getOffset.bind(this); - - // Checks ----+ - // | - // V - if (!ab.isIncluded(b.x, a.y)&&!bb.isIncluded(b.x, a.y)) { - positions.push({ - a : {x:b.x+off(last,bm,"x"),y:a.y+off(first,am,"y")}, - z : this.getWeight(from, a.x < b.x ? "r" : "l", to, a.y < b.y ? "t" : "b", edge) - }); - } - - // Checks | - // +---> - if (!ab.isIncluded(a.x, b.y)&&!bb.isIncluded(a.x, b.y)) { - positions.push({ - a : {x:a.x+off(first,am,"x"),y:b.y+off(last,bm,"y")}, - z : this.getWeight(from, a.y < b.y ? "b" : "t", to, a.x < b.x ? "l" : "r", edge) - }); - } - - // Checks --+ - // | - // +---> - if (!ab.isIncluded(m.x, a.y)&&!bb.isIncluded(m.x, b.y)) { - positions.push({ - a : {x:m.x,y:a.y+off(first,am,"y")}, - b : {x:m.x,y:b.y+off(last,bm,"y")}, - z : this.getWeight(from, "r", to, "l", edge, a.x > b.x) - }); - } - - // Checks | - // +---+ - // | - // V - if (!ab.isIncluded(a.x, m.y)&&!bb.isIncluded(b.x, m.y)) { - positions.push({ - a : {x:a.x+off(first,am,"x"),y:m.y}, - b : {x:b.x+off(last,bm,"x"),y:m.y}, - z : this.getWeight(from, "b", to, "t", edge, a.y > b.y) - }); - } - - // Sort DESC of weights - return positions.sort(function(a,b){ return a.z < b.z ? 1 : (a.z == b.z ? -1 : -1)}); - }, - - /** - * Returns a offset for the pos to the center of the bounds - * - * @param {Object} val - * @param {Object} pos2 - * @param {String} dir Direction x|y - */ - getOffset: function(pos, pos2, dir){ - return pos[dir] - pos2[dir]; - }, - - /** - * Returns a value which shows the weight for this configuration - * - * @param {Object} from Shape which is coming from - * @param {String} d1 Direction where is goes - * @param {Object} to Shape which goes to - * @param {String} d2 Direction where it comes to - * @param {Object} edge Edge between from and to - * @param {Boolean} reverse Reverse the direction (e.g. "r" -> "l") - */ - getWeight: function(from, d1, to, d2, edge, reverse){ - - d1 = (d1||"").toLowerCase(); - d2 = (d2||"").toLowerCase(); - - if (!["t","r","b","l"].include(d1)){ d1 = "r"} - if (!["t","r","b","l"].include(d2)){ d1 = "l"} - - // If reverse is set - if (reverse) { - // Reverse d1 and d2 - d1 = d1=="t"?"b":(d1=="r"?"l":(d1=="b"?"t":(d1=="l"?"r":"r"))) - d2 = d2=="t"?"b":(d2=="r"?"l":(d2=="b"?"t":(d2=="l"?"r":"r"))) - } - - - var weight = 0; - // Get rules for from "out" and to "in" - var dr1 = this.facade.getRules().getLayoutingRules(from, edge)["out"]; - var dr2 = this.facade.getRules().getLayoutingRules(to, edge)["in"]; - - var fromWeight = dr1[d1]; - var toWeight = dr2[d2]; - - - /** - * Return a true if the center 1 is in the same direction than center 2 - * @param {Object} direction - * @param {Object} center1 - * @param {Object} center2 - */ - var sameDirection = function(direction, center1, center2){ - switch(direction){ - case "t": return Math.abs(center1.x - center2.x) < 2 && center1.y < center2.y - case "r": return center1.x > center2.x && Math.abs(center1.y - center2.y) < 2 - case "b": return Math.abs(center1.x - center2.x) < 2 && center1.y > center2.y - case "l": return center1.x < center2.x && Math.abs(center1.y - center2.y) < 2 - default: return false; - } - } + if (docker.isChanged) { + return; + } - // Check if there are same incoming edges from 'from' - var sameIncomingFrom = from - .getIncomingShapes() - .findAll(function(a){ return a instanceof ORYX.Core.Edge}) - .any(function(e){ - return sameDirection(d1, e.dockers[e.dockers.length-2].bounds.center(), e.dockers.last().bounds.center()); - }); - - // Check if there are same outgoing edges from 'to' - var sameOutgoingTo = to - .getOutgoingShapes() - .findAll(function(a){ return a instanceof ORYX.Core.Edge}) - .any(function(e){ - return sameDirection(d2, e.dockers[1].bounds.center(), e.dockers.first().bounds.center()); - }); - - // If there are equivalent edges, set 0 - //fromWeight = sameIncomingFrom ? 0 : fromWeight; - //toWeight = sameOutgoingTo ? 0 : toWeight; - - // Get the sum of "out" and the direction plus "in" and the direction - return (sameIncomingFrom||sameOutgoingTo?0:fromWeight+toWeight); - }, - - /** - * Removes all current dockers from the node - * (except the start and end) and adds two new - * dockers, on the position a and b. - * @param {Object} edge - * @param {Object} a - * @param {Object} b - */ - setDockers: function(edge, a, b){ - if (!edge){ return } - - // Remove all dockers (implicit, - // start and end dockers will not removed) - edge.dockers.each(function(r){ - edge.removeDocker(r); - }); - - // For a and b (if exists), create - // a new docker and set position - [a, b].compact().each(function(pos){ - var docker = edge.createDocker(undefined, pos); - docker.bounds.centerMoveTo(pos); - }); - - // Update all dockers from the edge - edge.dockers.each(function(docker){ - docker.update() - }) - - // Update edge - //edge.refresh(); - edge._update(true); - - } - }); - - -}() -/* - * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. - * License rights for this program may be obtained from Alfresco Software, Ltd. - * pursuant to a written agreement and any use of this program without such an - * agreement is prohibited. - */ -/* - * All code Copyright 2013 KIS Consultancy all rights reserved - */ + var off = Object.clone(offset); -if(!ORYX.Plugins) - ORYX.Plugins = new Object(); + if (!abs.isIncluded(docker.bounds.center())) { + var index = docker.parent.dockers.indexOf(docker); + var size = docker.parent.dockers.length; + var from = docker.parent.getSource(); + var to = docker.parent.getTarget(); -new function(){ - - ORYX.Plugins.BPMN2_0 = { - - /** - * Constructor - * @param {Object} Facade: The Facade of the Editor - */ - construct: function(facade){ - this.facade = facade; - - 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; - }, - - /** - * Force to update every pool - */ - afterLoad: function(){ - this.facade.getCanvas().getChildNodes().each(function(shape){ - if (shape.getStencil().id().endsWith("Pool")) { - this.handleLayoutPool({ - shape: shape - }); + var bothAreIncluded = children.include(from) && children.include(to); + + if (!bothAreIncluded) { + var previousIsOver = index !== 0 ? abs.isIncluded(docker.parent.dockers[index - 1].bounds.center()) : false; + var nextIsOver = index !== size - 1 ? abs.isIncluded(docker.parent.dockers[index + 1].bounds.center()) : false; + + if (!previousIsOver && !nextIsOver) { + return; } - }.bind(this)) - }, - - /** - * If a pool is selected and contains no lane, - * a lane is created automagically - */ - onSelectionChanged: function(event) { - var selection = event.elements; - - if(selection && selection.length === 1) { - var namespace = this.getNamespace(); - var shape = selection[0]; - if(shape.getStencil().idWithoutNs() === "Pool") { - if(shape.getChildNodes().length === 0) { - // create a lane inside the selected pool - var option = { - type:namespace + "Lane", - position:{x:0,y:0}, - namespace:shape.getStencil().namespace(), - parent:shape - }; - this.facade.createShape(option); - this.facade.getCanvas().update(); - this.facade.setSelection([shape]); - } + + var ref = docker.parent.dockers[previousIsOver ? index - 1 : index + 1]; + if (Math.abs(-Math.abs(ref.bounds.center().x - docker.bounds.center().x)) < 2) { + off.y = 0; + } else if (Math.abs(-Math.abs(ref.bounds.center().y - docker.bounds.center().y)) < 2) { + off.x = 0; + } else { + return; } + } + } - - // Preventing selection of all lanes but not the pool - if(selection.any(function(s){ return s instanceof ORYX.Core.Node && s.getStencil().id().endsWith("Lane")})){ - var lanes = selection.findAll(function(s){ - return s instanceof ORYX.Core.Node && s.getStencil().id().endsWith("Lane") - }); - - var pools = []; - var unselectLanes = []; - lanes.each(function(lane){ - pools.push(this.getParentPool(lane)) - }.bind(this)); - - pools = pools.uniq().findAll(function(pool){ - var childLanes = this.getLanes(pool, true); - if (childLanes.all(function(lane){ return lanes.include(lane)})){ - unselectLanes = unselectLanes.concat(childLanes); - return true; - } else if (selection.include(pool) && childLanes.any(function(lane){ return lanes.include(lane)})) { - unselectLanes = unselectLanes.concat(childLanes); - return true; - } else { - return false; - } - }.bind(this)) - - if (unselectLanes.length > 0 && pools.length > 0){ - selection = selection.without.apply(selection, unselectLanes); - selection = selection.concat(pools); - this.facade.setSelection(selection.uniq()); - } + + obj[docker.getId()] = { + docker: docker, + offset: off } + }) + + // Set dockers + this.facade.executeCommands([new ORYX.Core.MoveDockersCommand(obj)]); + }, - - handleShapeRemove: function(option) { - - var sh = option.shape; - var parent = option.parent; - - if (sh instanceof ORYX.Core.Node && sh.getStencil().idWithoutNs() === "Lane" && this.facade.isExecutingCommands()) { - - var pool = this.getParentPool(parent); - if (pool&&pool.parent){ - - var isLeafFn = function(leaf){ - return !leaf.getChildNodes().any(function(r){ return r.getStencil().idWithoutNs() === "Lane"}); - } - - var isLeaf = isLeafFn(sh); - var parentHasMoreLanes = parent.getChildNodes().any(function(r){ return r.getStencil().idWithoutNs() === "Lane"}); - - if (isLeaf && parentHasMoreLanes){ - - var command = new ResizeLanesCommand(sh, parent, pool, this); - this.facade.executeCommands([command]); - - } else if( !isLeaf && - !this.facade.getSelection().any(function(select){ // Find one of the selection, which is a lane and child of "sh" and is a leaf lane - return select instanceof ORYX.Core.Node && select.getStencil().idWithoutNs() === "Lane" && - select.isParent(sh) && isLeafFn(select);})) { - - var Command = ORYX.Core.Command.extend({ - construct: function(shape, facade) { - this.children = shape.getChildNodes(true); - this.facade = facade; - }, - execute: function() { - this.children.each(function(child){ - child.bounds.moveBy(30,0) - }); - //this.facade.getCanvas().update(); - }, - rollback: function() { - this.children.each(function(child){ - child.bounds.moveBy(-30,0) - }) - //this.facade.getCanvas().update(); - } - }); - this.facade.executeCommands([new Command(sh, this.facade)]); - - } else if (isLeaf&&!parentHasMoreLanes&&parent == pool){ - parent.add(sh); - } + + /** + * DragDocker.Docked Handler + * + */ + handleDockerDocked: function (options) { + var namespace = this.getNamespace(); + + var edge = options.parent; + var edgeSource = options.target; + + if (edge.getStencil().id() === namespace + "SequenceFlow") { + var isGateway = edgeSource.getStencil().groups().find(function (group) { + if (group == "Gateways") + return group; + }); + if (!isGateway && (edge.properties["oryx-conditiontype"] == "Expression")) + // show diamond on edge source + edge.setProperty("oryx-showdiamondmarker", true); + else + // do not show diamond on edge source + edge.setProperty("oryx-showdiamondmarker", false); + + // update edge rendering + //edge.update(); + + this.facade.getCanvas().update(); + } + }, + + /** + * PropertyWindow.PropertyChanged Handler + */ + handlePropertyChanged: function (option) { + var namespace = this.getNamespace(); + + var shapes = option.elements; + var propertyKey = option.key; + var propertyValue = option.value; + + var changed = false; + shapes.each(function (shape) { + if ((shape.getStencil().id() === namespace + "SequenceFlow") && + (propertyKey === "oryx-conditiontype")) { + + if (propertyValue != "Expression") + // Do not show the Diamond + shape.setProperty("oryx-showdiamondmarker", false); + else { + var incomingShapes = shape.getIncomingShapes(); + + if (!incomingShapes) { + shape.setProperty("oryx-showdiamondmarker", true); } - + + var incomingGateway = incomingShapes.find(function (aShape) { + var foundGateway = aShape.getStencil().groups().find(function (group) { + if (group == "Gateways") + return group; + }); + if (foundGateway) + return foundGateway; + }); + + if (!incomingGateway) + // show diamond on edge source + shape.setProperty("oryx-showdiamondmarker", true); + else + // do not show diamond + shape.setProperty("oryx-showdiamondmarker", false); + } + + changed = true; } - + }.bind(this)); + + if (changed) { + this.facade.getCanvas().update(); + } + }, - - hashedSubProcesses: {}, - - hashChildShapes: function(shape){ - var children = shape.getChildNodes(); - children.each(function(child){ - if (this.hashedSubProcesses[child.id]){ - this.hashedSubProcesses[child.id] = child.absoluteXY(); - this.hashedSubProcesses[child.id].width = child.bounds.width(); - this.hashedSubProcesses[child.id].height = child.bounds.height(); - this.hashChildShapes(child); - } - }.bind(this)); - }, - - /** - * Handle the layouting of a sub process. - * Mainly to adjust the child dockers of a sub process. - * - */ - handleSubProcess : function(option) { - - var sh = option.shape; - - if (!this.hashedSubProcesses[sh.id]) { - this.hashedSubProcesses[sh.id] = sh.absoluteXY(); - this.hashedSubProcesses[sh.id].width = sh.bounds.width(); - this.hashedSubProcesses[sh.id].height = sh.bounds.height(); - return; - } - - var offset = sh.absoluteXY(); - offset.x -= this.hashedSubProcesses[sh.id].x; - offset.y -= this.hashedSubProcesses[sh.id].y; - - var resized = this.hashedSubProcesses[sh.id].width !== sh.bounds.width() || this.hashedSubProcesses[sh.id].height !== sh.bounds.height(); - - this.hashedSubProcesses[sh.id] = sh.absoluteXY(); - this.hashedSubProcesses[sh.id].width = sh.bounds.width(); - this.hashedSubProcesses[sh.id].height = sh.bounds.height(); - this.hashChildShapes(sh); - - - // Move dockers only if currently is not resizing - if (this.facade.isExecutingCommands()&&!resized) { - this.moveChildDockers(sh, offset); - } - }, - - moveChildDockers: function(shape, offset){ - - if (!offset.x && !offset.y) { - return; - } - - var children = shape.getChildNodes(true); - - // Get all nodes - var dockers = children - // Get all incoming and outgoing edges - .map(function(node){ - return [].concat(node.getIncomingShapes()) - .concat(node.getOutgoingShapes()) - }) - // Flatten all including arrays into one - .flatten() - // Get every edge only once - .uniq() - // Get all dockers - .map(function(edge){ - return edge.dockers.length > 2 ? - edge.dockers.slice(1, edge.dockers.length-1) : - []; - }) - // Flatten the dockers lists - .flatten(); - - var abs = shape.absoluteBounds(); - abs.moveBy(-offset.x, -offset.y) - var obj = {}; - dockers.each(function(docker){ - - if (docker.isChanged){ - return; - } - - var off = Object.clone(offset); - - if (!abs.isIncluded(docker.bounds.center())){ - var index = docker.parent.dockers.indexOf(docker); - var size = docker.parent.dockers.length; - var from = docker.parent.getSource(); - var to = docker.parent.getTarget(); - - var bothAreIncluded = children.include(from) && children.include(to); - - if (!bothAreIncluded){ - var previousIsOver = index !== 0 ? abs.isIncluded(docker.parent.dockers[index-1].bounds.center()) : false; - var nextIsOver = index !== size-1 ? abs.isIncluded(docker.parent.dockers[index+1].bounds.center()) : false; - - if (!previousIsOver && !nextIsOver){ return; } - - var ref = docker.parent.dockers[previousIsOver ? index-1 : index+1]; - if (Math.abs(-Math.abs(ref.bounds.center().x-docker.bounds.center().x)) < 2){ - off.y = 0; - } else if(Math.abs(-Math.abs(ref.bounds.center().y-docker.bounds.center().y)) < 2){ - off.x = 0; - } else { - return; - } - } - - } - - obj[docker.getId()] = { - docker:docker, - offset:off - } - }) - - // Set dockers - this.facade.executeCommands([new ORYX.Core.MoveDockersCommand(obj)]); - - }, - - /** - * DragDocker.Docked Handler - * - */ - handleDockerDocked: function(options) { - var namespace = this.getNamespace(); - - var edge = options.parent; - var edgeSource = options.target; - - if(edge.getStencil().id() === namespace + "SequenceFlow") { - var isGateway = edgeSource.getStencil().groups().find(function(group) { - if(group == "Gateways") - return group; - }); - if(!isGateway && (edge.properties["oryx-conditiontype"] == "Expression")) - // show diamond on edge source - edge.setProperty("oryx-showdiamondmarker", true); - else - // do not show diamond on edge source - edge.setProperty("oryx-showdiamondmarker", false); - - // update edge rendering - //edge.update(); - - this.facade.getCanvas().update(); - } - }, - - /** - * PropertyWindow.PropertyChanged Handler - */ - handlePropertyChanged: function(option) { - var namespace = this.getNamespace(); - - var shapes = option.elements; - var propertyKey = option.key; - var propertyValue = option.value; - - var changed = false; - shapes.each(function(shape){ - if((shape.getStencil().id() === namespace + "SequenceFlow") && - (propertyKey === "oryx-conditiontype")) { - - if(propertyValue != "Expression") - // Do not show the Diamond - shape.setProperty("oryx-showdiamondmarker", false); - else { - var incomingShapes = shape.getIncomingShapes(); - - if(!incomingShapes) { - shape.setProperty("oryx-showdiamondmarker", true); - } - - var incomingGateway = incomingShapes.find(function(aShape) { - var foundGateway = aShape.getStencil().groups().find(function(group) { - if(group == "Gateways") - return group; - }); - if(foundGateway) - return foundGateway; - }); - - if(!incomingGateway) - // show diamond on edge source - shape.setProperty("oryx-showdiamondmarker", true); - else - // do not show diamond - shape.setProperty("oryx-showdiamondmarker", false); - } - - changed = true; - } - }.bind(this)); - - if(changed) {this.facade.getCanvas().update();} - - }, - - hashedPoolPositions : {}, - hashedLaneDepth : {}, - hashedBounds : {}, - hashedPositions: {}, - - /** + hashedPoolPositions: {}, + hashedLaneDepth: {}, + hashedBounds: {}, + hashedPositions: {}, + + /** * Handler for layouting event 'layout.bpmn2_0.pool' * @param {Object} event */ - handleLayoutPool: function(event){ - - - var pool = event.shape; - var selection = this.facade.getSelection(); - var currentShape = selection.include(pool) ? pool : selection.first(); - - currentShape = currentShape || pool; - - this.currentPool = pool; - - // Check if it is a pool or a lane - if (!(currentShape.getStencil().id().endsWith("Pool") || currentShape.getStencil().id().endsWith("Lane"))) { - return; - } - - // Check if the lane is within the pool and is not removed lately - if (currentShape !== pool && !currentShape.isParent(pool) && !this.hashedBounds[pool.id][currentShape.id]){ - return; - } - - - if (!this.hashedBounds[pool.id]) { - this.hashedBounds[pool.id] = {}; + handleLayoutPool: function (event) { + + + var pool = event.shape; + var selection = this.facade.getSelection(); + var currentShape = selection.include(pool) ? pool : selection.first(); + + currentShape = currentShape || pool; + + this.currentPool = pool; + + // Check if it is a pool or a lane + if (!(currentShape.getStencil().id().endsWith("Pool") || currentShape.getStencil().id().endsWith("Lane"))) { + return; + } + + // Check if the lane is within the pool and is not removed lately + if (currentShape !== pool && !currentShape.isParent(pool) && !this.hashedBounds[pool.id][currentShape.id]) { + return; + } + + + if (!this.hashedBounds[pool.id]) { + this.hashedBounds[pool.id] = {}; + } + + // Find all child lanes + var lanes = this.getLanes(pool); + + if (lanes.length <= 0) { + return + } + + var allLanes = this.getLanes(pool, true), hp; + var considerForDockers = allLanes.clone(); + + var hashedPositions = $H({}); + allLanes.each(function (lane) { + hashedPositions[lane.id] = lane.bounds.upperLeft(); + }) + + + // Show/hide caption regarding the number of lanes + if (lanes.length === 1 && this.getLanes(lanes.first()).length <= 0) { + // TRUE if there is a caption + lanes.first().setProperty("oryx-showcaption", lanes.first().properties["oryx-name"].trim().length > 0); + var rect = lanes.first().node.getElementsByTagName("rect"); + rect[0].setAttributeNS(null, "display", "none"); + } else { + allLanes.invoke("setProperty", "oryx-showcaption", true); + allLanes.each(function (lane) { + var rect = lane.node.getElementsByTagName("rect"); + rect[0].removeAttributeNS(null, "display"); + }) + } + + var deletedLanes = []; + var addedLanes = []; + + // Get all new lanes + var i = -1; + while (++i < allLanes.length) { + if (!this.hashedBounds[pool.id][allLanes[i].id]) { + addedLanes.push(allLanes[i]) } - - // Find all child lanes - var lanes = this.getLanes(pool); - - if (lanes.length <= 0) { - return + } + + if (addedLanes.length > 0) { + currentShape = addedLanes.first(); + } + + + // Get all deleted lanes + var resourceIds = $H(this.hashedBounds[pool.id]).keys(); + var i = -1; + while (++i < resourceIds.length) { + if (!allLanes.any(function (lane) { + return lane.id == resourceIds[i] + })) { + deletedLanes.push(this.hashedBounds[pool.id][resourceIds[i]]); + selection = selection.without(function (r) { + return r.id == resourceIds[i] + }); } - - var allLanes = this.getLanes(pool, true), hp; - var considerForDockers = allLanes.clone(); - - var hashedPositions = $H({}); - allLanes.each(function(lane){ - hashedPositions[lane.id] = lane.bounds.upperLeft(); - }) - - - - // Show/hide caption regarding the number of lanes - if (lanes.length === 1 && this.getLanes(lanes.first()).length <= 0) { - // TRUE if there is a caption - lanes.first().setProperty("oryx-showcaption", lanes.first().properties["oryx-name"].trim().length > 0); - var rect = lanes.first().node.getElementsByTagName("rect"); - rect[0].setAttributeNS(null, "display", "none"); + } + + var height, width, x, y; + + if (deletedLanes.length > 0 || addedLanes.length > 0) { + + if (addedLanes.length === 1 && this.getLanes(addedLanes[0].parent).length === 1) { + // Set height from the pool + height = this.adjustHeight(lanes, addedLanes[0].parent); } else { - allLanes.invoke("setProperty", "oryx-showcaption", true); - allLanes.each(function(lane){ - var rect = lane.node.getElementsByTagName("rect"); - rect[0].removeAttributeNS(null, "display"); - }) - } - - var deletedLanes = []; - var addedLanes = []; - - // Get all new lanes - var i=-1; - while (++i 0){ - currentShape = addedLanes.first(); + // Set width from the pool + width = this.adjustWidth(lanes, pool.bounds.width()); + + pool.update(); + } + + /** + * Set width/height depending on the pool + */ + else if (pool == currentShape) { + + if (selection.length === 1 && this.isResized(pool, this.hashedPoolPositions[pool.id])) { + var oldXY = this.hashedPoolPositions[pool.id].upperLeft(); + var xy = pool.bounds.upperLeft(); + var scale = 0; + if (this.shouldScale(pool)) { + var old = this.hashedPoolPositions[pool.id]; + scale = old.height() / pool.bounds.height(); + } + + this.adjustLanes(pool, allLanes, oldXY.x - xy.x, oldXY.y - xy.y, scale); } - - - // Get all deleted lanes - var resourceIds = $H(this.hashedBounds[pool.id]).keys(); - var i=-1; - while (++i 0 || addedLanes.length > 0) { - - if (addedLanes.length === 1 && this.getLanes(addedLanes[0].parent).length === 1){ - // Set height from the pool - height = this.adjustHeight(lanes, addedLanes[0].parent); + + // Set height from the pool + height = this.adjustHeight(lanes, undefined, pool.bounds.height()); + // Set width from the pool + width = this.adjustWidth(lanes, pool.bounds.width()); + } + + /**??? + * Set width/height depending on containing lanes + */ + else { + + // Reposition the pool if one shape is selected and the upperleft has changed + if (selection.length === 1 && this.isResized(currentShape, this.hashedBounds[pool.id][currentShape.id])) { + var oldXY = this.hashedBounds[pool.id][currentShape.id].upperLeft(); + var xy = currentShape.absoluteXY(); + x = oldXY.x - xy.x; + y = oldXY.y - xy.y; + + // Adjust all other lanes beneath this lane + if (x || y) { + considerForDockers = considerForDockers.without(currentShape); + this.adjustLanes(pool, this.getAllExcludedLanes(pool, currentShape), x, 0); + } + + // Adjust all child lanes + var childLanes = this.getLanes(currentShape, true); + if (childLanes.length > 0) { + if (this.shouldScale(currentShape)) { + var old = this.hashedBounds[pool.id][currentShape.id]; + var scale = old.height() / currentShape.bounds.height(); + this.adjustLanes(pool, childLanes, x, y, scale); } else { - // Set height from the pool - height = this.updateHeight(pool); - } - // Set width from the pool - width = this.adjustWidth(lanes, pool.bounds.width()); - - pool.update(); - } - - /** - * Set width/height depending on the pool - */ - else if (pool == currentShape) { - - if (selection.length === 1 && this.isResized(pool, this.hashedPoolPositions[pool.id])) { - var oldXY = this.hashedPoolPositions[pool.id].upperLeft(); - var xy = pool.bounds.upperLeft(); - var scale = 0; - if (this.shouldScale(pool)){ - var old = this.hashedPoolPositions[pool.id]; - scale = old.height()/pool.bounds.height(); - } - - this.adjustLanes(pool, allLanes, oldXY.x - xy.x, oldXY.y - xy.y, scale); + this.adjustLanes(pool, childLanes, x, y, 0); } - - // Set height from the pool - height = this.adjustHeight(lanes, undefined, pool.bounds.height()); - // Set width from the pool - width = this.adjustWidth(lanes, pool.bounds.width()); - } - - /**??? - * Set width/height depending on containing lanes - */ - else { - - // Reposition the pool if one shape is selected and the upperleft has changed - if (selection.length === 1 && this.isResized(currentShape, this.hashedBounds[pool.id][currentShape.id])){ - var oldXY = this.hashedBounds[pool.id][currentShape.id].upperLeft(); - var xy = currentShape.absoluteXY(); - x = oldXY.x - xy.x; - y = oldXY.y - xy.y; - - // Adjust all other lanes beneath this lane - if (x||y){ - considerForDockers = considerForDockers.without(currentShape); - this.adjustLanes(pool, this.getAllExcludedLanes(pool, currentShape), x, 0); - } - - // Adjust all child lanes - var childLanes = this.getLanes(currentShape, true); - if (childLanes.length > 0){ - if (this.shouldScale(currentShape)){ - var old = this.hashedBounds[pool.id][currentShape.id]; - var scale = old.height()/currentShape.bounds.height(); - this.adjustLanes(pool, childLanes, x, y, scale); - } else { - this.adjustLanes(pool, childLanes, x, y, 0); - } - } - } - - // Cache all bounds - var changes = allLanes.map(function(lane){ return { - shape: lane, - bounds: lane.bounds.clone() - } }); - - // Get height and adjust child heights - height = this.adjustHeight(lanes, currentShape); - // Check if something has changed and maybe create a command - this.checkForChanges(allLanes, changes); - - // Set width from the current shape - width = this.adjustWidth(lanes, currentShape.bounds.width()+(this.getDepth(currentShape,pool)*30)); + } } - - this.setDimensions(pool, width, height, x, y); - - - if (this.facade.isExecutingCommands() && (deletedLanes.length === 0 || addedLanes.length !== 0)){ - // Update all dockers - this.updateDockers(considerForDockers, pool); - - // Check if the order has changed - if (this.hashedPositions[pool.id] && this.hashedPositions[pool.id].keys().any(function(key, i){ - return (allLanes[i]||{}).id !== key; - })){ - - var LanesHasBeenReordered = ORYX.Core.Command.extend({ - construct: function(originPosition, newPosition, lanes, plugin, poolId) { - this.originPosition = Object.clone(originPosition); - this.newPosition = Object.clone(newPosition); - this.lanes = lanes; - this.plugin = plugin; - this.pool = poolId; - }, - execute: function(){ - if (!this.executed){ - this.executed = true; - this.lanes.each(function(lane){ - if (this.newPosition[lane.id]) - lane.bounds.moveTo(this.newPosition[lane.id]) - }.bind(this)); - this.plugin.hashedPositions[this.pool] = Object.clone(this.newPosition); - } - }, - rollback: function(){ - this.lanes.each(function(lane){ - if (this.originPosition[lane.id]) - lane.bounds.moveTo(this.originPosition[lane.id]) - }.bind(this)); - this.plugin.hashedPositions[this.pool] = Object.clone(this.originPosition); - } - }); - - var hp2 = $H({}); - allLanes.each(function(lane){ - hp2[lane.id] = lane.bounds.upperLeft(); - }) - - var command = new LanesHasBeenReordered(hashedPositions, hp2, allLanes, this, pool.id); - this.facade.executeCommands([command]); - + + // Cache all bounds + var changes = allLanes.map(function (lane) { + return { + shape: lane, + bounds: lane.bounds.clone() + } + }); + + // Get height and adjust child heights + height = this.adjustHeight(lanes, currentShape); + // Check if something has changed and maybe create a command + this.checkForChanges(allLanes, changes); + + // Set width from the current shape + width = this.adjustWidth(lanes, currentShape.bounds.width() + (this.getDepth(currentShape, pool) * 30)); + } + + this.setDimensions(pool, width, height, x, y); + + + if (this.facade.isExecutingCommands() && (deletedLanes.length === 0 || addedLanes.length !== 0)) { + // Update all dockers + this.updateDockers(considerForDockers, pool); + + // Check if the order has changed + if (this.hashedPositions[pool.id] && this.hashedPositions[pool.id].keys().any(function (key, i) { + return (allLanes[i] || {}).id !== key; + })) { + + var LanesHasBeenReordered = ORYX.Core.Command.extend({ + construct: function (originPosition, newPosition, lanes, plugin, poolId) { + this.originPosition = Object.clone(originPosition); + this.newPosition = Object.clone(newPosition); + this.lanes = lanes; + this.plugin = plugin; + this.pool = poolId; + }, + execute: function () { + if (!this.executed) { + this.executed = true; + this.lanes.each(function (lane) { + if (this.newPosition[lane.id]) + lane.bounds.moveTo(this.newPosition[lane.id]) + }.bind(this)); + this.plugin.hashedPositions[this.pool] = Object.clone(this.newPosition); + } + }, + rollback: function () { + this.lanes.each(function (lane) { + if (this.originPosition[lane.id]) + lane.bounds.moveTo(this.originPosition[lane.id]) + }.bind(this)); + this.plugin.hashedPositions[this.pool] = Object.clone(this.originPosition); } + }); + + var hp2 = $H({}); + allLanes.each(function (lane) { + hp2[lane.id] = lane.bounds.upperLeft(); + }) + + var command = new LanesHasBeenReordered(hashedPositions, hp2, allLanes, this, pool.id); + this.facade.executeCommands([command]); + } - - this.hashedBounds[pool.id] = {}; - this.hashedPositions[pool.id] = hashedPositions; - - var i=-1; - while (++i < allLanes.length) { - // Cache positions - this.hashedBounds[pool.id][allLanes[i].id] = allLanes[i].absoluteBounds(); - - // Cache also the bounds of child shapes, mainly for child subprocesses - this.hashChildShapes(allLanes[i]); - - this.hashedLaneDepth[allLanes[i].id] = this.getDepth(allLanes[i], pool); - - this.forceToUpdateLane(allLanes[i]); - } - - this.hashedPoolPositions[pool.id] = pool.bounds.clone(); - - - // Update selection - //this.facade.setSelection(selection); + } + + this.hashedBounds[pool.id] = {}; + this.hashedPositions[pool.id] = hashedPositions; + + var i = -1; + while (++i < allLanes.length) { + // Cache positions + this.hashedBounds[pool.id][allLanes[i].id] = allLanes[i].absoluteBounds(); + + // Cache also the bounds of child shapes, mainly for child subprocesses + this.hashChildShapes(allLanes[i]); + + this.hashedLaneDepth[allLanes[i].id] = this.getDepth(allLanes[i], pool); + + this.forceToUpdateLane(allLanes[i]); + } + + this.hashedPoolPositions[pool.id] = pool.bounds.clone(); + + + // Update selection + //this.facade.setSelection(selection); }, - - shouldScale: function(element){ - var childLanes = element.getChildNodes().findAll(function(shape){ return shape.getStencil().id().endsWith("Lane") }) - return childLanes.length > 1 || childLanes.any(function(lane){ return this.shouldScale(lane) }.bind(this)) + + shouldScale: function (element) { + var childLanes = element.getChildNodes().findAll(function (shape) { + return shape.getStencil().id().endsWith("Lane") + }) + return childLanes.length > 1 || childLanes.any(function (lane) { + return this.shouldScale(lane) + }.bind(this)) }, - + /** * Lookup if some bounds has changed * @param {Object} lanes * @param {Object} changes */ - checkForChanges: function(lanes, changes){ - // Check if something has changed - if (this.facade.isExecutingCommands() && changes.any(function(change){ - return change.shape.bounds.toString() !== change.bounds.toString(); - })){ - - var Command = ORYX.Core.Command.extend({ - construct: function(changes) { - this.oldState = changes; - this.newState = changes.map(function(s){ return {shape:s.shape, bounds:s.bounds.clone()}}); - }, - execute: function(){ - if (this.executed){ - this.applyState(this.newState); - } - this.executed = true; - }, - rollback: function(){ - this.applyState(this.oldState); - }, - applyState: function(state){ - state.each(function(s){ - s.shape.bounds.set(s.bounds.upperLeft(), s.bounds.lowerRight()); - }) - } - }); - - this.facade.executeCommands([new Command(changes)]); - } - }, - - isResized: function(shape, bounds){ - - if (!bounds||!shape){ - return false; - } - - var oldB = bounds; - //var oldXY = oldB.upperLeft(); - //var xy = shape.absoluteXY(); - return Math.round(oldB.width() - shape.bounds.width()) !== 0 || Math.round(oldB.height() - shape.bounds.height()) !== 0 - }, - - adjustLanes: function(pool, lanes, x, y, scale){ - - scale = scale || 0; - - // For every lane, adjust the child nodes with the offset - lanes.each(function(l){ - l.getChildNodes().each(function(child){ - if (!child.getStencil().id().endsWith("Lane")){ - var cy = scale ? child.bounds.center().y - (child.bounds.center().y/scale) : -y; - child.bounds.moveBy((x||0), -cy); - - if (scale&&child.getStencil().id().endsWith("Subprocess")) { - this.moveChildDockers(child, {x:(0), y:-cy}); - } - - } - }.bind(this)); - this.hashedBounds[pool.id][l.id].moveBy(-(x||0), !scale?-y:0); - if (scale) { - l.isScaled = true; + checkForChanges: function (lanes, changes) { + // Check if something has changed + if (this.facade.isExecutingCommands() && changes.any(function (change) { + return change.shape.bounds.toString() !== change.bounds.toString(); + })) { + + var Command = ORYX.Core.Command.extend({ + construct: function (changes) { + this.oldState = changes; + this.newState = changes.map(function (s) { + return {shape: s.shape, bounds: s.bounds.clone()} + }); + }, + execute: function () { + if (this.executed) { + this.applyState(this.newState); } - }.bind(this)) - + this.executed = true; + }, + rollback: function () { + this.applyState(this.oldState); + }, + applyState: function (state) { + state.each(function (s) { + s.shape.bounds.set(s.bounds.upperLeft(), s.bounds.lowerRight()); + }) + } + }); + + this.facade.executeCommands([new Command(changes)]); + } + }, + + isResized: function (shape, bounds) { + + if (!bounds || !shape) { + return false; + } + + var oldB = bounds; + //var oldXY = oldB.upperLeft(); + //var xy = shape.absoluteXY(); + return Math.round(oldB.width() - shape.bounds.width()) !== 0 || Math.round(oldB.height() - shape.bounds.height()) !== 0 }, - - getAllExcludedLanes: function(parent, lane){ - var lanes = []; - parent.getChildNodes().each(function(shape){ - if ((!lane || shape !== lane) && shape.getStencil().id().endsWith("Lane")){ - lanes.push(shape); - lanes = lanes.concat(this.getAllExcludedLanes(shape, lane)); + + adjustLanes: function (pool, lanes, x, y, scale) { + + scale = scale || 0; + + // For every lane, adjust the child nodes with the offset + lanes.each(function (l) { + l.getChildNodes().each(function (child) { + if (!child.getStencil().id().endsWith("Lane")) { + var cy = scale ? child.bounds.center().y - (child.bounds.center().y / scale) : -y; + child.bounds.moveBy((x || 0), -cy); + + if (scale && child.getStencil().id().endsWith("Subprocess")) { + this.moveChildDockers(child, {x: (0), y: -cy}); } + + } }.bind(this)); - return lanes; - }, - - - forceToUpdateLane: function(lane){ - - if (lane.bounds.height() !== lane._svgShapes[0].height) { - lane.isChanged = true; - lane.isResized = true; - lane._update(); + this.hashedBounds[pool.id][l.id].moveBy(-(x || 0), !scale ? -y : 0); + if (scale) { + l.isScaled = true; } + }.bind(this)) + }, - - getDepth: function(child, parent){ - - var i=0; - while(child && child.parent && child !== parent){ - child = child.parent; - ++i + + getAllExcludedLanes: function (parent, lane) { + var lanes = []; + parent.getChildNodes().each(function (shape) { + if ((!lane || shape !== lane) && shape.getStencil().id().endsWith("Lane")) { + lanes.push(shape); + lanes = lanes.concat(this.getAllExcludedLanes(shape, lane)); } - return i; + }.bind(this)); + return lanes; }, - - updateDepth: function(lane, fromDepth, toDepth){ - - var xOffset = (fromDepth - toDepth) * 30; - - lane.getChildNodes().each(function(shape){ - shape.bounds.moveBy(xOffset, 0); - - [].concat(children[j].getIncomingShapes()) - .concat(children[j].getOutgoingShapes()) - - }) - + + + forceToUpdateLane: function (lane) { + + if (lane.bounds.height() !== lane._svgShapes[0].height) { + lane.isChanged = true; + lane.isResized = true; + lane._update(); + } }, - - setDimensions: function(shape, width, height, x, y){ - var isLane = shape.getStencil().id().endsWith("Lane"); - // Set the bounds - shape.bounds.set( - isLane ? 30 : (shape.bounds.a.x - (x || 0)), - isLane ? shape.bounds.a.y : (shape.bounds.a.y - (y || 0)), - width ? shape.bounds.a.x + width - (isLane?30:(x||0)) : shape.bounds.b.x, - height ? shape.bounds.a.y + height - (isLane?0:(y||0)) : shape.bounds.b.y - ); + + getDepth: function (child, parent) { + + var i = 0; + while (child && child.parent && child !== parent) { + child = child.parent; + ++i + } + return i; }, - setLanePosition: function(shape, y){ - - shape.bounds.moveTo(30, y); - + updateDepth: function (lane, fromDepth, toDepth) { + + var xOffset = (fromDepth - toDepth) * 30; + + lane.getChildNodes().each(function (shape) { + shape.bounds.moveBy(xOffset, 0); + + [].concat(children[j].getIncomingShapes()) + .concat(children[j].getOutgoingShapes()) + + }) + }, - - adjustWidth: function(lanes, width) { - - // Set width to each lane - (lanes||[]).each(function(lane){ - this.setDimensions(lane, width); - this.adjustWidth(this.getLanes(lane), width-30); - }.bind(this)); - - return width; + + setDimensions: function (shape, width, height, x, y) { + var isLane = shape.getStencil().id().endsWith("Lane"); + // Set the bounds + shape.bounds.set( + isLane ? 30 : (shape.bounds.a.x - (x || 0)), + isLane ? shape.bounds.a.y : (shape.bounds.a.y - (y || 0)), + width ? shape.bounds.a.x + width - (isLane ? 30 : (x || 0)) : shape.bounds.b.x, + height ? shape.bounds.a.y + height - (isLane ? 0 : (y || 0)) : shape.bounds.b.y + ); }, - - - adjustHeight: function(lanes, changedLane, propagateHeight){ - - var oldHeight = 0; - if (!changedLane && propagateHeight){ - var i=-1; - while (++i2 && edges[k].dockers[l-1].isDocked()){ + + l = -1; + while (++l < edges[k].dockers.length) { + + docker = edges[k].dockers[l]; + + if (docker.getDockedShape() || docker.isChanged) { + continue; + } + + + pos = docker.bounds.center(); + + // Check if the modified center included the new position + var isOverLane = oldBounds.isIncluded(pos); + // Check if the original center is over the pool + var isOutSidePool = !oldPool.isIncluded(pos); + var previousIsOverLane = l == 0 ? isOverLane : oldBounds.isIncluded(edges[k].dockers[l - 1].bounds.center()); + var nextIsOverLane = l == edges[k].dockers.length - 1 ? isOverLane : oldBounds.isIncluded(edges[k].dockers[l + 1].bounds.center()); + var off = Object.clone(offset); + + // If the + if (isScaled && isOverLane && this.isResized(lanes[i], this.hashedBounds[pool.id][lanes[i].id])) { + var relY = (pos.y - absBounds.upperLeft().y + off.y); + off.y -= (relY - (relY * (absBounds.height() / oldBounds.height()))); + } + + // Check if the previous dockers docked shape is from this lane + // Otherwise, check if the docker is over the lane OR is outside the lane + // but the previous/next was over this lane + if (isOverLane) { + dockers[docker.id] = {docker: docker, offset: off}; + } + /*else if (l == 1 && edges[k].dockers.length>2 && edges[k].dockers[l-1].isDocked()){ var dockedLane = this.getNextLane(edges[k].dockers[l-1].getDockedShape()); if (dockedLane != lanes[i]) continue; @@ -24089,422 +24834,427 @@ new function(){ continue; dockers[docker.id] = {docker: docker, offset:offset}; } - + else if (isOutSidePool) { dockers[docker.id] = {docker: docker, offset:this.getOffset(lanes[i], true, pool)}; }*/ - - - } - } - + + } + } + } - - // Move the moved children - var MoveChildCommand = ORYX.Core.Command.extend({ - construct: function(state){ - this.state = state; - }, - execute: function(){ - if (this.executed){ - this.state.each(function(s){ - s.shape.bounds.moveBy(s.xOffset, 0); - }); - } - this.executed = true; - }, - rollback: function(){ - this.state.each(function(s){ - s.shape.bounds.moveBy(-s.xOffset, 0); - }); - } - }) - - - // Set dockers - this.facade.executeCommands([new ORYX.Core.MoveDockersCommand(dockers), new MoveChildCommand(movedShapes)]); + } + + // Move the moved children + var MoveChildCommand = ORYX.Core.Command.extend({ + construct: function (state) { + this.state = state; + }, + execute: function () { + if (this.executed) { + this.state.each(function (s) { + s.shape.bounds.moveBy(s.xOffset, 0); + }); + } + this.executed = true; + }, + rollback: function () { + this.state.each(function (s) { + s.shape.bounds.moveBy(-s.xOffset, 0); + }); + } + }) + + + // Set dockers + this.facade.executeCommands([new ORYX.Core.MoveDockersCommand(dockers), new MoveChildCommand(movedShapes)]); }, - - moveBy: function(pos, offset){ - pos.x += offset.x; - pos.y += offset.y; - return pos; + + moveBy: function (pos, offset) { + pos.x += offset.x; + pos.y += offset.y; + return pos; }, - - getHashedBounds: function(shape){ - return this.currentPool && this.hashedBounds[this.currentPool.id][shape.id] ? this.hashedBounds[this.currentPool.id][shape.id] : shape.absoluteBounds(); + + getHashedBounds: function (shape) { + return this.currentPool && this.hashedBounds[this.currentPool.id][shape.id] ? this.hashedBounds[this.currentPool.id][shape.id] : shape.absoluteBounds(); }, - + /** * Returns a set on all child lanes for the given Shape. If recursive is TRUE, also indirect children will be returned (default is FALSE) * The set is sorted with first child the lowest y-coordinate and the last one the highest. * @param {ORYX.Core.Shape} shape * @param {boolean} recursive */ - getLanes: function(shape, recursive){ - var namespace = this.getNamespace(); - - // Get all the child lanes - var lanes = shape.getChildNodes(recursive||false).findAll(function(node) { return (node.getStencil().id() === namespace + "Lane"); }); - - // Sort all lanes by there y coordinate - lanes = lanes.sort(function(a, b){ - - // Get y coordinates for upper left and lower right - var auy = Math.round(a.bounds.upperLeft().y); - var buy = Math.round(b.bounds.upperLeft().y); - var aly = Math.round(a.bounds.lowerRight().y); - var bly = Math.round(b.bounds.lowerRight().y); - - var ha = this.getHashedBounds(a); - var hb = this.getHashedBounds(b); - - // Get the old y coordinates - var oauy = Math.round(ha.upperLeft().y); - var obuy = Math.round(hb.upperLeft().y); - var oaly = Math.round(ha.lowerRight().y); - var obly = Math.round(hb.lowerRight().y); - - // If equal, than use the old one - if (auy == buy && aly == bly) { - auy = oauy; buy = obuy; aly = oaly; bly = obly; - } - - if (Math.round(a.bounds.height()-ha.height()) === 0 && Math.round(b.bounds.height()-hb.height()) === 0){ - return auy < buy ? -1 : (auy > buy ? 1: 0); - } - - // Check if upper left and lower right is completely above/below - var above = auy < buy && aly < bly; - var below = auy > buy && aly > bly; - // Check if a is above b including the old values - var slightlyAboveBottom = auy < buy && aly >= bly && oaly < obly; - var slightlyAboveTop = auy >= buy && aly < bly && oauy < obuy; - // Check if a is below b including the old values - var slightlyBelowBottom = auy > buy && aly <= bly && oaly > obly; - var slightlyBelowTop = auy <= buy && aly > bly && oauy > obuy; - - // Return -1 if a is above b, 1 if b is above a, or 0 otherwise - return (above || slightlyAboveBottom || slightlyAboveTop ? -1 : (below || slightlyBelowBottom || slightlyBelowTop ? 1 : 0)) - }.bind(this)); - - // Return lanes - return lanes; + getLanes: function (shape, recursive) { + var namespace = this.getNamespace(); + + // Get all the child lanes + var lanes = shape.getChildNodes(recursive || false).findAll(function (node) { + return (node.getStencil().id() === namespace + "Lane"); + }); + + // Sort all lanes by there y coordinate + lanes = lanes.sort(function (a, b) { + + // Get y coordinates for upper left and lower right + var auy = Math.round(a.bounds.upperLeft().y); + var buy = Math.round(b.bounds.upperLeft().y); + var aly = Math.round(a.bounds.lowerRight().y); + var bly = Math.round(b.bounds.lowerRight().y); + + var ha = this.getHashedBounds(a); + var hb = this.getHashedBounds(b); + + // Get the old y coordinates + var oauy = Math.round(ha.upperLeft().y); + var obuy = Math.round(hb.upperLeft().y); + var oaly = Math.round(ha.lowerRight().y); + var obly = Math.round(hb.lowerRight().y); + + // If equal, than use the old one + if (auy == buy && aly == bly) { + auy = oauy; + buy = obuy; + aly = oaly; + bly = obly; + } + + if (Math.round(a.bounds.height() - ha.height()) === 0 && Math.round(b.bounds.height() - hb.height()) === 0) { + return auy < buy ? -1 : (auy > buy ? 1 : 0); + } + + // Check if upper left and lower right is completely above/below + var above = auy < buy && aly < bly; + var below = auy > buy && aly > bly; + // Check if a is above b including the old values + var slightlyAboveBottom = auy < buy && aly >= bly && oaly < obly; + var slightlyAboveTop = auy >= buy && aly < bly && oauy < obuy; + // Check if a is below b including the old values + var slightlyBelowBottom = auy > buy && aly <= bly && oaly > obly; + var slightlyBelowTop = auy <= buy && aly > bly && oauy > obuy; + + // Return -1 if a is above b, 1 if b is above a, or 0 otherwise + return (above || slightlyAboveBottom || slightlyAboveTop ? -1 : (below || slightlyBelowBottom || slightlyBelowTop ? 1 : 0)) + }.bind(this)); + + // Return lanes + return lanes; }, - - getNamespace: function() { - if(!this.namespace) { - var stencilsets = this.facade.getStencilSets(); - if(stencilsets.keys()) { - this.namespace = stencilsets.keys()[0]; - } else { - return undefined; - } + + getNamespace: function () { + if (!this.namespace) { + var stencilsets = this.facade.getStencilSets(); + if (stencilsets.keys()) { + this.namespace = stencilsets.keys()[0]; + } else { + return undefined; } - return this.namespace; - } - }; - - var ResizeLanesCommand = ORYX.Core.Command.extend({ - - construct: function(shape, parent, pool, plugin) { - - this.facade = plugin.facade; - this.plugin = plugin; - this.shape = shape; - this.changes; - - this.pool = pool; - - this.parent = parent; - - - this.shapeChildren = []; - - /* + } + return this.namespace; + } + }; + + var ResizeLanesCommand = ORYX.Core.Command.extend({ + + construct: function (shape, parent, pool, plugin) { + + this.facade = plugin.facade; + this.plugin = plugin; + this.shape = shape; + this.changes; + + this.pool = pool; + + this.parent = parent; + + + this.shapeChildren = []; + + /* * The Bounds have to be stored * separate because they would * otherwise also be influenced */ - this.shape.getChildShapes().each(function(childShape) { - this.shapeChildren.push({ - shape: childShape, - bounds: { - a: { - x: childShape.bounds.a.x, - y: childShape.bounds.a.y - }, - b: { - x: childShape.bounds.b.x, - y: childShape.bounds.b.y - } - } - }); - }.bind(this)); + this.shape.getChildShapes().each(function (childShape) { + this.shapeChildren.push({ + shape: childShape, + bounds: { + a: { + x: childShape.bounds.a.x, + y: childShape.bounds.a.y + }, + b: { + x: childShape.bounds.b.x, + y: childShape.bounds.b.y + } + } + }); + }.bind(this)); - this.shapeUpperLeft = this.shape.bounds.upperLeft(); - - // If there is no parent, - // correct the abs position with the parents abs. - /*if (!this.shape.parent) { + this.shapeUpperLeft = this.shape.bounds.upperLeft(); + + // If there is no parent, + // correct the abs position with the parents abs. + /*if (!this.shape.parent) { var pAbs = parent.absoluteXY(); this.shapeUpperLeft.x += pAbs.x; this.shapeUpperLeft.y += pAbs.y; }*/ - this.parentHeight = this.parent.bounds.height(); + this.parentHeight = this.parent.bounds.height(); }, - - getLeafLanes: function(lane){ - var childLanes = this.plugin.getLanes(lane).map(function(child){ - return this.getLeafLanes(child); - }.bind(this)).flatten(); - return childLanes.length > 0 ? childLanes : [lane]; + + getLeafLanes: function (lane) { + var childLanes = this.plugin.getLanes(lane).map(function (child) { + return this.getLeafLanes(child); + }.bind(this)).flatten(); + return childLanes.length > 0 ? childLanes : [lane]; }, - - findNewLane: function(){ - - var lanes = this.plugin.getLanes(this.parent); - var leafLanes = this.getLeafLanes(this.parent); - /*leafLanes = leafLanes.sort(function(a,b){ + findNewLane: function () { + + var lanes = this.plugin.getLanes(this.parent); + + var leafLanes = this.getLeafLanes(this.parent); + /*leafLanes = leafLanes.sort(function(a,b){ var aupl = a.absoluteXY().y; var bupl = b.absoluteXY().y; return aupl < bupl ? -1 : (aupl > bupl ? 1 : 0) })*/ - this.lane = leafLanes.find(function(l){ return l.bounds.upperLeft().y >= this.shapeUpperLeft.y }.bind(this)) || leafLanes.last(); - this.laneUpperLeft = this.lane.bounds.upperLeft(); + this.lane = leafLanes.find(function (l) { + return l.bounds.upperLeft().y >= this.shapeUpperLeft.y + }.bind(this)) || leafLanes.last(); + this.laneUpperLeft = this.lane.bounds.upperLeft(); }, - - execute: function() { - - if(this.changes) { - this.executeAgain(); - return; - } - /* + execute: function () { + + if (this.changes) { + this.executeAgain(); + return; + } + + /* * Rescue all ChildShapes of the deleted * Shape into the lane that takes its * place */ - - if (!this.lane){ - this.findNewLane(); - } - - if(this.lane) { - - var laUpL = this.laneUpperLeft; - var shUpL = this.shapeUpperLeft; - - var depthChange = this.plugin.getDepth(this.lane, this.parent)-1; - - this.changes = $H({}); - - // Selected lane is BELOW the removed lane - if (laUpL.y >= shUpL.y) { - this.lane.getChildShapes().each(function(childShape) { - - /* + + if (!this.lane) { + this.findNewLane(); + } + + if (this.lane) { + + var laUpL = this.laneUpperLeft; + var shUpL = this.shapeUpperLeft; + + var depthChange = this.plugin.getDepth(this.lane, this.parent) - 1; + + this.changes = $H({}); + + // Selected lane is BELOW the removed lane + if (laUpL.y >= shUpL.y) { + this.lane.getChildShapes().each(function (childShape) { + + /* * Cache the changes for rollback */ - if(!this.changes[childShape.getId()]) { - this.changes[childShape.getId()] = this.computeChanges(childShape, this.lane, this.lane, this.shape.bounds.height()); - } - - childShape.bounds.moveBy(0, this.shape.bounds.height()); - }.bind(this)); - - this.plugin.hashChildShapes(this.lane); - - this.shapeChildren.each(function(shapeChild) { - shapeChild.shape.bounds.set(shapeChild.bounds); - shapeChild.shape.bounds.moveBy((shUpL.x-30)-(depthChange*30), 0); - - /* + if (!this.changes[childShape.getId()]) { + this.changes[childShape.getId()] = this.computeChanges(childShape, this.lane, this.lane, this.shape.bounds.height()); + } + + childShape.bounds.moveBy(0, this.shape.bounds.height()); + }.bind(this)); + + this.plugin.hashChildShapes(this.lane); + + this.shapeChildren.each(function (shapeChild) { + shapeChild.shape.bounds.set(shapeChild.bounds); + shapeChild.shape.bounds.moveBy((shUpL.x - 30) - (depthChange * 30), 0); + + /* * Cache the changes for rollback */ - if(!this.changes[shapeChild.shape.getId()]) { - this.changes[shapeChild.shape.getId()] = this.computeChanges(shapeChild.shape, this.shape, this.lane, 0); - } - - this.lane.add(shapeChild.shape); - - }.bind(this)); - - this.lane.bounds.moveBy(0, shUpL.y-laUpL.y); - - // Selected lane is ABOVE the removed lane - } else if(shUpL.y > laUpL.y){ - - this.shapeChildren.each(function(shapeChild) { - shapeChild.shape.bounds.set(shapeChild.bounds); - shapeChild.shape.bounds.moveBy((shUpL.x-30)-(depthChange*30), this.lane.bounds.height()); - - /* + if (!this.changes[shapeChild.shape.getId()]) { + this.changes[shapeChild.shape.getId()] = this.computeChanges(shapeChild.shape, this.shape, this.lane, 0); + } + + this.lane.add(shapeChild.shape); + + }.bind(this)); + + this.lane.bounds.moveBy(0, shUpL.y - laUpL.y); + + // Selected lane is ABOVE the removed lane + } else if (shUpL.y > laUpL.y) { + + this.shapeChildren.each(function (shapeChild) { + shapeChild.shape.bounds.set(shapeChild.bounds); + shapeChild.shape.bounds.moveBy((shUpL.x - 30) - (depthChange * 30), this.lane.bounds.height()); + + /* * Cache the changes for rollback */ - if(!this.changes[shapeChild.shape.getId()]) { - this.changes[shapeChild.shape.getId()] = this.computeChanges(shapeChild.shape, this.shape, this.lane, 0); - } - - this.lane.add(shapeChild.shape); - - }.bind(this)); + if (!this.changes[shapeChild.shape.getId()]) { + this.changes[shapeChild.shape.getId()] = this.computeChanges(shapeChild.shape, this.shape, this.lane, 0); } - - - + this.lane.add(shapeChild.shape); + + }.bind(this)); } - - /* + + + } + + /* * Adjust the height of the lanes */ - // Get the height values - var oldHeight = this.lane.bounds.height(); - var newHeight = this.lane.length === 1 ? this.parentHeight : this.lane.bounds.height() + this.shape.bounds.height(); - - // Set height - this.setHeight(newHeight, oldHeight, this.parent, this.parentHeight, true); - - // Cache all sibling lanes - //this.changes[this.shape.getId()] = this.computeChanges(this.shape, this.parent, this.parent, 0); - this.plugin.getLanes(this.parent).each(function(childLane){ - if(!this.changes[childLane.getId()] && childLane !== this.lane && childLane !== this.shape) { - this.changes[childLane.getId()] = this.computeChanges(childLane, this.parent, this.parent, 0); - } - }.bind(this)) - - // Update - this.update(); - }, - - setHeight: function(newHeight, oldHeight, parent, parentHeight, store){ - - // Set heigh of the lane - this.plugin.setDimensions(this.lane, this.lane.bounds.width(), newHeight); - this.plugin.hashedBounds[this.pool.id][this.lane.id] = this.lane.absoluteBounds(); - - // Adjust child lanes - this.plugin.adjustHeight(this.plugin.getLanes(parent), this.lane); - - if (store === true){ - // Store changes - this.changes[this.shape.getId()] = this.computeChanges(this.shape, parent, parent, 0, oldHeight, newHeight); - } - - // Set parents height - this.plugin.setDimensions(parent, parent.bounds.width(), parentHeight); - - if (parent !== this.pool){ - this.plugin.setDimensions(this.pool, this.pool.bounds.width(), this.pool.bounds.height() + (newHeight-oldHeight)); + // Get the height values + var oldHeight = this.lane.bounds.height(); + var newHeight = this.lane.length === 1 ? this.parentHeight : this.lane.bounds.height() + this.shape.bounds.height(); + + // Set height + this.setHeight(newHeight, oldHeight, this.parent, this.parentHeight, true); + + // Cache all sibling lanes + //this.changes[this.shape.getId()] = this.computeChanges(this.shape, this.parent, this.parent, 0); + this.plugin.getLanes(this.parent).each(function (childLane) { + if (!this.changes[childLane.getId()] && childLane !== this.lane && childLane !== this.shape) { + this.changes[childLane.getId()] = this.computeChanges(childLane, this.parent, this.parent, 0); } + }.bind(this)) + + // Update + this.update(); }, - - update: function(){ - - // Hack to prevent the updating of the dockers - this.plugin.hashedBounds[this.pool.id]["REMOVED"] = true; - // Update - //this.facade.getCanvas().update(); + + setHeight: function (newHeight, oldHeight, parent, parentHeight, store) { + + // Set heigh of the lane + this.plugin.setDimensions(this.lane, this.lane.bounds.width(), newHeight); + this.plugin.hashedBounds[this.pool.id][this.lane.id] = this.lane.absoluteBounds(); + + // Adjust child lanes + this.plugin.adjustHeight(this.plugin.getLanes(parent), this.lane); + + if (store === true) { + // Store changes + this.changes[this.shape.getId()] = this.computeChanges(this.shape, parent, parent, 0, oldHeight, newHeight); + } + + // Set parents height + this.plugin.setDimensions(parent, parent.bounds.width(), parentHeight); + + if (parent !== this.pool) { + this.plugin.setDimensions(this.pool, this.pool.bounds.width(), this.pool.bounds.height() + (newHeight - oldHeight)); + } }, - - rollback: function() { - - var laUpL = this.laneUpperLeft; - var shUpL = this.shapeUpperLeft; - - this.changes.each(function(pair) { - - var parent = pair.value.oldParent; - var shape = pair.value.shape; - var parentHeight = pair.value.parentHeight; - var oldHeight = pair.value.oldHeight; - var newHeight = pair.value.newHeight; - - // Move siblings - if (shape.getStencil().id().endsWith("Lane")){ - shape.bounds.moveTo(pair.value.oldPosition); - } - - // If lane - if(oldHeight) { - this.setHeight(oldHeight, newHeight, parent, parent.bounds.height() + (oldHeight - newHeight)); - if (laUpL.y >= shUpL.y) { - this.lane.bounds.moveBy(0, this.shape.bounds.height()-1); - } - } else { - parent.add(shape); - shape.bounds.moveTo(pair.value.oldPosition); - - } - - }.bind(this)); - - // Update - //this.update(); - + update: function () { + + // Hack to prevent the updating of the dockers + this.plugin.hashedBounds[this.pool.id]["REMOVED"] = true; + // Update + //this.facade.getCanvas().update(); }, - - executeAgain: function() { - - this.changes.each(function(pair) { - var parent = pair.value.newParent; - var shape = pair.value.shape; - var newHeight = pair.value.newHeight; - var oldHeight = pair.value.oldHeight; - - // If lane - if(newHeight) { - var laUpL = this.laneUpperLeft.y; - var shUpL = this.shapeUpperLeft.y; - - if (laUpL >= shUpL) { - this.lane.bounds.moveBy(0, shUpL - laUpL); - } - this.setHeight(newHeight, oldHeight, parent, parent.bounds.height() + (newHeight-oldHeight)); - } else { - parent.add(shape); - shape.bounds.moveTo(pair.value.newPosition); - } - - }.bind(this)); - - // Update - this.update(); + + rollback: function () { + + var laUpL = this.laneUpperLeft; + var shUpL = this.shapeUpperLeft; + + this.changes.each(function (pair) { + + var parent = pair.value.oldParent; + var shape = pair.value.shape; + var parentHeight = pair.value.parentHeight; + var oldHeight = pair.value.oldHeight; + var newHeight = pair.value.newHeight; + + // Move siblings + if (shape.getStencil().id().endsWith("Lane")) { + shape.bounds.moveTo(pair.value.oldPosition); + } + + // If lane + if (oldHeight) { + this.setHeight(oldHeight, newHeight, parent, parent.bounds.height() + (oldHeight - newHeight)); + if (laUpL.y >= shUpL.y) { + this.lane.bounds.moveBy(0, this.shape.bounds.height() - 1); + } + } else { + parent.add(shape); + shape.bounds.moveTo(pair.value.oldPosition); + + } + + + }.bind(this)); + + // Update + //this.update(); + }, - - computeChanges: function(shape, oldParent, parent, yOffset, oldHeight, newHeight) { - - oldParent = this.changes[shape.getId()] ? this.changes[shape.getId()].oldParent : oldParent; - var oldPosition = this.changes[shape.getId()] ? this.changes[shape.getId()].oldPosition : shape.bounds.upperLeft(); - - var sUl = shape.bounds.upperLeft(); - - var pos = {x: sUl.x, y: sUl.y + yOffset}; - - var changes = { - shape : shape, - parentHeight: oldParent.bounds.height(), - oldParent : oldParent, - oldPosition : oldPosition, - oldHeight : oldHeight, - newParent : parent, - newPosition : pos, - newHeight : newHeight - }; - - return changes; + + executeAgain: function () { + + this.changes.each(function (pair) { + var parent = pair.value.newParent; + var shape = pair.value.shape; + var newHeight = pair.value.newHeight; + var oldHeight = pair.value.oldHeight; + + // If lane + if (newHeight) { + var laUpL = this.laneUpperLeft.y; + var shUpL = this.shapeUpperLeft.y; + + if (laUpL >= shUpL) { + this.lane.bounds.moveBy(0, shUpL - laUpL); + } + this.setHeight(newHeight, oldHeight, parent, parent.bounds.height() + (newHeight - oldHeight)); + } else { + parent.add(shape); + shape.bounds.moveTo(pair.value.newPosition); + } + + }.bind(this)); + + // Update + this.update(); + }, + + computeChanges: function (shape, oldParent, parent, yOffset, oldHeight, newHeight) { + + oldParent = this.changes[shape.getId()] ? this.changes[shape.getId()].oldParent : oldParent; + var oldPosition = this.changes[shape.getId()] ? this.changes[shape.getId()].oldPosition : shape.bounds.upperLeft(); + + var sUl = shape.bounds.upperLeft(); + + var pos = {x: sUl.x, y: sUl.y + yOffset}; + + var changes = { + shape: shape, + parentHeight: oldParent.bounds.height(), + oldParent: oldParent, + oldPosition: oldPosition, + oldHeight: oldHeight, + newParent: parent, + newPosition: pos, + newHeight: newHeight + }; + + return changes; } - - }); - - ORYX.Plugins.BPMN2_0 = ORYX.Plugins.AbstractPlugin.extend(ORYX.Plugins.BPMN2_0); - -}() \ No newline at end of file + }); + + + ORYX.Plugins.BPMN2_0 = ORYX.Plugins.AbstractPlugin.extend(ORYX.Plugins.BPMN2_0); + +}() diff --git a/pear-modules/pear-process/src/main/resources/static/editor-app/eventbus.js b/pear-modules/pear-process/src/main/resources/static/editor-app/eventbus.js index d67991004dcedc3bb03b9aab390cce8b41e12206..f1c04759a20bb2949dfa563ea6b63854a5379904 100644 --- a/pear-modules/pear-process/src/main/resources/static/editor-app/eventbus.js +++ b/pear-modules/pear-process/src/main/resources/static/editor-app/eventbus.js @@ -1,7 +1,7 @@ /* * Activiti Modeler component part of the Activiti project * Copyright 2005-2014 Alfresco Software, Ltd. All rights reserved. - * + * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either @@ -47,7 +47,7 @@ KISBPM.eventBus = { /** Event fired when a model is saved. */ EVENT_TYPE_MODEL_SAVED: 'event-type-model-saved', - + /** Event fired when the quick menu buttons should be hidden. */ EVENT_TYPE_HIDE_SHAPE_BUTTONS: 'event-type-hide-shape-buttons', @@ -95,15 +95,15 @@ KISBPM.eventBus = { } }, - hasListener:function(type, callback, scope) { - if(typeof this.listeners[type] != "undefined") { + hasListener: function (type, callback, scope) { + if (typeof this.listeners[type] != "undefined") { var numOfCallbacks = this.listeners[type].length; - if(callback === undefined && scope === undefined){ + if (callback === undefined && scope === undefined) { return numOfCallbacks > 0; } - for(var i=0; i - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pear-modules/pear-process/src/main/resources/static/editor-app/fonts/glyphicons-halflings-regular.svg b/pear-modules/pear-process/src/main/resources/static/editor-app/fonts/glyphicons-halflings-regular.svg index 4469488747892e5d72de3752a17705b0f02bec91..16017e04777c720e685d99f39bd7b0105bd0a758 100644 --- a/pear-modules/pear-process/src/main/resources/static/editor-app/fonts/glyphicons-halflings-regular.svg +++ b/pear-modules/pear-process/src/main/resources/static/editor-app/fonts/glyphicons-halflings-regular.svg @@ -1,229 +1,410 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pear-modules/pear-process/src/main/resources/static/editor-app/i18n/en.json b/pear-modules/pear-process/src/main/resources/static/editor-app/i18n/en.json index def96657a0edc9422dbab622d39188d1ee6ba41a..ef32a3216e50c54ee1d3bc041f39e8ec996e3114 100644 --- a/pear-modules/pear-process/src/main/resources/static/editor-app/i18n/en.json +++ b/pear-modules/pear-process/src/main/resources/static/editor-app/i18n/en.json @@ -1,286 +1,259 @@ { - "HEADER.BRAND" : "Activiti编辑", - "HEADER.BRAND_TAGLINE" : "powered by Alfresco", - "PAGE.HEADER" : "Orchestration Details", - - "ACTION.OK" : "确认", - "ACTION.SAVE" : "保存", - "ACTION.SAVE-AND-CLOSE" : "确认保存", - "ACTION.SEND" : "发送", - "ACTION.CANCEL" : "取消", - "ACTION.SELECT" : "选择", - "ACTION.ADD" : "添加", - "ACTION.REMOVE" : "清除", - "ACTION.MOVE.UP" : "上移", - "ACTION.MOVE.DOWN" : "下移", - - "MAIN_NAVIGATION_ORCHESTRATIONS" : "业务流程", - "MAIN_NAVIGATION_DISPATCH_RULES" : "调度规则", - "MAIN_NAVIGATION_ASSET_GROUPS" : "审批组", - "MAIN_NAVIGATION_SOLUTIONS" : "解决", - - "TOOLBAR.ACTION.CLOSE" : "Close the editor and go back to the overview page", - "TOOLBAR.ACTION.SAVE" : "保存", - "TOOLBAR.ACTION.VALIDATE": "校验", - "TOOLBAR.ACTION.CUT" : "剪切", - "TOOLBAR.ACTION.COPY" : "复制", - "TOOLBAR.ACTION.PASTE" : "粘贴", - "TOOLBAR.ACTION.DELETE" : "删除", - "TOOLBAR.ACTION.UNDO" : "撤销", - "TOOLBAR.ACTION.REDO" : "重复", - "TOOLBAR.ACTION.ZOOMIN" : "放大", - "TOOLBAR.ACTION.ZOOMOUT" : "缩小", - "TOOLBAR.ACTION.ZOOMACTUAL" : "实际大小 ", - "TOOLBAR.ACTION.ZOOMFIT" : "适应屏幕", - "TOOLBAR.ACTION.MOVE" : "移动", - "TOOLBAR.ACTION.IMPORT" : "导入", - "TOOLBAR.ACTION.EXPORT" : "导出", - "TOOLBAR.ACTION.BENDPOINT.ADD" : "为选定的流程连线添加弯曲点", - "TOOLBAR.ACTION.BENDPOINT.REMOVE" : "为选定的流程连线删除弯曲点", - "TOOLBAR.ACTION.ALIGNHORIZONTAL" : "水平对齐", - "TOOLBAR.ACTION.ALIGNVERTICAL" : "垂直对齐", - "TOOLBAR.ACTION.SAMESIZE" : "Same size", - "TOOLBAR.ACTION.HELP": "Start the guided tour", - "TOOLBAR.ACTION.FEEDBACK": "Provide feedback", - - "KICKSTART.PROCESS_TOOLBAR.ACTION.SAVE" : "保存", - "KICKSTART.PROCESS_TOOLBAR.ACTION.VALIDATE": "校验模型", - "KICKSTART.PROCESS_TOOLBAR.ACTION.HELP": "预览", - "KICKSTART.PROCESS_TOOLBAR.ACTION.FEEDBACK": "反馈", - - "FORM_TOOLBAR.ACTION.SAVE" : "保存", - "FORM_TOOLBAR.ACTION.VALIDATE": "校验模型", - "FORM_TOOLBAR.ACTION.HELP": "预览", - "FORM_TOOLBAR.ACTION.FEEDBACK": "反馈", - - "APP_DEFINITION_TOOLBAR.ACTION.SAVE" : "保存", - "APP_DEFINITION_TOOLBAR.ACTION.VALIDATE" : "校验模型", - "APP_DEFINITION_TOOLBAR.ACTION.HELP" : "预览", - "APP_DEFINITION_TOOLBAR.ACTION.FEEDBACK" : "反馈", - - "BUTTON.ACTION.DELETE.TOOLTIP": "从模型中删除元素", - "BUTTON.ACTION.MORPH.TOOLTIP": "更改元素类型", - - "ELEMENT.AUTHOR" : "作者", - "ELEMENT.DATE_CREATED" : "创建日期", - "ELEMENT.SELECTED_EMPTY_TITLE" : "(输入名称)", - - "PROPERTY.REMOVED" : "清除", - "PROPERTY.EMPTY" : "", - "PROPERTY.PROPERTY.EDIT.TITLE" : "修改 \"{{title}}\"", - - "PROPERTY.FEEDBACK.TITLE" : "请填写您的反馈意见", - - "PROPERTY.ASSIGNMENT.TITLE" : "指派", - "PROPERTY.ASSIGNMENT.TYPE" : "类型", - "PROPERTY.ASSIGNMENT.TYPE.IDENTITYSTORE" : "Identity store", - "PROPERTY.ASSIGNMENT.TYPE.STATIC" : "静态值", - "PROPERTY.ASSIGNMENT.ASSIGNEE" : "代理人", - "PROPERTY.ASSIGNMENT.MATCHING" : "使用上下方向键选择并按回车键确认或使用鼠标", - "PROPERTY.ASSIGNMENT.ASSIGNEE_PLACEHOLDER" : "请输入代理人", - "PROPERTY.ASSIGNMENT.EMPTY" : "无代理人", - "PROPERTY.ASSIGNMENT.ASSIGNEE_DISPLAY" : "代理人 {{assignee}}", - "PROPERTY.ASSIGNMENT.CANDIDATE_USERS_DISPLAY" : "{{length}}候选人", - "PROPERTY.ASSIGNMENT.CANDIDATE_USERS" : "候选人", - "PROPERTY.ASSIGNMENT.CANDIDATE_GROUPS_DISPLAY" : "{{length}}候选组", - "PROPERTY.ASSIGNMENT.CANDIDATE_GROUPS" : "候选组", - "PROPERTY.ASSIGNMENT.USER_IDM_DISPLAY": "用户{{firstName}} {{lastName}}", - "PROPERTY.ASSIGNMENT.USER_IDM_EMAIL_DISPLAY": "用户{{email}}", - "PROPERTY.ASSIGNMENT.IDM_EMPTY" : "发起人", - "PROPERTY.ASSIGNMENT.IDM.TYPE" : "任务", - "PROPERTY.ASSIGNMENT.IDM.NO_CANDIDATE_USERS" : "没有选择候选人...", - "PROPERTY.ASSIGNMENT.IDM.NO_CANDIDATE_GROUPS" : "没有选择候选组...", - "PROPERTY.ASSIGNMENT.IDM.DROPDOWN.INITIATOR" : "分派给发起人", - "PROPERTY.ASSIGNMENT.IDM.DROPDOWN.USER" : "分派给一个用户", - "PROPERTY.ASSIGNMENT.IDM.DROPDOWN.USERS" : "候选人s", - "PROPERTY.ASSIGNMENT.IDM.DROPDOWN.GROUPS" : "候选组", - "PROPERTY.ASSIGNMENT.EMAIL.HELP" : "键入一个电子邮件地址,然后按回车键继续 ", - - "PROPERTY.EXECUTIONLISTENERS.DISPLAY" : "{{length}}执行监听", - "PROPERTY.EXECUTIONLISTENERS.EMPTY" : "没有配置执行监听", - "PROPERTY.EXECUTIONLISTENERS.EVENT" : "事件", - "PROPERTY.EXECUTIONLISTENERS.CLASS" : "类", - "PROPERTY.EXECUTIONLISTENERS.CLASS.PLACEHOLDER" : "输入类名", - "PROPERTY.EXECUTIONLISTENERS.EXPRESSION" : "表达式", - "PROPERTY.EXECUTIONLISTENERS.EXPRESSION.PLACEHOLDER" : "输入表达式", - "PROPERTY.EXECUTIONLISTENERS.DELEGATEEXPRESSION" : "委托表达式", - "PROPERTY.EXECUTIONLISTENERS.DELEGATEEXPRESSION.PLACEHOLDER" : "输入委托表达式", - "PROPERTY.EXECUTIONLISTENERS.UNSELECTED" : "没有配置执行监听", - "PROPERTY.EXECUTIONLISTENERS.FIELDS.NAME" : "名称", - "PROPERTY.EXECUTIONLISTENERS.FIELDS.NAME.PLACEHOLDER" : "输入名称", - "PROPERTY.EXECUTIONLISTENERS.FIELDS.EXPRESSION" : "表达式", - "PROPERTY.EXECUTIONLISTENERS.FIELDS.EXPRESSION.PLACEHOLDER" : "输入表达式", - "PROPERTY.EXECUTIONLISTENERS.FIELDS.STRINGVALUE" : "字符串", - "PROPERTY.EXECUTIONLISTENERS.FIELDS.STRINGVALUE.PLACEHOLDER" : "输入字符串", - "PROPERTY.EXECUTIONLISTENERS.FIELDS.STRING" : "字符串", - "PROPERTY.EXECUTIONLISTENERS.FIELDS.STRING.PLACEHOLDER" : "输入字符串", - "PROPERTY.EXECUTIONLISTENERS.FIELDS.IMPLEMENTATION" : "实现类", - "PROPERTY.EXECUTIONLISTENERS.FIELDS.EMPTY" : "没有选择字段", - - "PROPERTY.FIELDS" : "{{length}}字段", - "PROPERTY.FIELDS.EMPTY" : "没有选择字段", - "PROPERTY.FIELDS.NAME" : "名称", - "PROPERTY.FIELDS.NAME.PLACEHOLDER" : "输入名称", - "PROPERTY.FIELDS.EXPRESSION" : "表达式", - "PROPERTY.FIELDS.EXPRESSION.PLACEHOLDER" : "输入表达式", - "PROPERTY.FIELDS.STRINGVALUE" : "字符串", - "PROPERTY.FIELDS.STRINGVALUE.PLACEHOLDER" : "输入字符串", - "PROPERTY.FIELDS.STRING" : "字符串", - "PROPERTY.FIELDS.STRING.PLACEHOLDER" : "输入字符串", - "PROPERTY.FIELDS.IMPLEMENTATION" : "实现类", - "PROPERTY.FIELDS.UNSELECTED" : "没有选择字段", - - "PROPERTY.FORMPROPERTIES.VALUE" : "{{length}}表单属性", - "PROPERTY.FORMPROPERTIES.EMPTY" : "没有配置表单", - "PROPERTY.FORMPROPERTIES.ID" : "活动编号", - "PROPERTY.FORMPROPERTIES.ID.PLACEHOLDER" : "输入活动编号", - "PROPERTY.FORMPROPERTIES.NAME" : "名称", - "PROPERTY.FORMPROPERTIES.NAME.PLACEHOLDER" : "输入名称", - "PROPERTY.FORMPROPERTIES.TYPE" : "类型", - "PROPERTY.FORMPROPERTIES.DATEPATTERN" : "时间选择框", - "PROPERTY.FORMPROPERTIES.DATEPATTERN.PLACEHOLDER" : "输入日期", - "PROPERTY.FORMPROPERTIES.VALUES" : "值", - "PROPERTY.FORMPROPERTIES.EXPRESSION" : "表达式", - "PROPERTY.FORMPROPERTIES.EXPRESSION.PLACEHOLDER" : "输入表达式", - "PROPERTY.FORMPROPERTIES.VARIABLE" : "变量", - "PROPERTY.FORMPROPERTIES.VARIABLE.PLACEHOLDER" : "输入变量", - "PROPERTY.FORMPROPERTIES.REQUIRED" : "必输", - "PROPERTY.FORMPROPERTIES.READABLE" : "可读", - "PROPERTY.FORMPROPERTIES.WRITABLE" : "可写", - - "PROPERTY.INPARAMETERS.VALUE" : "{{length}}输入参数", - "PROPERTY.INPARAMETERS.EMPTY" : "没有配置输入参数", - - "PROPERTY.OUTPARAMETERS.VALUE" : "{{length}}返回参数", - "PROPERTY.OUTPARAMETERS.EMPTY" : "没有配置返回参数", - - "PROPERTY.PARAMETER.SOURCE" : "源", - "PROPERTY.PARAMETER.SOURCE.PLACEHOLDER" : "输入源", - "PROPERTY.PARAMETER.SOURCEEXPRESSION" : "源表达式", - "PROPERTY.PARAMETER.SOURCEEXPRESSION.PLACEHOLDER" : "输入源表达式", - "PROPERTY.PARAMETER.TARGET" : "目标", - "PROPERTY.PARAMETER.TARGET.PLACEHOLDER" : "输入目标", - "PROPERTY.PARAMETER.EMPTY" : "没有选择参数", - - "PROPERTY.SUBPROCESSREFERENCE.EMPTY" : "没有引用子流程", - "PROPERTY.SUBPROCESSREFERENCE.TITLE" : "引用错误的子流程", - "PROPERTY.SUBPROCESSREFERENCE.ERROR.SUBPROCESS" : "子流程加载错误.请稍后再试", - "PROPERTY.SUBPROCESSREFERENCE.FOLDER.ROOT" : "文件夹", - "PROPERTY.SUBPROCESSREFERENCE.FOLDER.LOADING" : "文件夹加载中...", - "PROPERTY.SUBPROCESSREFERENCE.FOLDER.EMPTY" : "文件夹未包含子文件夹", - "PROPERTY.SUBPROCESSREFERENCE.SUBPROCESS.LOADING" : "子流程加载中...", - "PROPERTY.SUBPROCESSREFERENCE.SUBPROCESS.EMPTY" : "文件夹包含子文件夹", - - "PROPERTY.FORMREFERENCE.EMPTY" : "没有引用表单", - "PROPERTY.FORMREFERENCE.TITLE" : "表单引用", - "PROPERTY.FORMREFERENCE.ERROR.FORM" : "表单加载错误.请稍后再试!", - "PROPERTY.FORMREFERENCE.FOLDER.ROOT" : "文件夹", - "PROPERTY.FORMREFERENCE.FOLDER.LOADING" : "文件夹加载中...", - "PROPERTY.FORMREFERENCE.FOLDER.EMPTY" : "文件夹未包含子文件夹", - "PROPERTY.FORMREFERENCE.FORM.LOADING" : "表单加载中...", - "PROPERTY.FORMREFERENCE.FORM.EMPTY" : "文件夹包含子文件夹", - - "PROPERTY.TASKLISTENERS.VALUE" : "{{length}}任务监听", - "PROPERTY.TASKLISTENERS.EMPTY" : "未配置任务监听", - "PROPERTY.TASKLISTENERS.EVENT" : "事件", - "PROPERTY.TASKLISTENERS.CLASS" : "类", - "PROPERTY.TASKLISTENERS.CLASS.PLACEHOLDER" : "输入类名", - "PROPERTY.TASKLISTENERS.EXPRESSION" : "表达式", - "PROPERTY.TASKLISTENERS.EXPRESSION.PLACEHOLDER" : "请输入表达式", - "PROPERTY.TASKLISTENERS.DELEGATEEXPRESSION" : "委托表达式", - "PROPERTY.TASKLISTENERS.DELEGATEEXPRESSION.PLACEHOLDER" : "请输入委托表达式", - "PROPERTY.TASKLISTENERS.UNSELECTED" : "没有选择任务监听", - "PROPERTY.TASKLISTENERS.FIELDS.NAME" : "名称", - "PROPERTY.TASKLISTENERS.FIELDS.NAME.PLACEHOLDER" : "请输入名称", - "PROPERTY.TASKLISTENERS.FIELDS.EXPRESSION" : "表达式", - "PROPERTY.TASKLISTENERS.FIELDS.EXPRESSION.PLACEHOLDER" : "请输入表达式", - "PROPERTY.TASKLISTENERS.FIELDS.STRINGVALUE" : "字符串", - "PROPERTY.TASKLISTENERS.FIELDS.STRINGVALUE.PLACEHOLDER" : "请输入字符串", - "PROPERTY.TASKLISTENERS.FIELDS.STRING" : "字符串", - "PROPERTY.TASKLISTENERS.FIELDS.STRING.PLACEHOLDER" : "请输入字符串", - "PROPERTY.TASKLISTENERS.FIELDS.IMPLEMENTATION" : "执行", - "PROPERTY.TASKLISTENERS.FIELDS.EMPTY" : "未选择字段", - - "PROPERTY.EVENTLISTENERS.DISPLAY" : "{{length}}事件监听", - "PROPERTY.EVENTLISTENERS.EMPTY" : "未配置事件监听", - "PROPERTY.EVENTLISTENERS.EVENTS": "事件", - "PROPERTY.EVENTLISTENERS.RETHROW": "抛出事件?", - "PROPERTY.EVENTLISTENERS.CLASS" : "类", - "PROPERTY.EVENTLISTENERS.CLASS.PLACEHOLDER" : "输入类名", - "PROPERTY.EVENTLISTENERS.DELEGATEEXPRESSION" : "委托表达式", - "PROPERTY.EVENTLISTENERS.DELEGATEEXPRESSION.PLACEHOLDER" : "请输入委托表达式", - "PROPERTY.EVENTLISTENERS.ENTITYTYPE" : "类型", - "PROPERTY.EVENTLISTENERS.ENTITYTYPE.PLACEHOLDER" : "请输入类型", - "PROPERTY.EVENTLISTENERS.RETHROWTYPE": "抛出事件类型", - "PROPERTY.EVENTLISTENERS.ERRORCODE" : "错误代码", - "PROPERTY.EVENTLISTENERS.ERRORCODE.PLACEHOLDER" : "请输入错误代码", - "PROPERTY.EVENTLISTENERS.MESSAGENAME" : "消息名称", - "PROPERTY.EVENTLISTENERS.MESSAGENAME.PLACEHOLDER" : "请输入消息名称", - "PROPERTY.EVENTLISTENERS.SIGNALNAME" : "信号名称", - "PROPERTY.EVENTLISTENERS.SIGNALNAME.PLACEHOLDER" : "请输入信号名称", - "PROPERTY.EVENTLISTENERS.UNSELECTED" : "没有选择事件监听", - - "PROPERTY.SIGNALDEFINITIONS.DISPLAY" : "{{length}}信号定义", - "PROPERTY.SIGNALDEFINITIONS.EMPTY" : "没有配置信号定义", - "PROPERTY.SIGNALDEFINITIONS.SCOPE-GLOBAL": "全局", - "PROPERTY.SIGNALDEFINITIONS.SCOPE-PROCESSINSTANCE": "流程初始化", - "PROPERTY.SIGNALDEFINITIONS.ID" : "编号", - "PROPERTY.SIGNALDEFINITIONS.NAME" : "名称", - "PROPERTY.SIGNALDEFINITIONS.SCOPE" : "Scope", - - "PROPERTY.MESSAGEDEFINITIONS.DISPLAY" : "{{length}}消息定义", - "PROPERTY.MESSAGEDEFINITIONS.EMPTY" : "没有配置消息定义", - "PROPERTY.MESSAGEDEFINITIONS.ID" : "编号", - "PROPERTY.MESSAGEDEFINITIONS.NAME" : "名称", - - "PROPERTY.SEQUENCEFLOW.ORDER.EMPTY" : "没有确定顺序流排序", - "PROPERTY.SEQUENCEFLOW.ORDER.NOT.EMPTY" : "顺序流排序", - "PROPERTY.SEQUENCEFLOW.ORDER.NO.OUTGOING.SEQUENCEFLOW.FOUND" : "没有输出顺序流.", - "PROPERTY.SEQUENCEFLOW.ORDER.DESCRIPTION" : "不能设置已经被使用的编号:", - "PROPERTY.SEQUENCEFLOW.ORDER.SEQUENCEFLOW.VALUE" : "顺序流{{targetType}} {{targetTitle}}", - - "PROPERTY.SEQUENCEFLOW.CONDITION.TITLE" : "条件", - "PROPERTY.SEQUENCEFLOW.CONDITION.TYPE.TITLE" : "条件类型", - "PROPERTY.SEQUENCEFLOW.CONDITION.TYPE.VARIABLE" : "选择的变量", - "PROPERTY.SEQUENCEFLOW.CONDITION.TYPE.STATIC" : "静态值", - "PROPERTY.SEQUENCEFLOW.CONDITION.STATIC" : "条件表达式", - "PROPERTY.SEQUENCEFLOW.CONDITION.STATIC_PLACEHOLDER" : "输入表达式值", - "PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.TYPE" : "变量类型", - "PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.NO-CONDITION" : "没有条件", - "PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.FORM-FIELD" : "表单字段", - "PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.FORM-OUTCOME" : "表单输出", - "PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.SELECT-FIELD" : "选择的字段", - "PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.NO-FIELDS-AVAILABLE" : "没有字段变量", - "PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.SELECT-FORM" : "选择表单", - "PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.NO-FORMS-AVAILABLE" : "没有表单变量", - "PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.SELECT-OPERATOR" : "选择操作", - "PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.EQUALS" : "等于", - "PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.NOTEQUALS" : "不等于", - "PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.LESSTHAN" : "小于", - "PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.GREATERTHAN" : "大于", - "PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.SELECT-OUTCOME" : "选择输出", - "PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.NO-OUTCOMES-AVAILABLE" : "没有输出变量", - "PROPERTY.SEQUENCEFLOW.CONDITION.NO-CONDITION-DISPLAY" : "没有条件", - - "MODEL.SAVE.TITLE" : "确认保存模型", - "MODEL.NAME" : "名称", - "MODEL.DESCRIPTION" : "描述", - "MODEL.SAVE.NEWVERSION" : "保存为新版本? 这样你可以随时回到以前的版本", - "MODEL.SAVE.COMMENT" : "注释", - "MODEL.SAVE.SAVING" : "保存", - "MODEL.LASTMODIFIEDDATE" : "上次保存时间", - "MODEL.SAVE.ERROR": "未知错误:保存失败!", - - "EVENT_TYPE.ACTIVITY.COMPENSATE.TOOLTIP": "一个活动被另外一个活动替代执行", - "EVENT_TYPE.ACTIVITY.COMPLETED.TOOLTIP": "一个活动被成功的执行", - "EVENT_TYPE.ACTIVITY.ERROR.RECEIVED.TOOLTIP": "在收到活动错误之前,活动已收到错误事件", - "EVENT_TYPE.MEMBERSHIP.CREATED.TOOLTIP": "一个唯一的成员被创建", - "EVENT_TYPE.MEMBERSHIP.DELETED.TOOLTIP": "一个唯一的成员被删除", - "EVENT_TYPE.MEMBERSHIPS.DELETED.TOOLTIP": "所有成员都被删除.可能是由于没有事件被分配", - "EVENT_TYPE.TASK.ASSIGNED.TOOLTIP": "在ENTITY_UPDATED事件抛出时,任务已经被分配", - "EVENT_TYPE.TASK.COMPLETED.TOOLTIP": "在任务实体删除前任务已经被完成", - "EVENT_TYPE.UNCAUGHT.BPMNERROR.TOOLTIP": "一个BPMN被抛出,但没有捕获", - "EVENT_TYPE.VARIABLE.CREATED.TOOLTIP": "一个变量被创建", - "EVENT_TYPE.VARIABLE.DELETED.TOOLTIP": "一个变量被删除", - "EVENT_TYPE.VARIABLE.UPDATED.TOOLTIP": "一个变量被更新" -} \ No newline at end of file + "HEADER.BRAND": "Activiti编辑", + "HEADER.BRAND_TAGLINE": "powered by Alfresco", + "PAGE.HEADER": "Orchestration Details", + "ACTION.OK": "确认", + "ACTION.SAVE": "保存", + "ACTION.SAVE-AND-CLOSE": "确认保存", + "ACTION.SEND": "发送", + "ACTION.CANCEL": "取消", + "ACTION.SELECT": "选择", + "ACTION.ADD": "添加", + "ACTION.REMOVE": "清除", + "ACTION.MOVE.UP": "上移", + "ACTION.MOVE.DOWN": "下移", + "MAIN_NAVIGATION_ORCHESTRATIONS": "业务流程", + "MAIN_NAVIGATION_DISPATCH_RULES": "调度规则", + "MAIN_NAVIGATION_ASSET_GROUPS": "审批组", + "MAIN_NAVIGATION_SOLUTIONS": "解决", + "TOOLBAR.ACTION.CLOSE": "Close the editor and go back to the overview page", + "TOOLBAR.ACTION.SAVE": "保存", + "TOOLBAR.ACTION.VALIDATE": "校验", + "TOOLBAR.ACTION.CUT": "剪切", + "TOOLBAR.ACTION.COPY": "复制", + "TOOLBAR.ACTION.PASTE": "粘贴", + "TOOLBAR.ACTION.DELETE": "删除", + "TOOLBAR.ACTION.UNDO": "撤销", + "TOOLBAR.ACTION.REDO": "重复", + "TOOLBAR.ACTION.ZOOMIN": "放大", + "TOOLBAR.ACTION.ZOOMOUT": "缩小", + "TOOLBAR.ACTION.ZOOMACTUAL": "实际大小 ", + "TOOLBAR.ACTION.ZOOMFIT": "适应屏幕", + "TOOLBAR.ACTION.MOVE": "移动", + "TOOLBAR.ACTION.IMPORT": "导入", + "TOOLBAR.ACTION.EXPORT": "导出", + "TOOLBAR.ACTION.BENDPOINT.ADD": "为选定的流程连线添加弯曲点", + "TOOLBAR.ACTION.BENDPOINT.REMOVE": "为选定的流程连线删除弯曲点", + "TOOLBAR.ACTION.ALIGNHORIZONTAL": "水平对齐", + "TOOLBAR.ACTION.ALIGNVERTICAL": "垂直对齐", + "TOOLBAR.ACTION.SAMESIZE": "Same size", + "TOOLBAR.ACTION.HELP": "Start the guided tour", + "TOOLBAR.ACTION.FEEDBACK": "Provide feedback", + "KICKSTART.PROCESS_TOOLBAR.ACTION.SAVE": "保存", + "KICKSTART.PROCESS_TOOLBAR.ACTION.VALIDATE": "校验模型", + "KICKSTART.PROCESS_TOOLBAR.ACTION.HELP": "预览", + "KICKSTART.PROCESS_TOOLBAR.ACTION.FEEDBACK": "反馈", + "FORM_TOOLBAR.ACTION.SAVE": "保存", + "FORM_TOOLBAR.ACTION.VALIDATE": "校验模型", + "FORM_TOOLBAR.ACTION.HELP": "预览", + "FORM_TOOLBAR.ACTION.FEEDBACK": "反馈", + "APP_DEFINITION_TOOLBAR.ACTION.SAVE": "保存", + "APP_DEFINITION_TOOLBAR.ACTION.VALIDATE": "校验模型", + "APP_DEFINITION_TOOLBAR.ACTION.HELP": "预览", + "APP_DEFINITION_TOOLBAR.ACTION.FEEDBACK": "反馈", + "BUTTON.ACTION.DELETE.TOOLTIP": "从模型中删除元素", + "BUTTON.ACTION.MORPH.TOOLTIP": "更改元素类型", + "ELEMENT.AUTHOR": "作者", + "ELEMENT.DATE_CREATED": "创建日期", + "ELEMENT.SELECTED_EMPTY_TITLE": "(输入名称)", + "PROPERTY.REMOVED": "清除", + "PROPERTY.EMPTY": "", + "PROPERTY.PROPERTY.EDIT.TITLE": "修改 \"{{title}}\"", + "PROPERTY.FEEDBACK.TITLE": "请填写您的反馈意见", + "PROPERTY.ASSIGNMENT.TITLE": "指派", + "PROPERTY.ASSIGNMENT.TYPE": "类型", + "PROPERTY.ASSIGNMENT.TYPE.IDENTITYSTORE": "Identity store", + "PROPERTY.ASSIGNMENT.TYPE.STATIC": "静态值", + "PROPERTY.ASSIGNMENT.ASSIGNEE": "代理人", + "PROPERTY.ASSIGNMENT.MATCHING": "使用上下方向键选择并按回车键确认或使用鼠标", + "PROPERTY.ASSIGNMENT.ASSIGNEE_PLACEHOLDER": "请输入代理人", + "PROPERTY.ASSIGNMENT.EMPTY": "无代理人", + "PROPERTY.ASSIGNMENT.ASSIGNEE_DISPLAY": "代理人 {{assignee}}", + "PROPERTY.ASSIGNMENT.CANDIDATE_USERS_DISPLAY": "{{length}}候选人", + "PROPERTY.ASSIGNMENT.CANDIDATE_USERS": "候选人", + "PROPERTY.ASSIGNMENT.CANDIDATE_GROUPS_DISPLAY": "{{length}}候选组", + "PROPERTY.ASSIGNMENT.CANDIDATE_GROUPS": "候选组", + "PROPERTY.ASSIGNMENT.USER_IDM_DISPLAY": "用户{{firstName}} {{lastName}}", + "PROPERTY.ASSIGNMENT.USER_IDM_EMAIL_DISPLAY": "用户{{email}}", + "PROPERTY.ASSIGNMENT.IDM_EMPTY": "发起人", + "PROPERTY.ASSIGNMENT.IDM.TYPE": "任务", + "PROPERTY.ASSIGNMENT.IDM.NO_CANDIDATE_USERS": "没有选择候选人...", + "PROPERTY.ASSIGNMENT.IDM.NO_CANDIDATE_GROUPS": "没有选择候选组...", + "PROPERTY.ASSIGNMENT.IDM.DROPDOWN.INITIATOR": "分派给发起人", + "PROPERTY.ASSIGNMENT.IDM.DROPDOWN.USER": "分派给一个用户", + "PROPERTY.ASSIGNMENT.IDM.DROPDOWN.USERS": "候选人s", + "PROPERTY.ASSIGNMENT.IDM.DROPDOWN.GROUPS": "候选组", + "PROPERTY.ASSIGNMENT.EMAIL.HELP": "键入一个电子邮件地址,然后按回车键继续 ", + "PROPERTY.EXECUTIONLISTENERS.DISPLAY": "{{length}}执行监听", + "PROPERTY.EXECUTIONLISTENERS.EMPTY": "没有配置执行监听", + "PROPERTY.EXECUTIONLISTENERS.EVENT": "事件", + "PROPERTY.EXECUTIONLISTENERS.CLASS": "类", + "PROPERTY.EXECUTIONLISTENERS.CLASS.PLACEHOLDER": "输入类名", + "PROPERTY.EXECUTIONLISTENERS.EXPRESSION": "表达式", + "PROPERTY.EXECUTIONLISTENERS.EXPRESSION.PLACEHOLDER": "输入表达式", + "PROPERTY.EXECUTIONLISTENERS.DELEGATEEXPRESSION": "委托表达式", + "PROPERTY.EXECUTIONLISTENERS.DELEGATEEXPRESSION.PLACEHOLDER": "输入委托表达式", + "PROPERTY.EXECUTIONLISTENERS.UNSELECTED": "没有配置执行监听", + "PROPERTY.EXECUTIONLISTENERS.FIELDS.NAME": "名称", + "PROPERTY.EXECUTIONLISTENERS.FIELDS.NAME.PLACEHOLDER": "输入名称", + "PROPERTY.EXECUTIONLISTENERS.FIELDS.EXPRESSION": "表达式", + "PROPERTY.EXECUTIONLISTENERS.FIELDS.EXPRESSION.PLACEHOLDER": "输入表达式", + "PROPERTY.EXECUTIONLISTENERS.FIELDS.STRINGVALUE": "字符串", + "PROPERTY.EXECUTIONLISTENERS.FIELDS.STRINGVALUE.PLACEHOLDER": "输入字符串", + "PROPERTY.EXECUTIONLISTENERS.FIELDS.STRING": "字符串", + "PROPERTY.EXECUTIONLISTENERS.FIELDS.STRING.PLACEHOLDER": "输入字符串", + "PROPERTY.EXECUTIONLISTENERS.FIELDS.IMPLEMENTATION": "实现类", + "PROPERTY.EXECUTIONLISTENERS.FIELDS.EMPTY": "没有选择字段", + "PROPERTY.FIELDS": "{{length}}字段", + "PROPERTY.FIELDS.EMPTY": "没有选择字段", + "PROPERTY.FIELDS.NAME": "名称", + "PROPERTY.FIELDS.NAME.PLACEHOLDER": "输入名称", + "PROPERTY.FIELDS.EXPRESSION": "表达式", + "PROPERTY.FIELDS.EXPRESSION.PLACEHOLDER": "输入表达式", + "PROPERTY.FIELDS.STRINGVALUE": "字符串", + "PROPERTY.FIELDS.STRINGVALUE.PLACEHOLDER": "输入字符串", + "PROPERTY.FIELDS.STRING": "字符串", + "PROPERTY.FIELDS.STRING.PLACEHOLDER": "输入字符串", + "PROPERTY.FIELDS.IMPLEMENTATION": "实现类", + "PROPERTY.FIELDS.UNSELECTED": "没有选择字段", + "PROPERTY.FORMPROPERTIES.VALUE": "{{length}}表单属性", + "PROPERTY.FORMPROPERTIES.EMPTY": "没有配置表单", + "PROPERTY.FORMPROPERTIES.ID": "活动编号", + "PROPERTY.FORMPROPERTIES.ID.PLACEHOLDER": "输入活动编号", + "PROPERTY.FORMPROPERTIES.NAME": "名称", + "PROPERTY.FORMPROPERTIES.NAME.PLACEHOLDER": "输入名称", + "PROPERTY.FORMPROPERTIES.TYPE": "类型", + "PROPERTY.FORMPROPERTIES.DATEPATTERN": "时间选择框", + "PROPERTY.FORMPROPERTIES.DATEPATTERN.PLACEHOLDER": "输入日期", + "PROPERTY.FORMPROPERTIES.VALUES": "值", + "PROPERTY.FORMPROPERTIES.EXPRESSION": "表达式", + "PROPERTY.FORMPROPERTIES.EXPRESSION.PLACEHOLDER": "输入表达式", + "PROPERTY.FORMPROPERTIES.VARIABLE": "变量", + "PROPERTY.FORMPROPERTIES.VARIABLE.PLACEHOLDER": "输入变量", + "PROPERTY.FORMPROPERTIES.REQUIRED": "必输", + "PROPERTY.FORMPROPERTIES.READABLE": "可读", + "PROPERTY.FORMPROPERTIES.WRITABLE": "可写", + "PROPERTY.INPARAMETERS.VALUE": "{{length}}输入参数", + "PROPERTY.INPARAMETERS.EMPTY": "没有配置输入参数", + "PROPERTY.OUTPARAMETERS.VALUE": "{{length}}返回参数", + "PROPERTY.OUTPARAMETERS.EMPTY": "没有配置返回参数", + "PROPERTY.PARAMETER.SOURCE": "源", + "PROPERTY.PARAMETER.SOURCE.PLACEHOLDER": "输入源", + "PROPERTY.PARAMETER.SOURCEEXPRESSION": "源表达式", + "PROPERTY.PARAMETER.SOURCEEXPRESSION.PLACEHOLDER": "输入源表达式", + "PROPERTY.PARAMETER.TARGET": "目标", + "PROPERTY.PARAMETER.TARGET.PLACEHOLDER": "输入目标", + "PROPERTY.PARAMETER.EMPTY": "没有选择参数", + "PROPERTY.SUBPROCESSREFERENCE.EMPTY": "没有引用子流程", + "PROPERTY.SUBPROCESSREFERENCE.TITLE": "引用错误的子流程", + "PROPERTY.SUBPROCESSREFERENCE.ERROR.SUBPROCESS": "子流程加载错误.请稍后再试", + "PROPERTY.SUBPROCESSREFERENCE.FOLDER.ROOT": "文件夹", + "PROPERTY.SUBPROCESSREFERENCE.FOLDER.LOADING": "文件夹加载中...", + "PROPERTY.SUBPROCESSREFERENCE.FOLDER.EMPTY": "文件夹未包含子文件夹", + "PROPERTY.SUBPROCESSREFERENCE.SUBPROCESS.LOADING": "子流程加载中...", + "PROPERTY.SUBPROCESSREFERENCE.SUBPROCESS.EMPTY": "文件夹包含子文件夹", + "PROPERTY.FORMREFERENCE.EMPTY": "没有引用表单", + "PROPERTY.FORMREFERENCE.TITLE": "表单引用", + "PROPERTY.FORMREFERENCE.ERROR.FORM": "表单加载错误.请稍后再试!", + "PROPERTY.FORMREFERENCE.FOLDER.ROOT": "文件夹", + "PROPERTY.FORMREFERENCE.FOLDER.LOADING": "文件夹加载中...", + "PROPERTY.FORMREFERENCE.FOLDER.EMPTY": "文件夹未包含子文件夹", + "PROPERTY.FORMREFERENCE.FORM.LOADING": "表单加载中...", + "PROPERTY.FORMREFERENCE.FORM.EMPTY": "文件夹包含子文件夹", + "PROPERTY.TASKLISTENERS.VALUE": "{{length}}任务监听", + "PROPERTY.TASKLISTENERS.EMPTY": "未配置任务监听", + "PROPERTY.TASKLISTENERS.EVENT": "事件", + "PROPERTY.TASKLISTENERS.CLASS": "类", + "PROPERTY.TASKLISTENERS.CLASS.PLACEHOLDER": "输入类名", + "PROPERTY.TASKLISTENERS.EXPRESSION": "表达式", + "PROPERTY.TASKLISTENERS.EXPRESSION.PLACEHOLDER": "请输入表达式", + "PROPERTY.TASKLISTENERS.DELEGATEEXPRESSION": "委托表达式", + "PROPERTY.TASKLISTENERS.DELEGATEEXPRESSION.PLACEHOLDER": "请输入委托表达式", + "PROPERTY.TASKLISTENERS.UNSELECTED": "没有选择任务监听", + "PROPERTY.TASKLISTENERS.FIELDS.NAME": "名称", + "PROPERTY.TASKLISTENERS.FIELDS.NAME.PLACEHOLDER": "请输入名称", + "PROPERTY.TASKLISTENERS.FIELDS.EXPRESSION": "表达式", + "PROPERTY.TASKLISTENERS.FIELDS.EXPRESSION.PLACEHOLDER": "请输入表达式", + "PROPERTY.TASKLISTENERS.FIELDS.STRINGVALUE": "字符串", + "PROPERTY.TASKLISTENERS.FIELDS.STRINGVALUE.PLACEHOLDER": "请输入字符串", + "PROPERTY.TASKLISTENERS.FIELDS.STRING": "字符串", + "PROPERTY.TASKLISTENERS.FIELDS.STRING.PLACEHOLDER": "请输入字符串", + "PROPERTY.TASKLISTENERS.FIELDS.IMPLEMENTATION": "执行", + "PROPERTY.TASKLISTENERS.FIELDS.EMPTY": "未选择字段", + "PROPERTY.EVENTLISTENERS.DISPLAY": "{{length}}事件监听", + "PROPERTY.EVENTLISTENERS.EMPTY": "未配置事件监听", + "PROPERTY.EVENTLISTENERS.EVENTS": "事件", + "PROPERTY.EVENTLISTENERS.RETHROW": "抛出事件?", + "PROPERTY.EVENTLISTENERS.CLASS": "类", + "PROPERTY.EVENTLISTENERS.CLASS.PLACEHOLDER": "输入类名", + "PROPERTY.EVENTLISTENERS.DELEGATEEXPRESSION": "委托表达式", + "PROPERTY.EVENTLISTENERS.DELEGATEEXPRESSION.PLACEHOLDER": "请输入委托表达式", + "PROPERTY.EVENTLISTENERS.ENTITYTYPE": "类型", + "PROPERTY.EVENTLISTENERS.ENTITYTYPE.PLACEHOLDER": "请输入类型", + "PROPERTY.EVENTLISTENERS.RETHROWTYPE": "抛出事件类型", + "PROPERTY.EVENTLISTENERS.ERRORCODE": "错误代码", + "PROPERTY.EVENTLISTENERS.ERRORCODE.PLACEHOLDER": "请输入错误代码", + "PROPERTY.EVENTLISTENERS.MESSAGENAME": "消息名称", + "PROPERTY.EVENTLISTENERS.MESSAGENAME.PLACEHOLDER": "请输入消息名称", + "PROPERTY.EVENTLISTENERS.SIGNALNAME": "信号名称", + "PROPERTY.EVENTLISTENERS.SIGNALNAME.PLACEHOLDER": "请输入信号名称", + "PROPERTY.EVENTLISTENERS.UNSELECTED": "没有选择事件监听", + "PROPERTY.SIGNALDEFINITIONS.DISPLAY": "{{length}}信号定义", + "PROPERTY.SIGNALDEFINITIONS.EMPTY": "没有配置信号定义", + "PROPERTY.SIGNALDEFINITIONS.SCOPE-GLOBAL": "全局", + "PROPERTY.SIGNALDEFINITIONS.SCOPE-PROCESSINSTANCE": "流程初始化", + "PROPERTY.SIGNALDEFINITIONS.ID": "编号", + "PROPERTY.SIGNALDEFINITIONS.NAME": "名称", + "PROPERTY.SIGNALDEFINITIONS.SCOPE": "Scope", + "PROPERTY.MESSAGEDEFINITIONS.DISPLAY": "{{length}}消息定义", + "PROPERTY.MESSAGEDEFINITIONS.EMPTY": "没有配置消息定义", + "PROPERTY.MESSAGEDEFINITIONS.ID": "编号", + "PROPERTY.MESSAGEDEFINITIONS.NAME": "名称", + "PROPERTY.SEQUENCEFLOW.ORDER.EMPTY": "没有确定顺序流排序", + "PROPERTY.SEQUENCEFLOW.ORDER.NOT.EMPTY": "顺序流排序", + "PROPERTY.SEQUENCEFLOW.ORDER.NO.OUTGOING.SEQUENCEFLOW.FOUND": "没有输出顺序流.", + "PROPERTY.SEQUENCEFLOW.ORDER.DESCRIPTION": "不能设置已经被使用的编号:", + "PROPERTY.SEQUENCEFLOW.ORDER.SEQUENCEFLOW.VALUE": "顺序流{{targetType}} {{targetTitle}}", + "PROPERTY.SEQUENCEFLOW.CONDITION.TITLE": "条件", + "PROPERTY.SEQUENCEFLOW.CONDITION.TYPE.TITLE": "条件类型", + "PROPERTY.SEQUENCEFLOW.CONDITION.TYPE.VARIABLE": "选择的变量", + "PROPERTY.SEQUENCEFLOW.CONDITION.TYPE.STATIC": "静态值", + "PROPERTY.SEQUENCEFLOW.CONDITION.STATIC": "条件表达式", + "PROPERTY.SEQUENCEFLOW.CONDITION.STATIC_PLACEHOLDER": "输入表达式值", + "PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.TYPE": "变量类型", + "PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.NO-CONDITION": "没有条件", + "PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.FORM-FIELD": "表单字段", + "PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.FORM-OUTCOME": "表单输出", + "PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.SELECT-FIELD": "选择的字段", + "PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.NO-FIELDS-AVAILABLE": "没有字段变量", + "PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.SELECT-FORM": "选择表单", + "PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.NO-FORMS-AVAILABLE": "没有表单变量", + "PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.SELECT-OPERATOR": "选择操作", + "PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.EQUALS": "等于", + "PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.NOTEQUALS": "不等于", + "PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.LESSTHAN": "小于", + "PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.GREATERTHAN": "大于", + "PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.SELECT-OUTCOME": "选择输出", + "PROPERTY.SEQUENCEFLOW.CONDITION.VARIABLE.NO-OUTCOMES-AVAILABLE": "没有输出变量", + "PROPERTY.SEQUENCEFLOW.CONDITION.NO-CONDITION-DISPLAY": "没有条件", + "MODEL.SAVE.TITLE": "确认保存模型", + "MODEL.NAME": "名称", + "MODEL.DESCRIPTION": "描述", + "MODEL.SAVE.NEWVERSION": "保存为新版本? 这样你可以随时回到以前的版本", + "MODEL.SAVE.COMMENT": "注释", + "MODEL.SAVE.SAVING": "保存", + "MODEL.LASTMODIFIEDDATE": "上次保存时间", + "MODEL.SAVE.ERROR": "未知错误:保存失败!", + "EVENT_TYPE.ACTIVITY.COMPENSATE.TOOLTIP": "一个活动被另外一个活动替代执行", + "EVENT_TYPE.ACTIVITY.COMPLETED.TOOLTIP": "一个活动被成功的执行", + "EVENT_TYPE.ACTIVITY.ERROR.RECEIVED.TOOLTIP": "在收到活动错误之前,活动已收到错误事件", + "EVENT_TYPE.MEMBERSHIP.CREATED.TOOLTIP": "一个唯一的成员被创建", + "EVENT_TYPE.MEMBERSHIP.DELETED.TOOLTIP": "一个唯一的成员被删除", + "EVENT_TYPE.MEMBERSHIPS.DELETED.TOOLTIP": "所有成员都被删除.可能是由于没有事件被分配", + "EVENT_TYPE.TASK.ASSIGNED.TOOLTIP": "在ENTITY_UPDATED事件抛出时,任务已经被分配", + "EVENT_TYPE.TASK.COMPLETED.TOOLTIP": "在任务实体删除前任务已经被完成", + "EVENT_TYPE.UNCAUGHT.BPMNERROR.TOOLTIP": "一个BPMN被抛出,但没有捕获", + "EVENT_TYPE.VARIABLE.CREATED.TOOLTIP": "一个变量被创建", + "EVENT_TYPE.VARIABLE.DELETED.TOOLTIP": "一个变量被删除", + "EVENT_TYPE.VARIABLE.UPDATED.TOOLTIP": "一个变量被更新" +} diff --git a/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-cookies_1.2.13/angular-cookies.min.js.map b/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-cookies_1.2.13/angular-cookies.min.js.map index 16299489175e5819b4cfaefccc08ce19b74d3cc7..42cecf4fc4f13037f179d2c3b0e7aa55548d082f 100644 --- a/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-cookies_1.2.13/angular-cookies.min.js.map +++ b/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-cookies_1.2.13/angular-cookies.min.js.map @@ -1,8 +1,42 @@ { -"version":3, -"file":"angular-cookies.min.js", -"lineCount":7, -"mappings":"A;;;;;aAKC,SAAQ,CAACA,CAAD,CAASC,CAAT,CAAkBC,CAAlB,CAA6B,CAoBtCD,CAAAE,OAAA,CAAe,WAAf,CAA4B,CAAC,IAAD,CAA5B,CAAAC,QAAA,CA4BW,UA5BX,CA4BuB,CAAC,YAAD,CAAe,UAAf,CAA2B,QAAS,CAACC,CAAD,CAAaC,CAAb,CAAuB,CAAA,IACxEC,EAAU,EAD8D,CAExEC,EAAc,EAF0D,CAGxEC,CAHwE,CAIxEC,EAAU,CAAA,CAJ8D,CAKxEC,EAAOV,CAAAU,KALiE,CAMxEC,EAAcX,CAAAW,YAGlBN,EAAAO,UAAA,CAAmB,QAAQ,EAAG,CAC5B,IAAIC,EAAiBR,CAAAC,QAAA,EACjBE,EAAJ,EAA0BK,CAA1B,GACEL,CAGA,CAHqBK,CAGrB,CAFAH,CAAA,CAAKG,CAAL,CAAqBN,CAArB,CAEA,CADAG,CAAA,CAAKG,CAAL,CAAqBP,CAArB,CACA,CAAIG,CAAJ,EAAaL,CAAAU,OAAA,EAJf,CAF4B,CAA9B,CAAA,EAUAL,EAAA,CAAU,CAAA,CAKVL,EAAAW,OAAA,CASAC,QAAa,EAAG,CAAA,IACVC,CADU,CAEVC,CAFU,CAIVC,CAGJ,KAAKF,CAAL,GAAaV,EAAb,CACMI,CAAA,CAAYL,CAAA,CAAQW,CAAR,CAAZ,CAAJ,EACEZ,CAAAC,QAAA,CAAiBW,CAAjB,CAAuBhB,CAAvB,CAKJ,KAAIgB,CAAJ,GAAYX,EAAZ,CAEE,CADAY,CACK,CADGZ,CAAA,CAAQW,CAAR,CACH,CAAAjB,CAAAoB,SAAA,CAAiBF,CAAjB,CAAL,EAMWA,CANX,GAMqBX,CAAA,CAAYU,CAAZ,CANrB,GAOEZ,CAAAC,QAAA,CAAiBW,CAAjB,CAAuBC,CAAvB,CACA,CAAAC,CAAA,CAAU,CAAA,CARZ,EACMnB,CAAAqB,UAAA,CAAkBd,CAAA,CAAYU,CAAZ,CAAlB,CAAJ,CACEX,CAAA,CAAQW,CAAR,CADF,CACkBV,CAAA,CAAYU,CAAZ,CADlB,CAGE,OAAOX,CAAA,CAAQW,CAAR,CASb,IAAIE,CAAJ,CAIE,IAAKF,CAAL,GAFAK,EAEahB,CAFID,CAAAC,QAAA,EAEJA,CAAAA,CAAb,CACMA,CAAA,CAAQW,CAAR,CAAJ,GAAsBK,CAAA,CAAeL,CAAf,CAAtB,GAEMN,CAAA,CAAYW,CAAA,CAAeL,CAAf,CAAZ,CAAJ,CACE,OAAOX,CAAA,CAAQW,CAAR,CADT,CAGEX,CAAA,CAAQW,CAAR,CAHF,CAGkBK,CAAA,CAAeL,CAAf,CALpB,CAlCU,CAThB,CAEA;MAAOX,EA1BqE,CAA3D,CA5BvB,CAAAH,QAAA,CA4HW,cA5HX,CA4H2B,CAAC,UAAD,CAAa,QAAQ,CAACoB,CAAD,CAAW,CAErD,MAAO,KAYAC,QAAQ,CAACC,CAAD,CAAM,CAEjB,MAAO,CADHP,CACG,CADKK,CAAA,CAASE,CAAT,CACL,EAAQzB,CAAA0B,SAAA,CAAiBR,CAAjB,CAAR,CAAkCA,CAFxB,CAZd,KA4BAS,QAAQ,CAACF,CAAD,CAAMP,CAAN,CAAa,CACxBK,CAAA,CAASE,CAAT,CAAA,CAAgBzB,CAAA4B,OAAA,CAAeV,CAAf,CADQ,CA5BrB,QA0CGW,QAAQ,CAACJ,CAAD,CAAM,CACpB,OAAOF,CAAA,CAASE,CAAT,CADa,CA1CjB,CAF8C,CAAhC,CA5H3B,CApBsC,CAArC,CAAA,CAoME1B,MApMF,CAoMUA,MAAAC,QApMV;", -"sources":["angular-cookies.js"], -"names":["window","angular","undefined","module","factory","$rootScope","$browser","cookies","lastCookies","lastBrowserCookies","runEval","copy","isUndefined","addPollFn","currentCookies","$apply","$watch","push","name","value","updated","isString","isDefined","browserCookies","$cookies","get","key","fromJson","put","toJson","remove"] -} \ No newline at end of file + "version": 3, + "file": "angular-cookies.min.js", + "lineCount": 7, + "mappings": "A;;;;;aAKC,SAAQ,CAACA,CAAD,CAASC,CAAT,CAAkBC,CAAlB,CAA6B,CAoBtCD,CAAAE,OAAA,CAAe,WAAf,CAA4B,CAAC,IAAD,CAA5B,CAAAC,QAAA,CA4BW,UA5BX,CA4BuB,CAAC,YAAD,CAAe,UAAf,CAA2B,QAAS,CAACC,CAAD,CAAaC,CAAb,CAAuB,CAAA,IACxEC,EAAU,EAD8D,CAExEC,EAAc,EAF0D,CAGxEC,CAHwE,CAIxEC,EAAU,CAAA,CAJ8D,CAKxEC,EAAOV,CAAAU,KALiE,CAMxEC,EAAcX,CAAAW,YAGlBN,EAAAO,UAAA,CAAmB,QAAQ,EAAG,CAC5B,IAAIC,EAAiBR,CAAAC,QAAA,EACjBE,EAAJ,EAA0BK,CAA1B,GACEL,CAGA,CAHqBK,CAGrB,CAFAH,CAAA,CAAKG,CAAL,CAAqBN,CAArB,CAEA,CADAG,CAAA,CAAKG,CAAL,CAAqBP,CAArB,CACA,CAAIG,CAAJ,EAAaL,CAAAU,OAAA,EAJf,CAF4B,CAA9B,CAAA,EAUAL,EAAA,CAAU,CAAA,CAKVL,EAAAW,OAAA,CASAC,QAAa,EAAG,CAAA,IACVC,CADU,CAEVC,CAFU,CAIVC,CAGJ,KAAKF,CAAL,GAAaV,EAAb,CACMI,CAAA,CAAYL,CAAA,CAAQW,CAAR,CAAZ,CAAJ,EACEZ,CAAAC,QAAA,CAAiBW,CAAjB,CAAuBhB,CAAvB,CAKJ,KAAIgB,CAAJ,GAAYX,EAAZ,CAEE,CADAY,CACK,CADGZ,CAAA,CAAQW,CAAR,CACH,CAAAjB,CAAAoB,SAAA,CAAiBF,CAAjB,CAAL,EAMWA,CANX,GAMqBX,CAAA,CAAYU,CAAZ,CANrB,GAOEZ,CAAAC,QAAA,CAAiBW,CAAjB,CAAuBC,CAAvB,CACA,CAAAC,CAAA,CAAU,CAAA,CARZ,EACMnB,CAAAqB,UAAA,CAAkBd,CAAA,CAAYU,CAAZ,CAAlB,CAAJ,CACEX,CAAA,CAAQW,CAAR,CADF,CACkBV,CAAA,CAAYU,CAAZ,CADlB,CAGE,OAAOX,CAAA,CAAQW,CAAR,CASb,IAAIE,CAAJ,CAIE,IAAKF,CAAL,GAFAK,EAEahB,CAFID,CAAAC,QAAA,EAEJA,CAAAA,CAAb,CACMA,CAAA,CAAQW,CAAR,CAAJ,GAAsBK,CAAA,CAAeL,CAAf,CAAtB,GAEMN,CAAA,CAAYW,CAAA,CAAeL,CAAf,CAAZ,CAAJ,CACE,OAAOX,CAAA,CAAQW,CAAR,CADT,CAGEX,CAAA,CAAQW,CAAR,CAHF,CAGkBK,CAAA,CAAeL,CAAf,CALpB,CAlCU,CAThB,CAEA;MAAOX,EA1BqE,CAA3D,CA5BvB,CAAAH,QAAA,CA4HW,cA5HX,CA4H2B,CAAC,UAAD,CAAa,QAAQ,CAACoB,CAAD,CAAW,CAErD,MAAO,KAYAC,QAAQ,CAACC,CAAD,CAAM,CAEjB,MAAO,CADHP,CACG,CADKK,CAAA,CAASE,CAAT,CACL,EAAQzB,CAAA0B,SAAA,CAAiBR,CAAjB,CAAR,CAAkCA,CAFxB,CAZd,KA4BAS,QAAQ,CAACF,CAAD,CAAMP,CAAN,CAAa,CACxBK,CAAA,CAASE,CAAT,CAAA,CAAgBzB,CAAA4B,OAAA,CAAeV,CAAf,CADQ,CA5BrB,QA0CGW,QAAQ,CAACJ,CAAD,CAAM,CACpB,OAAOF,CAAA,CAASE,CAAT,CADa,CA1CjB,CAF8C,CAAhC,CA5H3B,CApBsC,CAArC,CAAA,CAoME1B,MApMF,CAoMUA,MAAAC,QApMV;", + "sources": [ + "angular-cookies.js" + ], + "names": [ + "window", + "angular", + "undefined", + "module", + "factory", + "$rootScope", + "$browser", + "cookies", + "lastCookies", + "lastBrowserCookies", + "runEval", + "copy", + "isUndefined", + "addPollFn", + "currentCookies", + "$apply", + "$watch", + "push", + "name", + "value", + "updated", + "isString", + "isDefined", + "browserCookies", + "$cookies", + "get", + "key", + "fromJson", + "put", + "toJson", + "remove" + ] +} diff --git a/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-mocks_1.2.13/angular-mocks.js b/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-mocks_1.2.13/angular-mocks.js index d3938aff09df5da9ba27392a01c32c00302e8c62..1710c6c052888d851d3ae44b958a832557138ad9 100644 --- a/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-mocks_1.2.13/angular-mocks.js +++ b/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-mocks_1.2.13/angular-mocks.js @@ -3,986 +3,1000 @@ * (c) 2010-2014 Google, Inc. http://angularjs.org * License: MIT */ -(function(window, angular, undefined) { +(function (window, angular, undefined) { -'use strict'; + 'use strict'; -/** - * @ngdoc overview - * @name angular.mock - * @description - * - * Namespace from 'angular-mocks.js' which contains testing related code. - */ -angular.mock = {}; - -/** - * ! This is a private undocumented service ! - * - * @name ngMock.$browser - * - * @description - * This service is a mock implementation of {@link ng.$browser}. It provides fake - * implementation for commonly used browser apis that are hard to test, e.g. setTimeout, xhr, - * cookies, etc... - * - * The api of this service is the same as that of the real {@link ng.$browser $browser}, except - * that there are several helper methods available which can be used in tests. - */ -angular.mock.$BrowserProvider = function() { - this.$get = function() { - return new angular.mock.$Browser(); - }; -}; - -angular.mock.$Browser = function() { - var self = this; + /** + * @ngdoc overview + * @name angular.mock + * @description + * + * Namespace from 'angular-mocks.js' which contains testing related code. + */ + angular.mock = {}; - this.isMock = true; - self.$$url = "http://server/"; - self.$$lastUrl = self.$$url; // used by url polling fn - self.pollFns = []; + /** + * ! This is a private undocumented service ! + * + * @name ngMock.$browser + * + * @description + * This service is a mock implementation of {@link ng.$browser}. It provides fake + * implementation for commonly used browser apis that are hard to test, e.g. setTimeout, xhr, + * cookies, etc... + * + * The api of this service is the same as that of the real {@link ng.$browser $browser}, except + * that there are several helper methods available which can be used in tests. + */ + angular.mock.$BrowserProvider = function () { + this.$get = function () { + return new angular.mock.$Browser(); + }; + }; - // TODO(vojta): remove this temporary api - self.$$completeOutstandingRequest = angular.noop; - self.$$incOutstandingRequestCount = angular.noop; + angular.mock.$Browser = function () { + var self = this; + this.isMock = true; + self.$$url = "http://server/"; + self.$$lastUrl = self.$$url; // used by url polling fn + self.pollFns = []; - // register url polling fn + // TODO(vojta): remove this temporary api + self.$$completeOutstandingRequest = angular.noop; + self.$$incOutstandingRequestCount = angular.noop; - self.onUrlChange = function(listener) { - self.pollFns.push( - function() { - if (self.$$lastUrl != self.$$url) { - self.$$lastUrl = self.$$url; - listener(self.$$url); - } - } - ); - return listener; - }; + // register url polling fn - self.cookieHash = {}; - self.lastCookieHash = {}; - self.deferredFns = []; - self.deferredNextId = 0; + self.onUrlChange = function (listener) { + self.pollFns.push( + function () { + if (self.$$lastUrl != self.$$url) { + self.$$lastUrl = self.$$url; + listener(self.$$url); + } + } + ); - self.defer = function(fn, delay) { - delay = delay || 0; - self.deferredFns.push({time:(self.defer.now + delay), fn:fn, id: self.deferredNextId}); - self.deferredFns.sort(function(a,b){ return a.time - b.time;}); - return self.deferredNextId++; - }; + return listener; + }; + self.cookieHash = {}; + self.lastCookieHash = {}; + self.deferredFns = []; + self.deferredNextId = 0; - /** - * @name ngMock.$browser#defer.now - * @propertyOf ngMock.$browser - * - * @description - * Current milliseconds mock time. - */ - self.defer.now = 0; + self.defer = function (fn, delay) { + delay = delay || 0; + self.deferredFns.push({time: (self.defer.now + delay), fn: fn, id: self.deferredNextId}); + self.deferredFns.sort(function (a, b) { + return a.time - b.time; + }); + return self.deferredNextId++; + }; - self.defer.cancel = function(deferId) { - var fnIndex; + /** + * @name ngMock.$browser#defer.now + * @propertyOf ngMock.$browser + * + * @description + * Current milliseconds mock time. + */ + self.defer.now = 0; - angular.forEach(self.deferredFns, function(fn, index) { - if (fn.id === deferId) fnIndex = index; - }); - if (fnIndex !== undefined) { - self.deferredFns.splice(fnIndex, 1); - return true; - } + self.defer.cancel = function (deferId) { + var fnIndex; - return false; - }; - - - /** - * @name ngMock.$browser#defer.flush - * @methodOf ngMock.$browser - * - * @description - * Flushes all pending requests and executes the defer callbacks. - * - * @param {number=} number of milliseconds to flush. See {@link #defer.now} - */ - self.defer.flush = function(delay) { - if (angular.isDefined(delay)) { - self.defer.now += delay; - } else { - if (self.deferredFns.length) { - self.defer.now = self.deferredFns[self.deferredFns.length-1].time; - } else { - throw new Error('No deferred tasks to be flushed'); - } - } + angular.forEach(self.deferredFns, function (fn, index) { + if (fn.id === deferId) fnIndex = index; + }); - while (self.deferredFns.length && self.deferredFns[0].time <= self.defer.now) { - self.deferredFns.shift().fn(); - } - }; + if (fnIndex !== undefined) { + self.deferredFns.splice(fnIndex, 1); + return true; + } - self.$$baseHref = ''; - self.baseHref = function() { - return this.$$baseHref; - }; -}; -angular.mock.$Browser.prototype = { + return false; + }; -/** - * @name ngMock.$browser#poll - * @methodOf ngMock.$browser - * - * @description - * run all fns in pollFns - */ - poll: function poll() { - angular.forEach(this.pollFns, function(pollFn){ - pollFn(); - }); - }, - addPollFn: function(pollFn) { - this.pollFns.push(pollFn); - return pollFn; - }, + /** + * @name ngMock.$browser#defer.flush + * @methodOf ngMock.$browser + * + * @description + * Flushes all pending requests and executes the defer callbacks. + * + * @param {number=} number of milliseconds to flush. See {@link #defer.now} + */ + self.defer.flush = function (delay) { + if (angular.isDefined(delay)) { + self.defer.now += delay; + } else { + if (self.deferredFns.length) { + self.defer.now = self.deferredFns[self.deferredFns.length - 1].time; + } else { + throw new Error('No deferred tasks to be flushed'); + } + } + + while (self.deferredFns.length && self.deferredFns[0].time <= self.defer.now) { + self.deferredFns.shift().fn(); + } + }; - url: function(url, replace) { - if (url) { - this.$$url = url; - return this; - } + self.$$baseHref = ''; + self.baseHref = function () { + return this.$$baseHref; + }; + }; + angular.mock.$Browser.prototype = { - return this.$$url; - }, - - cookies: function(name, value) { - if (name) { - if (angular.isUndefined(value)) { - delete this.cookieHash[name]; - } else { - if (angular.isString(value) && //strings only - value.length <= 4096) { //strict cookie storage limits - this.cookieHash[name] = value; + /** + * @name ngMock.$browser#poll + * @methodOf ngMock.$browser + * + * @description + * run all fns in pollFns + */ + poll: function poll() { + angular.forEach(this.pollFns, function (pollFn) { + pollFn(); + }); + }, + + addPollFn: function (pollFn) { + this.pollFns.push(pollFn); + return pollFn; + }, + + url: function (url, replace) { + if (url) { + this.$$url = url; + return this; + } + + return this.$$url; + }, + + cookies: function (name, value) { + if (name) { + if (angular.isUndefined(value)) { + delete this.cookieHash[name]; + } else { + if (angular.isString(value) && //strings only + value.length <= 4096) { //strict cookie storage limits + this.cookieHash[name] = value; + } + } + } else { + if (!angular.equals(this.cookieHash, this.lastCookieHash)) { + this.lastCookieHash = angular.copy(this.cookieHash); + this.cookieHash = angular.copy(this.cookieHash); + } + return this.cookieHash; + } + }, + + notifyWhenNoOutstandingRequests: function (fn) { + fn(); } - } - } else { - if (!angular.equals(this.cookieHash, this.lastCookieHash)) { - this.lastCookieHash = angular.copy(this.cookieHash); - this.cookieHash = angular.copy(this.cookieHash); - } - return this.cookieHash; - } - }, + }; - notifyWhenNoOutstandingRequests: function(fn) { - fn(); - } -}; + /** + * @ngdoc object + * @name ngMock.$exceptionHandlerProvider + * + * @description + * Configures the mock implementation of {@link ng.$exceptionHandler} to rethrow or to log errors + * passed into the `$exceptionHandler`. + */ -/** - * @ngdoc object - * @name ngMock.$exceptionHandlerProvider - * - * @description - * Configures the mock implementation of {@link ng.$exceptionHandler} to rethrow or to log errors - * passed into the `$exceptionHandler`. - */ + /** + * @ngdoc object + * @name ngMock.$exceptionHandler + * + * @description + * Mock implementation of {@link ng.$exceptionHandler} that rethrows or logs errors passed + * into it. See {@link ngMock.$exceptionHandlerProvider $exceptionHandlerProvider} for configuration + * information. + * + * + *
+     *   describe('$exceptionHandlerProvider', function() {
+     *
+     *     it('should capture log messages and exceptions', function() {
+     *
+     *       module(function($exceptionHandlerProvider) {
+     *         $exceptionHandlerProvider.mode('log');
+     *       });
+     *
+     *       inject(function($log, $exceptionHandler, $timeout) {
+     *         $timeout(function() { $log.log(1); });
+     *         $timeout(function() { $log.log(2); throw 'banana peel'; });
+     *         $timeout(function() { $log.log(3); });
+     *         expect($exceptionHandler.errors).toEqual([]);
+     *         expect($log.assertEmpty());
+     *         $timeout.flush();
+     *         expect($exceptionHandler.errors).toEqual(['banana peel']);
+     *         expect($log.log.logs).toEqual([[1], [2], [3]]);
+     *       });
+     *     });
+     *   });
+     * 
+ */ -/** - * @ngdoc object - * @name ngMock.$exceptionHandler - * - * @description - * Mock implementation of {@link ng.$exceptionHandler} that rethrows or logs errors passed - * into it. See {@link ngMock.$exceptionHandlerProvider $exceptionHandlerProvider} for configuration - * information. - * - * - *
- *   describe('$exceptionHandlerProvider', function() {
- *
- *     it('should capture log messages and exceptions', function() {
- *
- *       module(function($exceptionHandlerProvider) {
- *         $exceptionHandlerProvider.mode('log');
- *       });
- *
- *       inject(function($log, $exceptionHandler, $timeout) {
- *         $timeout(function() { $log.log(1); });
- *         $timeout(function() { $log.log(2); throw 'banana peel'; });
- *         $timeout(function() { $log.log(3); });
- *         expect($exceptionHandler.errors).toEqual([]);
- *         expect($log.assertEmpty());
- *         $timeout.flush();
- *         expect($exceptionHandler.errors).toEqual(['banana peel']);
- *         expect($log.log.logs).toEqual([[1], [2], [3]]);
- *       });
- *     });
- *   });
- * 
- */ + angular.mock.$ExceptionHandlerProvider = function () { + var handler; -angular.mock.$ExceptionHandlerProvider = function() { - var handler; - - /** - * @ngdoc method - * @name ngMock.$exceptionHandlerProvider#mode - * @methodOf ngMock.$exceptionHandlerProvider - * - * @description - * Sets the logging mode. - * - * @param {string} mode Mode of operation, defaults to `rethrow`. - * - * - `rethrow`: If any errors are passed into the handler in tests, it typically - * means that there is a bug in the application or test, so this mock will - * make these tests fail. - * - `log`: Sometimes it is desirable to test that an error is thrown, for this case the `log` - * mode stores an array of errors in `$exceptionHandler.errors`, to allow later - * assertion of them. See {@link ngMock.$log#assertEmpty assertEmpty()} and - * {@link ngMock.$log#reset reset()} - */ - this.mode = function(mode) { - switch(mode) { - case 'rethrow': - handler = function(e) { - throw e; - }; - break; - case 'log': - var errors = []; - - handler = function(e) { - if (arguments.length == 1) { - errors.push(e); - } else { - errors.push([].slice.call(arguments, 0)); - } + /** + * @ngdoc method + * @name ngMock.$exceptionHandlerProvider#mode + * @methodOf ngMock.$exceptionHandlerProvider + * + * @description + * Sets the logging mode. + * + * @param {string} mode Mode of operation, defaults to `rethrow`. + * + * - `rethrow`: If any errors are passed into the handler in tests, it typically + * means that there is a bug in the application or test, so this mock will + * make these tests fail. + * - `log`: Sometimes it is desirable to test that an error is thrown, for this case the `log` + * mode stores an array of errors in `$exceptionHandler.errors`, to allow later + * assertion of them. See {@link ngMock.$log#assertEmpty assertEmpty()} and + * {@link ngMock.$log#reset reset()} + */ + this.mode = function (mode) { + switch (mode) { + case 'rethrow': + handler = function (e) { + throw e; + }; + break; + case 'log': + var errors = []; + + handler = function (e) { + if (arguments.length == 1) { + errors.push(e); + } else { + errors.push([].slice.call(arguments, 0)); + } + }; + + handler.errors = errors; + break; + default: + throw new Error("Unknown mode '" + mode + "', only 'log'/'rethrow' modes are allowed!"); + } }; - handler.errors = errors; - break; - default: - throw new Error("Unknown mode '" + mode + "', only 'log'/'rethrow' modes are allowed!"); - } - }; - - this.$get = function() { - return handler; - }; - - this.mode('rethrow'); -}; - - -/** - * @ngdoc service - * @name ngMock.$log - * - * @description - * Mock implementation of {@link ng.$log} that gathers all logged messages in arrays - * (one array per logging level). These arrays are exposed as `logs` property of each of the - * level-specific log function, e.g. for level `error` the array is exposed as `$log.error.logs`. - * - */ -angular.mock.$LogProvider = function() { - var debug = true; - - function concat(array1, array2, index) { - return array1.concat(Array.prototype.slice.call(array2, index)); - } + this.$get = function () { + return handler; + }; - this.debugEnabled = function(flag) { - if (angular.isDefined(flag)) { - debug = flag; - return this; - } else { - return debug; - } - }; - - this.$get = function () { - var $log = { - log: function() { $log.log.logs.push(concat([], arguments, 0)); }, - warn: function() { $log.warn.logs.push(concat([], arguments, 0)); }, - info: function() { $log.info.logs.push(concat([], arguments, 0)); }, - error: function() { $log.error.logs.push(concat([], arguments, 0)); }, - debug: function() { - if (debug) { - $log.debug.logs.push(concat([], arguments, 0)); - } - } + this.mode('rethrow'); }; + /** - * @ngdoc method - * @name ngMock.$log#reset - * @methodOf ngMock.$log + * @ngdoc service + * @name ngMock.$log * * @description - * Reset all of the logging arrays to empty. + * Mock implementation of {@link ng.$log} that gathers all logged messages in arrays + * (one array per logging level). These arrays are exposed as `logs` property of each of the + * level-specific log function, e.g. for level `error` the array is exposed as `$log.error.logs`. + * */ - $log.reset = function () { - /** - * @ngdoc property - * @name ngMock.$log#log.logs - * @propertyOf ngMock.$log - * - * @description - * Array of messages logged using {@link ngMock.$log#log}. - * - * @example - *
-       * $log.log('Some Log');
-       * var first = $log.log.logs.unshift();
-       * 
- */ - $log.log.logs = []; - /** - * @ngdoc property - * @name ngMock.$log#info.logs - * @propertyOf ngMock.$log - * - * @description - * Array of messages logged using {@link ngMock.$log#info}. - * - * @example - *
-       * $log.info('Some Info');
-       * var first = $log.info.logs.unshift();
-       * 
- */ - $log.info.logs = []; - /** - * @ngdoc property - * @name ngMock.$log#warn.logs - * @propertyOf ngMock.$log - * - * @description - * Array of messages logged using {@link ngMock.$log#warn}. - * - * @example - *
-       * $log.warn('Some Warning');
-       * var first = $log.warn.logs.unshift();
-       * 
- */ - $log.warn.logs = []; - /** - * @ngdoc property - * @name ngMock.$log#error.logs - * @propertyOf ngMock.$log - * - * @description - * Array of messages logged using {@link ngMock.$log#error}. - * - * @example - *
-       * $log.error('Some Error');
-       * var first = $log.error.logs.unshift();
-       * 
- */ - $log.error.logs = []; - /** - * @ngdoc property - * @name ngMock.$log#debug.logs - * @propertyOf ngMock.$log - * - * @description - * Array of messages logged using {@link ngMock.$log#debug}. - * - * @example - *
-       * $log.debug('Some Error');
-       * var first = $log.debug.logs.unshift();
-       * 
- */ - $log.debug.logs = []; + angular.mock.$LogProvider = function () { + var debug = true; + + function concat(array1, array2, index) { + return array1.concat(Array.prototype.slice.call(array2, index)); + } + + this.debugEnabled = function (flag) { + if (angular.isDefined(flag)) { + debug = flag; + return this; + } else { + return debug; + } + }; + + this.$get = function () { + var $log = { + log: function () { + $log.log.logs.push(concat([], arguments, 0)); + }, + warn: function () { + $log.warn.logs.push(concat([], arguments, 0)); + }, + info: function () { + $log.info.logs.push(concat([], arguments, 0)); + }, + error: function () { + $log.error.logs.push(concat([], arguments, 0)); + }, + debug: function () { + if (debug) { + $log.debug.logs.push(concat([], arguments, 0)); + } + } + }; + + /** + * @ngdoc method + * @name ngMock.$log#reset + * @methodOf ngMock.$log + * + * @description + * Reset all of the logging arrays to empty. + */ + $log.reset = function () { + /** + * @ngdoc property + * @name ngMock.$log#log.logs + * @propertyOf ngMock.$log + * + * @description + * Array of messages logged using {@link ngMock.$log#log}. + * + * @example + *
+                 * $log.log('Some Log');
+                 * var first = $log.log.logs.unshift();
+                 * 
+ */ + $log.log.logs = []; + /** + * @ngdoc property + * @name ngMock.$log#info.logs + * @propertyOf ngMock.$log + * + * @description + * Array of messages logged using {@link ngMock.$log#info}. + * + * @example + *
+                 * $log.info('Some Info');
+                 * var first = $log.info.logs.unshift();
+                 * 
+ */ + $log.info.logs = []; + /** + * @ngdoc property + * @name ngMock.$log#warn.logs + * @propertyOf ngMock.$log + * + * @description + * Array of messages logged using {@link ngMock.$log#warn}. + * + * @example + *
+                 * $log.warn('Some Warning');
+                 * var first = $log.warn.logs.unshift();
+                 * 
+ */ + $log.warn.logs = []; + /** + * @ngdoc property + * @name ngMock.$log#error.logs + * @propertyOf ngMock.$log + * + * @description + * Array of messages logged using {@link ngMock.$log#error}. + * + * @example + *
+                 * $log.error('Some Error');
+                 * var first = $log.error.logs.unshift();
+                 * 
+ */ + $log.error.logs = []; + /** + * @ngdoc property + * @name ngMock.$log#debug.logs + * @propertyOf ngMock.$log + * + * @description + * Array of messages logged using {@link ngMock.$log#debug}. + * + * @example + *
+                 * $log.debug('Some Error');
+                 * var first = $log.debug.logs.unshift();
+                 * 
+ */ + $log.debug.logs = []; + }; + + /** + * @ngdoc method + * @name ngMock.$log#assertEmpty + * @methodOf ngMock.$log + * + * @description + * Assert that the all of the logging methods have no logged messages. If messages present, an + * exception is thrown. + */ + $log.assertEmpty = function () { + var errors = []; + angular.forEach(['error', 'warn', 'info', 'log', 'debug'], function (logLevel) { + angular.forEach($log[logLevel].logs, function (log) { + angular.forEach(log, function (logItem) { + errors.push('MOCK $log (' + logLevel + '): ' + String(logItem) + '\n' + + (logItem.stack || '')); + }); + }); + }); + if (errors.length) { + errors.unshift("Expected $log to be empty! Either a message was logged unexpectedly, or " + + "an expected log message was not checked and removed:"); + errors.push(''); + throw new Error(errors.join('\n---------\n')); + } + }; + + $log.reset(); + return $log; + }; }; + /** - * @ngdoc method - * @name ngMock.$log#assertEmpty - * @methodOf ngMock.$log + * @ngdoc service + * @name ngMock.$interval * * @description - * Assert that the all of the logging methods have no logged messages. If messages present, an - * exception is thrown. + * Mock implementation of the $interval service. + * + * Use {@link ngMock.$interval#methods_flush `$interval.flush(millis)`} to + * move forward by `millis` milliseconds and trigger any functions scheduled to run in that + * time. + * + * @param {function()} fn A function that should be called repeatedly. + * @param {number} delay Number of milliseconds between each function call. + * @param {number=} [count=0] Number of times to repeat. If not set, or 0, will repeat + * indefinitely. + * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise + * will invoke `fn` within the {@link ng.$rootScope.Scope#methods_$apply $apply} block. + * @returns {promise} A promise which will be notified on each iteration. */ - $log.assertEmpty = function() { - var errors = []; - angular.forEach(['error', 'warn', 'info', 'log', 'debug'], function(logLevel) { - angular.forEach($log[logLevel].logs, function(log) { - angular.forEach(log, function (logItem) { - errors.push('MOCK $log (' + logLevel + '): ' + String(logItem) + '\n' + - (logItem.stack || '')); - }); - }); - }); - if (errors.length) { - errors.unshift("Expected $log to be empty! Either a message was logged unexpectedly, or "+ - "an expected log message was not checked and removed:"); - errors.push(''); - throw new Error(errors.join('\n---------\n')); - } + angular.mock.$IntervalProvider = function () { + this.$get = ['$rootScope', '$q', + function ($rootScope, $q) { + var repeatFns = [], + nextRepeatId = 0, + now = 0; + + var $interval = function (fn, delay, count, invokeApply) { + var deferred = $q.defer(), + promise = deferred.promise, + iteration = 0, + skipApply = (angular.isDefined(invokeApply) && !invokeApply); + + count = (angular.isDefined(count)) ? count : 0, + promise.then(null, null, fn); + + promise.$$intervalId = nextRepeatId; + + function tick() { + deferred.notify(iteration++); + + if (count > 0 && iteration >= count) { + var fnIndex; + deferred.resolve(iteration); + + angular.forEach(repeatFns, function (fn, index) { + if (fn.id === promise.$$intervalId) fnIndex = index; + }); + + if (fnIndex !== undefined) { + repeatFns.splice(fnIndex, 1); + } + } + + if (!skipApply) $rootScope.$apply(); + } + + repeatFns.push({ + nextTime: (now + delay), + delay: delay, + fn: tick, + id: nextRepeatId, + deferred: deferred + }); + repeatFns.sort(function (a, b) { + return a.nextTime - b.nextTime; + }); + + nextRepeatId++; + return promise; + }; + + $interval.cancel = function (promise) { + if (!promise) return false; + var fnIndex; + + angular.forEach(repeatFns, function (fn, index) { + if (fn.id === promise.$$intervalId) fnIndex = index; + }); + + if (fnIndex !== undefined) { + repeatFns[fnIndex].deferred.reject('canceled'); + repeatFns.splice(fnIndex, 1); + return true; + } + + return false; + }; + + /** + * @ngdoc method + * @name ngMock.$interval#flush + * @methodOf ngMock.$interval + * @description + * + * Runs interval tasks scheduled to be run in the next `millis` milliseconds. + * + * @param {number=} millis maximum timeout amount to flush up until. + * + * @return {number} The amount of time moved forward. + */ + $interval.flush = function (millis) { + now += millis; + while (repeatFns.length && repeatFns[0].nextTime <= now) { + var task = repeatFns[0]; + task.fn(); + task.nextTime += task.delay; + repeatFns.sort(function (a, b) { + return a.nextTime - b.nextTime; + }); + } + return millis; + }; + + return $interval; + }]; }; - $log.reset(); - return $log; - }; -}; - -/** - * @ngdoc service - * @name ngMock.$interval - * - * @description - * Mock implementation of the $interval service. - * - * Use {@link ngMock.$interval#methods_flush `$interval.flush(millis)`} to - * move forward by `millis` milliseconds and trigger any functions scheduled to run in that - * time. - * - * @param {function()} fn A function that should be called repeatedly. - * @param {number} delay Number of milliseconds between each function call. - * @param {number=} [count=0] Number of times to repeat. If not set, or 0, will repeat - * indefinitely. - * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise - * will invoke `fn` within the {@link ng.$rootScope.Scope#methods_$apply $apply} block. - * @returns {promise} A promise which will be notified on each iteration. - */ -angular.mock.$IntervalProvider = function() { - this.$get = ['$rootScope', '$q', - function($rootScope, $q) { - var repeatFns = [], - nextRepeatId = 0, - now = 0; - - var $interval = function(fn, delay, count, invokeApply) { - var deferred = $q.defer(), - promise = deferred.promise, - iteration = 0, - skipApply = (angular.isDefined(invokeApply) && !invokeApply); - - count = (angular.isDefined(count)) ? count : 0, - promise.then(null, null, fn); - - promise.$$intervalId = nextRepeatId; - - function tick() { - deferred.notify(iteration++); - - if (count > 0 && iteration >= count) { - var fnIndex; - deferred.resolve(iteration); - - angular.forEach(repeatFns, function(fn, index) { - if (fn.id === promise.$$intervalId) fnIndex = index; - }); - - if (fnIndex !== undefined) { - repeatFns.splice(fnIndex, 1); - } + /* jshint -W101 */ + /* The R_ISO8061_STR regex is never going to fit into the 100 char limit! + * This directive should go inside the anonymous function but a bug in JSHint means that it would + * not be enacted early enough to prevent the warning. + */ + var R_ISO8061_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?:\:?(\d\d)(?:\:?(\d\d)(?:\.(\d{3}))?)?)?(Z|([+-])(\d\d):?(\d\d)))?$/; + + function jsonStringToDate(string) { + var match; + if (match = string.match(R_ISO8061_STR)) { + var date = new Date(0), + tzHour = 0, + tzMin = 0; + if (match[9]) { + tzHour = int(match[9] + match[10]); + tzMin = int(match[9] + match[11]); + } + date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3])); + date.setUTCHours(int(match[4] || 0) - tzHour, + int(match[5] || 0) - tzMin, + int(match[6] || 0), + int(match[7] || 0)); + return date; } + return string; + } - if (!skipApply) $rootScope.$apply(); - } - - repeatFns.push({ - nextTime:(now + delay), - delay: delay, - fn: tick, - id: nextRepeatId, - deferred: deferred - }); - repeatFns.sort(function(a,b){ return a.nextTime - b.nextTime;}); - - nextRepeatId++; - return promise; - }; - - $interval.cancel = function(promise) { - if(!promise) return false; - var fnIndex; - - angular.forEach(repeatFns, function(fn, index) { - if (fn.id === promise.$$intervalId) fnIndex = index; - }); + function int(str) { + return parseInt(str, 10); + } - if (fnIndex !== undefined) { - repeatFns[fnIndex].deferred.reject('canceled'); - repeatFns.splice(fnIndex, 1); - return true; - } + function padNumber(num, digits, trim) { + var neg = ''; + if (num < 0) { + neg = '-'; + num = -num; + } + num = '' + num; + while (num.length < digits) num = '0' + num; + if (trim) + num = num.substr(num.length - digits); + return neg + num; + } - return false; - }; /** - * @ngdoc method - * @name ngMock.$interval#flush - * @methodOf ngMock.$interval + * @ngdoc object + * @name angular.mock.TzDate * @description * - * Runs interval tasks scheduled to be run in the next `millis` milliseconds. + * *NOTE*: this is not an injectable instance, just a globally available mock class of `Date`. + * + * Mock of the Date type which has its timezone specified via constructor arg. + * + * The main purpose is to create Date-like instances with timezone fixed to the specified timezone + * offset, so that we can test code that depends on local timezone settings without dependency on + * the time zone settings of the machine where the code is running. + * + * @param {number} offset Offset of the *desired* timezone in hours (fractions will be honored) + * @param {(number|string)} timestamp Timestamp representing the desired time in *UTC* * - * @param {number=} millis maximum timeout amount to flush up until. + * @example + * !!!! WARNING !!!!! + * This is not a complete Date object so only methods that were implemented can be called safely. + * To make matters worse, TzDate instances inherit stuff from Date via a prototype. + * + * We do our best to intercept calls to "unimplemented" methods, but since the list of methods is + * incomplete we might be missing some non-standard methods. This can result in errors like: + * "Date.prototype.foo called on incompatible Object". + * + *
+     * var newYearInBratislava = new TzDate(-1, '2009-12-31T23:00:00Z');
+     * newYearInBratislava.getTimezoneOffset() => -60;
+     * newYearInBratislava.getFullYear() => 2010;
+     * newYearInBratislava.getMonth() => 0;
+     * newYearInBratislava.getDate() => 1;
+     * newYearInBratislava.getHours() => 0;
+     * newYearInBratislava.getMinutes() => 0;
+     * newYearInBratislava.getSeconds() => 0;
+     * 
* - * @return {number} The amount of time moved forward. */ - $interval.flush = function(millis) { - now += millis; - while (repeatFns.length && repeatFns[0].nextTime <= now) { - var task = repeatFns[0]; - task.fn(); - task.nextTime += task.delay; - repeatFns.sort(function(a,b){ return a.nextTime - b.nextTime;}); - } - return millis; - }; + angular.mock.TzDate = function (offset, timestamp) { + var self = new Date(0); + if (angular.isString(timestamp)) { + var tsStr = timestamp; + + self.origDate = jsonStringToDate(timestamp); + + timestamp = self.origDate.getTime(); + if (isNaN(timestamp)) + throw { + name: "Illegal Argument", + message: "Arg '" + tsStr + "' passed into TzDate constructor is not a valid date string" + }; + } else { + self.origDate = new Date(timestamp); + } - return $interval; - }]; -}; + var localOffset = new Date(timestamp).getTimezoneOffset(); + self.offsetDiff = localOffset * 60 * 1000 - offset * 1000 * 60 * 60; + self.date = new Date(timestamp + self.offsetDiff); + self.getTime = function () { + return self.date.getTime() - self.offsetDiff; + }; -/* jshint -W101 */ -/* The R_ISO8061_STR regex is never going to fit into the 100 char limit! - * This directive should go inside the anonymous function but a bug in JSHint means that it would - * not be enacted early enough to prevent the warning. - */ -var R_ISO8061_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?:\:?(\d\d)(?:\:?(\d\d)(?:\.(\d{3}))?)?)?(Z|([+-])(\d\d):?(\d\d)))?$/; - -function jsonStringToDate(string) { - var match; - if (match = string.match(R_ISO8061_STR)) { - var date = new Date(0), - tzHour = 0, - tzMin = 0; - if (match[9]) { - tzHour = int(match[9] + match[10]); - tzMin = int(match[9] + match[11]); - } - date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3])); - date.setUTCHours(int(match[4]||0) - tzHour, - int(match[5]||0) - tzMin, - int(match[6]||0), - int(match[7]||0)); - return date; - } - return string; -} - -function int(str) { - return parseInt(str, 10); -} - -function padNumber(num, digits, trim) { - var neg = ''; - if (num < 0) { - neg = '-'; - num = -num; - } - num = '' + num; - while(num.length < digits) num = '0' + num; - if (trim) - num = num.substr(num.length - digits); - return neg + num; -} + self.toLocaleDateString = function () { + return self.date.toLocaleDateString(); + }; + self.getFullYear = function () { + return self.date.getFullYear(); + }; -/** - * @ngdoc object - * @name angular.mock.TzDate - * @description - * - * *NOTE*: this is not an injectable instance, just a globally available mock class of `Date`. - * - * Mock of the Date type which has its timezone specified via constructor arg. - * - * The main purpose is to create Date-like instances with timezone fixed to the specified timezone - * offset, so that we can test code that depends on local timezone settings without dependency on - * the time zone settings of the machine where the code is running. - * - * @param {number} offset Offset of the *desired* timezone in hours (fractions will be honored) - * @param {(number|string)} timestamp Timestamp representing the desired time in *UTC* - * - * @example - * !!!! WARNING !!!!! - * This is not a complete Date object so only methods that were implemented can be called safely. - * To make matters worse, TzDate instances inherit stuff from Date via a prototype. - * - * We do our best to intercept calls to "unimplemented" methods, but since the list of methods is - * incomplete we might be missing some non-standard methods. This can result in errors like: - * "Date.prototype.foo called on incompatible Object". - * - *
- * var newYearInBratislava = new TzDate(-1, '2009-12-31T23:00:00Z');
- * newYearInBratislava.getTimezoneOffset() => -60;
- * newYearInBratislava.getFullYear() => 2010;
- * newYearInBratislava.getMonth() => 0;
- * newYearInBratislava.getDate() => 1;
- * newYearInBratislava.getHours() => 0;
- * newYearInBratislava.getMinutes() => 0;
- * newYearInBratislava.getSeconds() => 0;
- * 
- * - */ -angular.mock.TzDate = function (offset, timestamp) { - var self = new Date(0); - if (angular.isString(timestamp)) { - var tsStr = timestamp; - - self.origDate = jsonStringToDate(timestamp); - - timestamp = self.origDate.getTime(); - if (isNaN(timestamp)) - throw { - name: "Illegal Argument", - message: "Arg '" + tsStr + "' passed into TzDate constructor is not a valid date string" - }; - } else { - self.origDate = new Date(timestamp); - } + self.getMonth = function () { + return self.date.getMonth(); + }; - var localOffset = new Date(timestamp).getTimezoneOffset(); - self.offsetDiff = localOffset*60*1000 - offset*1000*60*60; - self.date = new Date(timestamp + self.offsetDiff); - - self.getTime = function() { - return self.date.getTime() - self.offsetDiff; - }; - - self.toLocaleDateString = function() { - return self.date.toLocaleDateString(); - }; - - self.getFullYear = function() { - return self.date.getFullYear(); - }; - - self.getMonth = function() { - return self.date.getMonth(); - }; - - self.getDate = function() { - return self.date.getDate(); - }; - - self.getHours = function() { - return self.date.getHours(); - }; - - self.getMinutes = function() { - return self.date.getMinutes(); - }; - - self.getSeconds = function() { - return self.date.getSeconds(); - }; - - self.getMilliseconds = function() { - return self.date.getMilliseconds(); - }; - - self.getTimezoneOffset = function() { - return offset * 60; - }; - - self.getUTCFullYear = function() { - return self.origDate.getUTCFullYear(); - }; - - self.getUTCMonth = function() { - return self.origDate.getUTCMonth(); - }; - - self.getUTCDate = function() { - return self.origDate.getUTCDate(); - }; - - self.getUTCHours = function() { - return self.origDate.getUTCHours(); - }; - - self.getUTCMinutes = function() { - return self.origDate.getUTCMinutes(); - }; - - self.getUTCSeconds = function() { - return self.origDate.getUTCSeconds(); - }; - - self.getUTCMilliseconds = function() { - return self.origDate.getUTCMilliseconds(); - }; - - self.getDay = function() { - return self.date.getDay(); - }; - - // provide this method only on browsers that already have it - if (self.toISOString) { - self.toISOString = function() { - return padNumber(self.origDate.getUTCFullYear(), 4) + '-' + - padNumber(self.origDate.getUTCMonth() + 1, 2) + '-' + - padNumber(self.origDate.getUTCDate(), 2) + 'T' + - padNumber(self.origDate.getUTCHours(), 2) + ':' + - padNumber(self.origDate.getUTCMinutes(), 2) + ':' + - padNumber(self.origDate.getUTCSeconds(), 2) + '.' + - padNumber(self.origDate.getUTCMilliseconds(), 3) + 'Z'; - }; - } + self.getDate = function () { + return self.date.getDate(); + }; - //hide all methods not implemented in this mock that the Date prototype exposes - var unimplementedMethods = ['getUTCDay', - 'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds', - 'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear', - 'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds', - 'setYear', 'toDateString', 'toGMTString', 'toJSON', 'toLocaleFormat', 'toLocaleString', - 'toLocaleTimeString', 'toSource', 'toString', 'toTimeString', 'toUTCString', 'valueOf']; - - angular.forEach(unimplementedMethods, function(methodName) { - self[methodName] = function() { - throw new Error("Method '" + methodName + "' is not implemented in the TzDate mock"); - }; - }); + self.getHours = function () { + return self.date.getHours(); + }; - return self; -}; + self.getMinutes = function () { + return self.date.getMinutes(); + }; -//make "tzDateInstance instanceof Date" return true -angular.mock.TzDate.prototype = Date.prototype; -/* jshint +W101 */ + self.getSeconds = function () { + return self.date.getSeconds(); + }; -angular.mock.animate = angular.module('ngAnimateMock', ['ng']) + self.getMilliseconds = function () { + return self.date.getMilliseconds(); + }; - .config(['$provide', function($provide) { - var reflowQueue = []; + self.getTimezoneOffset = function () { + return offset * 60; + }; - $provide.value('$$animateReflow', function(fn) { - reflowQueue.push(fn); - return angular.noop; - }); + self.getUTCFullYear = function () { + return self.origDate.getUTCFullYear(); + }; - $provide.decorator('$animate', function($delegate) { - var animate = { - queue : [], - enabled : $delegate.enabled, - triggerReflow : function() { - if(reflowQueue.length === 0) { - throw new Error('No animation reflows present'); - } - angular.forEach(reflowQueue, function(fn) { - fn(); - }); - reflowQueue = []; - } - }; - - angular.forEach( - ['enter','leave','move','addClass','removeClass','setClass'], function(method) { - animate[method] = function() { - animate.queue.push({ - event : method, - element : arguments[0], - args : arguments - }); - $delegate[method].apply($delegate, arguments); + self.getUTCMonth = function () { + return self.origDate.getUTCMonth(); }; - }); - return animate; - }); + self.getUTCDate = function () { + return self.origDate.getUTCDate(); + }; - }]); + self.getUTCHours = function () { + return self.origDate.getUTCHours(); + }; + self.getUTCMinutes = function () { + return self.origDate.getUTCMinutes(); + }; -/** - * @ngdoc function - * @name angular.mock.dump - * @description - * - * *NOTE*: this is not an injectable instance, just a globally available function. - * - * Method for serializing common angular objects (scope, elements, etc..) into strings, useful for - * debugging. - * - * This method is also available on window, where it can be used to display objects on debug - * console. - * - * @param {*} object - any object to turn into string. - * @return {string} a serialized string of the argument - */ -angular.mock.dump = function(object) { - return serialize(object); + self.getUTCSeconds = function () { + return self.origDate.getUTCSeconds(); + }; - function serialize(object) { - var out; + self.getUTCMilliseconds = function () { + return self.origDate.getUTCMilliseconds(); + }; - if (angular.isElement(object)) { - object = angular.element(object); - out = angular.element('
'); - angular.forEach(object, function(element) { - out.append(angular.element(element).clone()); - }); - out = out.html(); - } else if (angular.isArray(object)) { - out = []; - angular.forEach(object, function(o) { - out.push(serialize(o)); - }); - out = '[ ' + out.join(', ') + ' ]'; - } else if (angular.isObject(object)) { - if (angular.isFunction(object.$eval) && angular.isFunction(object.$apply)) { - out = serializeScope(object); - } else if (object instanceof Error) { - out = object.stack || ('' + object.name + ': ' + object.message); - } else { - // TODO(i): this prevents methods being logged, - // we should have a better way to serialize objects - out = angular.toJson(object, true); - } - } else { - out = String(object); - } + self.getDay = function () { + return self.date.getDay(); + }; - return out; - } + // provide this method only on browsers that already have it + if (self.toISOString) { + self.toISOString = function () { + return padNumber(self.origDate.getUTCFullYear(), 4) + '-' + + padNumber(self.origDate.getUTCMonth() + 1, 2) + '-' + + padNumber(self.origDate.getUTCDate(), 2) + 'T' + + padNumber(self.origDate.getUTCHours(), 2) + ':' + + padNumber(self.origDate.getUTCMinutes(), 2) + ':' + + padNumber(self.origDate.getUTCSeconds(), 2) + '.' + + padNumber(self.origDate.getUTCMilliseconds(), 3) + 'Z'; + }; + } - function serializeScope(scope, offset) { - offset = offset || ' '; - var log = [offset + 'Scope(' + scope.$id + '): {']; - for ( var key in scope ) { - if (Object.prototype.hasOwnProperty.call(scope, key) && !key.match(/^(\$|this)/)) { - log.push(' ' + key + ': ' + angular.toJson(scope[key])); - } - } - var child = scope.$$childHead; - while(child) { - log.push(serializeScope(child, offset + ' ')); - child = child.$$nextSibling; - } - log.push('}'); - return log.join('\n' + offset); - } -}; + //hide all methods not implemented in this mock that the Date prototype exposes + var unimplementedMethods = ['getUTCDay', + 'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds', + 'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear', + 'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds', + 'setYear', 'toDateString', 'toGMTString', 'toJSON', 'toLocaleFormat', 'toLocaleString', + 'toLocaleTimeString', 'toSource', 'toString', 'toTimeString', 'toUTCString', 'valueOf']; + + angular.forEach(unimplementedMethods, function (methodName) { + self[methodName] = function () { + throw new Error("Method '" + methodName + "' is not implemented in the TzDate mock"); + }; + }); -/** - * @ngdoc object - * @name ngMock.$httpBackend - * @description - * Fake HTTP backend implementation suitable for unit testing applications that use the - * {@link ng.$http $http service}. - * - * *Note*: For fake HTTP backend implementation suitable for end-to-end testing or backend-less - * development please see {@link ngMockE2E.$httpBackend e2e $httpBackend mock}. - * - * During unit testing, we want our unit tests to run quickly and have no external dependencies so - * we don’t want to send {@link https://developer.mozilla.org/en/xmlhttprequest XHR} or - * {@link http://en.wikipedia.org/wiki/JSONP JSONP} requests to a real server. All we really need is - * to verify whether a certain request has been sent or not, or alternatively just let the - * application make requests, respond with pre-trained responses and assert that the end result is - * what we expect it to be. - * - * This mock implementation can be used to respond with static or dynamic responses via the - * `expect` and `when` apis and their shortcuts (`expectGET`, `whenPOST`, etc). - * - * When an Angular application needs some data from a server, it calls the $http service, which - * sends the request to a real server using $httpBackend service. With dependency injection, it is - * easy to inject $httpBackend mock (which has the same API as $httpBackend) and use it to verify - * the requests and respond with some testing data without sending a request to real server. - * - * There are two ways to specify what test data should be returned as http responses by the mock - * backend when the code under test makes http requests: - * - * - `$httpBackend.expect` - specifies a request expectation - * - `$httpBackend.when` - specifies a backend definition - * - * - * # Request Expectations vs Backend Definitions - * - * Request expectations provide a way to make assertions about requests made by the application and - * to define responses for those requests. The test will fail if the expected requests are not made - * or they are made in the wrong order. - * - * Backend definitions allow you to define a fake backend for your application which doesn't assert - * if a particular request was made or not, it just returns a trained response if a request is made. - * The test will pass whether or not the request gets made during testing. - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
Request expectationsBackend definitions
Syntax.expect(...).respond(...).when(...).respond(...)
Typical usagestrict unit testsloose (black-box) unit testing
Fulfills multiple requestsNOYES
Order of requests mattersYESNO
Request requiredYESNO
Response requiredoptional (see below)YES
- * - * In cases where both backend definitions and request expectations are specified during unit - * testing, the request expectations are evaluated first. - * - * If a request expectation has no response specified, the algorithm will search your backend - * definitions for an appropriate response. - * - * If a request didn't match any expectation or if the expectation doesn't have the response - * defined, the backend definitions are evaluated in sequential order to see if any of them match - * the request. The response from the first matched definition is returned. - * - * - * # Flushing HTTP requests - * - * The $httpBackend used in production always responds to requests with responses asynchronously. - * If we preserved this behavior in unit testing we'd have to create async unit tests, which are - * hard to write, understand, and maintain. However, the testing mock can't respond - * synchronously because that would change the execution of the code under test. For this reason the - * mock $httpBackend has a `flush()` method, which allows the test to explicitly flush pending - * requests and thus preserve the async api of the backend while allowing the test to execute - * synchronously. - * - * - * # Unit testing with mock $httpBackend - * The following code shows how to setup and use the mock backend when unit testing a controller. - * First we create the controller under test: - * -
-  // The controller code
-  function MyController($scope, $http) {
+        return self;
+    };
+
+//make "tzDateInstance instanceof Date" return true
+    angular.mock.TzDate.prototype = Date.prototype;
+    /* jshint +W101 */
+
+    angular.mock.animate = angular.module('ngAnimateMock', ['ng'])
+
+        .config(['$provide', function ($provide) {
+            var reflowQueue = [];
+
+            $provide.value('$$animateReflow', function (fn) {
+                reflowQueue.push(fn);
+                return angular.noop;
+            });
+
+            $provide.decorator('$animate', function ($delegate) {
+                var animate = {
+                    queue: [],
+                    enabled: $delegate.enabled,
+                    triggerReflow: function () {
+                        if (reflowQueue.length === 0) {
+                            throw new Error('No animation reflows present');
+                        }
+                        angular.forEach(reflowQueue, function (fn) {
+                            fn();
+                        });
+                        reflowQueue = [];
+                    }
+                };
+
+                angular.forEach(
+                    ['enter', 'leave', 'move', 'addClass', 'removeClass', 'setClass'], function (method) {
+                        animate[method] = function () {
+                            animate.queue.push({
+                                event: method,
+                                element: arguments[0],
+                                args: arguments
+                            });
+                            $delegate[method].apply($delegate, arguments);
+                        };
+                    });
+
+                return animate;
+            });
+
+        }]);
+
+
+    /**
+     * @ngdoc function
+     * @name angular.mock.dump
+     * @description
+     *
+     * *NOTE*: this is not an injectable instance, just a globally available function.
+     *
+     * Method for serializing common angular objects (scope, elements, etc..) into strings, useful for
+     * debugging.
+     *
+     * This method is also available on window, where it can be used to display objects on debug
+     * console.
+     *
+     * @param {*} object - any object to turn into string.
+     * @return {string} a serialized string of the argument
+     */
+    angular.mock.dump = function (object) {
+        return serialize(object);
+
+        function serialize(object) {
+            var out;
+
+            if (angular.isElement(object)) {
+                object = angular.element(object);
+                out = angular.element('
'); + angular.forEach(object, function (element) { + out.append(angular.element(element).clone()); + }); + out = out.html(); + } else if (angular.isArray(object)) { + out = []; + angular.forEach(object, function (o) { + out.push(serialize(o)); + }); + out = '[ ' + out.join(', ') + ' ]'; + } else if (angular.isObject(object)) { + if (angular.isFunction(object.$eval) && angular.isFunction(object.$apply)) { + out = serializeScope(object); + } else if (object instanceof Error) { + out = object.stack || ('' + object.name + ': ' + object.message); + } else { + // TODO(i): this prevents methods being logged, + // we should have a better way to serialize objects + out = angular.toJson(object, true); + } + } else { + out = String(object); + } + + return out; + } + + function serializeScope(scope, offset) { + offset = offset || ' '; + var log = [offset + 'Scope(' + scope.$id + '): {']; + for (var key in scope) { + if (Object.prototype.hasOwnProperty.call(scope, key) && !key.match(/^(\$|this)/)) { + log.push(' ' + key + ': ' + angular.toJson(scope[key])); + } + } + var child = scope.$$childHead; + while (child) { + log.push(serializeScope(child, offset + ' ')); + child = child.$$nextSibling; + } + log.push('}'); + return log.join('\n' + offset); + } + }; + + /** + * @ngdoc object + * @name ngMock.$httpBackend + * @description + * Fake HTTP backend implementation suitable for unit testing applications that use the + * {@link ng.$http $http service}. + * + * *Note*: For fake HTTP backend implementation suitable for end-to-end testing or backend-less + * development please see {@link ngMockE2E.$httpBackend e2e $httpBackend mock}. + * + * During unit testing, we want our unit tests to run quickly and have no external dependencies so + * we don’t want to send {@link https://developer.mozilla.org/en/xmlhttprequest XHR} or + * {@link http://en.wikipedia.org/wiki/JSONP JSONP} requests to a real server. All we really need is + * to verify whether a certain request has been sent or not, or alternatively just let the + * application make requests, respond with pre-trained responses and assert that the end result is + * what we expect it to be. + * + * This mock implementation can be used to respond with static or dynamic responses via the + * `expect` and `when` apis and their shortcuts (`expectGET`, `whenPOST`, etc). + * + * When an Angular application needs some data from a server, it calls the $http service, which + * sends the request to a real server using $httpBackend service. With dependency injection, it is + * easy to inject $httpBackend mock (which has the same API as $httpBackend) and use it to verify + * the requests and respond with some testing data without sending a request to real server. + * + * There are two ways to specify what test data should be returned as http responses by the mock + * backend when the code under test makes http requests: + * + * - `$httpBackend.expect` - specifies a request expectation + * - `$httpBackend.when` - specifies a backend definition + * + * + * # Request Expectations vs Backend Definitions + * + * Request expectations provide a way to make assertions about requests made by the application and + * to define responses for those requests. The test will fail if the expected requests are not made + * or they are made in the wrong order. + * + * Backend definitions allow you to define a fake backend for your application which doesn't assert + * if a particular request was made or not, it just returns a trained response if a request is made. + * The test will pass whether or not the request gets made during testing. + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Request expectationsBackend definitions
Syntax.expect(...).respond(...).when(...).respond(...)
Typical usagestrict unit testsloose (black-box) unit testing
Fulfills multiple requestsNOYES
Order of requests mattersYESNO
Request requiredYESNO
Response requiredoptional (see below)YES
+ * + * In cases where both backend definitions and request expectations are specified during unit + * testing, the request expectations are evaluated first. + * + * If a request expectation has no response specified, the algorithm will search your backend + * definitions for an appropriate response. + * + * If a request didn't match any expectation or if the expectation doesn't have the response + * defined, the backend definitions are evaluated in sequential order to see if any of them match + * the request. The response from the first matched definition is returned. + * + * + * # Flushing HTTP requests + * + * The $httpBackend used in production always responds to requests with responses asynchronously. + * If we preserved this behavior in unit testing we'd have to create async unit tests, which are + * hard to write, understand, and maintain. However, the testing mock can't respond + * synchronously because that would change the execution of the code under test. For this reason the + * mock $httpBackend has a `flush()` method, which allows the test to explicitly flush pending + * requests and thus preserve the async api of the backend while allowing the test to execute + * synchronously. + * + * + * # Unit testing with mock $httpBackend + * The following code shows how to setup and use the mock backend when unit testing a controller. + * First we create the controller under test: + * +
+     // The controller code
+     function MyController($scope, $http) {
     var authToken;
 
     $http.get('/auth.py').success(function(data, status, headers) {
@@ -1001,13 +1015,13 @@ angular.mock.dump = function(object) {
       });
     };
   }
-  
- * - * Now we setup the mock backend and create the test specs: - * -
-    // testing controller
-    describe('MyController', function() {
+     
+ * + * Now we setup the mock backend and create the test specs: + * +
+     // testing controller
+     describe('MyController', function() {
        var $httpBackend, $rootScope, createController;
 
        beforeEach(inject(function($injector) {
@@ -1071,1066 +1085,1068 @@ angular.mock.dump = function(object) {
          $httpBackend.flush();
        });
     });
-   
- */ -angular.mock.$HttpBackendProvider = function() { - this.$get = ['$rootScope', createHttpBackendMock]; -}; - -/** - * General factory function for $httpBackend mock. - * Returns instance for unit testing (when no arguments specified): - * - passing through is disabled - * - auto flushing is disabled - * - * Returns instance for e2e testing (when `$delegate` and `$browser` specified): - * - passing through (delegating request to real backend) is enabled - * - auto flushing is enabled - * - * @param {Object=} $delegate Real $httpBackend instance (allow passing through if specified) - * @param {Object=} $browser Auto-flushing enabled if specified - * @return {Object} Instance of $httpBackend mock - */ -function createHttpBackendMock($rootScope, $delegate, $browser) { - var definitions = [], - expectations = [], - responses = [], - responsesPush = angular.bind(responses, responses.push), - copy = angular.copy; - - function createResponse(status, data, headers) { - if (angular.isFunction(status)) return status; - - return function() { - return angular.isNumber(status) - ? [status, data, headers] - : [200, status, data]; +
+ */ + angular.mock.$HttpBackendProvider = function () { + this.$get = ['$rootScope', createHttpBackendMock]; }; - } - // TODO(vojta): change params to: method, url, data, headers, callback - function $httpBackend(method, url, data, callback, headers, timeout, withCredentials) { - var xhr = new MockXhr(), - expectation = expectations[0], - wasExpected = false; + /** + * General factory function for $httpBackend mock. + * Returns instance for unit testing (when no arguments specified): + * - passing through is disabled + * - auto flushing is disabled + * + * Returns instance for e2e testing (when `$delegate` and `$browser` specified): + * - passing through (delegating request to real backend) is enabled + * - auto flushing is enabled + * + * @param {Object=} $delegate Real $httpBackend instance (allow passing through if specified) + * @param {Object=} $browser Auto-flushing enabled if specified + * @return {Object} Instance of $httpBackend mock + */ + function createHttpBackendMock($rootScope, $delegate, $browser) { + var definitions = [], + expectations = [], + responses = [], + responsesPush = angular.bind(responses, responses.push), + copy = angular.copy; + + function createResponse(status, data, headers) { + if (angular.isFunction(status)) return status; + + return function () { + return angular.isNumber(status) + ? [status, data, headers] + : [200, status, data]; + }; + } - function prettyPrint(data) { - return (angular.isString(data) || angular.isFunction(data) || data instanceof RegExp) - ? data - : angular.toJson(data); - } + // TODO(vojta): change params to: method, url, data, headers, callback + function $httpBackend(method, url, data, callback, headers, timeout, withCredentials) { + var xhr = new MockXhr(), + expectation = expectations[0], + wasExpected = false; + + function prettyPrint(data) { + return (angular.isString(data) || angular.isFunction(data) || data instanceof RegExp) + ? data + : angular.toJson(data); + } + + function wrapResponse(wrapped) { + if (!$browser && timeout && timeout.then) timeout.then(handleTimeout); + + return handleResponse; + + function handleResponse() { + var response = wrapped.response(method, url, data, headers); + xhr.$$respHeaders = response[2]; + callback(copy(response[0]), copy(response[1]), xhr.getAllResponseHeaders()); + } + + function handleTimeout() { + for (var i = 0, ii = responses.length; i < ii; i++) { + if (responses[i] === handleResponse) { + responses.splice(i, 1); + callback(-1, undefined, ''); + break; + } + } + } + } + + if (expectation && expectation.match(method, url)) { + if (!expectation.matchData(data)) + throw new Error('Expected ' + expectation + ' with different data\n' + + 'EXPECTED: ' + prettyPrint(expectation.data) + '\nGOT: ' + data); + + if (!expectation.matchHeaders(headers)) + throw new Error('Expected ' + expectation + ' with different headers\n' + + 'EXPECTED: ' + prettyPrint(expectation.headers) + '\nGOT: ' + + prettyPrint(headers)); + + expectations.shift(); + + if (expectation.response) { + responses.push(wrapResponse(expectation)); + return; + } + wasExpected = true; + } + + var i = -1, definition; + while ((definition = definitions[++i])) { + if (definition.match(method, url, data, headers || {})) { + if (definition.response) { + // if $browser specified, we do auto flush all requests + ($browser ? $browser.defer : responsesPush)(wrapResponse(definition)); + } else if (definition.passThrough) { + $delegate(method, url, data, callback, headers, timeout, withCredentials); + } else throw new Error('No response defined !'); + return; + } + } + throw wasExpected ? + new Error('No response defined !') : + new Error('Unexpected request: ' + method + ' ' + url + '\n' + + (expectation ? 'Expected ' + expectation : 'No more request expected')); + } + + /** + * @ngdoc method + * @name ngMock.$httpBackend#when + * @methodOf ngMock.$httpBackend + * @description + * Creates a new backend definition. + * + * @param {string} method HTTP method. + * @param {string|RegExp} url HTTP url. + * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives + * data string and returns true if the data is as expected. + * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header + * object and returns true if the headers match the current definition. + * @returns {requestHandler} Returns an object with `respond` method that controls how a matched + * request is handled. + * + * - respond – + * `{function([status,] data[, headers])|function(function(method, url, data, headers)}` + * – The respond method takes a set of static data to be returned or a function that can return + * an array containing response status (number), response data (string) and response headers + * (Object). + */ + $httpBackend.when = function (method, url, data, headers) { + var definition = new MockHttpExpectation(method, url, data, headers), + chain = { + respond: function (status, data, headers) { + definition.response = createResponse(status, data, headers); + } + }; + + if ($browser) { + chain.passThrough = function () { + definition.passThrough = true; + }; + } + + definitions.push(definition); + return chain; + }; + + /** + * @ngdoc method + * @name ngMock.$httpBackend#whenGET + * @methodOf ngMock.$httpBackend + * @description + * Creates a new backend definition for GET requests. For more info see `when()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(Object|function(Object))=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ + + /** + * @ngdoc method + * @name ngMock.$httpBackend#whenHEAD + * @methodOf ngMock.$httpBackend + * @description + * Creates a new backend definition for HEAD requests. For more info see `when()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(Object|function(Object))=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ + + /** + * @ngdoc method + * @name ngMock.$httpBackend#whenDELETE + * @methodOf ngMock.$httpBackend + * @description + * Creates a new backend definition for DELETE requests. For more info see `when()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(Object|function(Object))=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ - function wrapResponse(wrapped) { - if (!$browser && timeout && timeout.then) timeout.then(handleTimeout); + /** + * @ngdoc method + * @name ngMock.$httpBackend#whenPOST + * @methodOf ngMock.$httpBackend + * @description + * Creates a new backend definition for POST requests. For more info see `when()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives + * data string and returns true if the data is as expected. + * @param {(Object|function(Object))=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ + + /** + * @ngdoc method + * @name ngMock.$httpBackend#whenPUT + * @methodOf ngMock.$httpBackend + * @description + * Creates a new backend definition for PUT requests. For more info see `when()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives + * data string and returns true if the data is as expected. + * @param {(Object|function(Object))=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ + + /** + * @ngdoc method + * @name ngMock.$httpBackend#whenJSONP + * @methodOf ngMock.$httpBackend + * @description + * Creates a new backend definition for JSONP requests. For more info see `when()`. + * + * @param {string|RegExp} url HTTP url. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ + createShortMethods('when'); + + + /** + * @ngdoc method + * @name ngMock.$httpBackend#expect + * @methodOf ngMock.$httpBackend + * @description + * Creates a new request expectation. + * + * @param {string} method HTTP method. + * @param {string|RegExp} url HTTP url. + * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that + * receives data string and returns true if the data is as expected, or Object if request body + * is in JSON format. + * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header + * object and returns true if the headers match the current expectation. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + * + * - respond – + * `{function([status,] data[, headers])|function(function(method, url, data, headers)}` + * – The respond method takes a set of static data to be returned or a function that can return + * an array containing response status (number), response data (string) and response headers + * (Object). + */ + $httpBackend.expect = function (method, url, data, headers) { + var expectation = new MockHttpExpectation(method, url, data, headers); + expectations.push(expectation); + return { + respond: function (status, data, headers) { + expectation.response = createResponse(status, data, headers); + } + }; + }; - return handleResponse; - function handleResponse() { - var response = wrapped.response(method, url, data, headers); - xhr.$$respHeaders = response[2]; - callback(copy(response[0]), copy(response[1]), xhr.getAllResponseHeaders()); - } + /** + * @ngdoc method + * @name ngMock.$httpBackend#expectGET + * @methodOf ngMock.$httpBackend + * @description + * Creates a new request expectation for GET requests. For more info see `expect()`. + * + * @param {string|RegExp} url HTTP url. + * @param {Object=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. See #expect for more info. + */ + + /** + * @ngdoc method + * @name ngMock.$httpBackend#expectHEAD + * @methodOf ngMock.$httpBackend + * @description + * Creates a new request expectation for HEAD requests. For more info see `expect()`. + * + * @param {string|RegExp} url HTTP url. + * @param {Object=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ + + /** + * @ngdoc method + * @name ngMock.$httpBackend#expectDELETE + * @methodOf ngMock.$httpBackend + * @description + * Creates a new request expectation for DELETE requests. For more info see `expect()`. + * + * @param {string|RegExp} url HTTP url. + * @param {Object=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ - function handleTimeout() { - for (var i = 0, ii = responses.length; i < ii; i++) { - if (responses[i] === handleResponse) { - responses.splice(i, 1); - callback(-1, undefined, ''); - break; - } + /** + * @ngdoc method + * @name ngMock.$httpBackend#expectPOST + * @methodOf ngMock.$httpBackend + * @description + * Creates a new request expectation for POST requests. For more info see `expect()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that + * receives data string and returns true if the data is as expected, or Object if request body + * is in JSON format. + * @param {Object=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ + + /** + * @ngdoc method + * @name ngMock.$httpBackend#expectPUT + * @methodOf ngMock.$httpBackend + * @description + * Creates a new request expectation for PUT requests. For more info see `expect()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that + * receives data string and returns true if the data is as expected, or Object if request body + * is in JSON format. + * @param {Object=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ + + /** + * @ngdoc method + * @name ngMock.$httpBackend#expectPATCH + * @methodOf ngMock.$httpBackend + * @description + * Creates a new request expectation for PATCH requests. For more info see `expect()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that + * receives data string and returns true if the data is as expected, or Object if request body + * is in JSON format. + * @param {Object=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ + + /** + * @ngdoc method + * @name ngMock.$httpBackend#expectJSONP + * @methodOf ngMock.$httpBackend + * @description + * Creates a new request expectation for JSONP requests. For more info see `expect()`. + * + * @param {string|RegExp} url HTTP url. + * @returns {requestHandler} Returns an object with `respond` method that control how a matched + * request is handled. + */ + createShortMethods('expect'); + + + /** + * @ngdoc method + * @name ngMock.$httpBackend#flush + * @methodOf ngMock.$httpBackend + * @description + * Flushes all pending requests using the trained responses. + * + * @param {number=} count Number of responses to flush (in the order they arrived). If undefined, + * all pending requests will be flushed. If there are no pending requests when the flush method + * is called an exception is thrown (as this typically a sign of programming error). + */ + $httpBackend.flush = function (count) { + $rootScope.$digest(); + if (!responses.length) throw new Error('No pending request to flush !'); + + if (angular.isDefined(count)) { + while (count--) { + if (!responses.length) throw new Error('No more pending request to flush !'); + responses.shift()(); + } + } else { + while (responses.length) { + responses.shift()(); + } + } + $httpBackend.verifyNoOutstandingExpectation(); + }; + + + /** + * @ngdoc method + * @name ngMock.$httpBackend#verifyNoOutstandingExpectation + * @methodOf ngMock.$httpBackend + * @description + * Verifies that all of the requests defined via the `expect` api were made. If any of the + * requests were not made, verifyNoOutstandingExpectation throws an exception. + * + * Typically, you would call this method following each test case that asserts requests using an + * "afterEach" clause. + * + *
+         *   afterEach($httpBackend.verifyNoOutstandingExpectation);
+         * 
+ */ + $httpBackend.verifyNoOutstandingExpectation = function () { + $rootScope.$digest(); + if (expectations.length) { + throw new Error('Unsatisfied requests: ' + expectations.join(', ')); + } + }; + + + /** + * @ngdoc method + * @name ngMock.$httpBackend#verifyNoOutstandingRequest + * @methodOf ngMock.$httpBackend + * @description + * Verifies that there are no outstanding requests that need to be flushed. + * + * Typically, you would call this method following each test case that asserts requests using an + * "afterEach" clause. + * + *
+         *   afterEach($httpBackend.verifyNoOutstandingRequest);
+         * 
+ */ + $httpBackend.verifyNoOutstandingRequest = function () { + if (responses.length) { + throw new Error('Unflushed requests: ' + responses.length); + } + }; + + + /** + * @ngdoc method + * @name ngMock.$httpBackend#resetExpectations + * @methodOf ngMock.$httpBackend + * @description + * Resets all request expectations, but preserves all backend definitions. Typically, you would + * call resetExpectations during a multiple-phase test when you want to reuse the same instance of + * $httpBackend mock. + */ + $httpBackend.resetExpectations = function () { + expectations.length = 0; + responses.length = 0; + }; + + return $httpBackend; + + + function createShortMethods(prefix) { + angular.forEach(['GET', 'DELETE', 'JSONP'], function (method) { + $httpBackend[prefix + method] = function (url, headers) { + return $httpBackend[prefix](method, url, undefined, headers); + }; + }); + + angular.forEach(['PUT', 'POST', 'PATCH'], function (method) { + $httpBackend[prefix + method] = function (url, data, headers) { + return $httpBackend[prefix](method, url, data, headers); + }; + }); } - } } - if (expectation && expectation.match(method, url)) { - if (!expectation.matchData(data)) - throw new Error('Expected ' + expectation + ' with different data\n' + - 'EXPECTED: ' + prettyPrint(expectation.data) + '\nGOT: ' + data); + function MockHttpExpectation(method, url, data, headers) { - if (!expectation.matchHeaders(headers)) - throw new Error('Expected ' + expectation + ' with different headers\n' + - 'EXPECTED: ' + prettyPrint(expectation.headers) + '\nGOT: ' + - prettyPrint(headers)); + this.data = data; + this.headers = headers; - expectations.shift(); + this.match = function (m, u, d, h) { + if (method != m) return false; + if (!this.matchUrl(u)) return false; + if (angular.isDefined(d) && !this.matchData(d)) return false; + if (angular.isDefined(h) && !this.matchHeaders(h)) return false; + return true; + }; - if (expectation.response) { - responses.push(wrapResponse(expectation)); - return; - } - wasExpected = true; - } + this.matchUrl = function (u) { + if (!url) return true; + if (angular.isFunction(url.test)) return url.test(u); + return url == u; + }; - var i = -1, definition; - while ((definition = definitions[++i])) { - if (definition.match(method, url, data, headers || {})) { - if (definition.response) { - // if $browser specified, we do auto flush all requests - ($browser ? $browser.defer : responsesPush)(wrapResponse(definition)); - } else if (definition.passThrough) { - $delegate(method, url, data, callback, headers, timeout, withCredentials); - } else throw new Error('No response defined !'); - return; - } - } - throw wasExpected ? - new Error('No response defined !') : - new Error('Unexpected request: ' + method + ' ' + url + '\n' + - (expectation ? 'Expected ' + expectation : 'No more request expected')); - } + this.matchHeaders = function (h) { + if (angular.isUndefined(headers)) return true; + if (angular.isFunction(headers)) return headers(h); + return angular.equals(headers, h); + }; - /** - * @ngdoc method - * @name ngMock.$httpBackend#when - * @methodOf ngMock.$httpBackend - * @description - * Creates a new backend definition. - * - * @param {string} method HTTP method. - * @param {string|RegExp} url HTTP url. - * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives - * data string and returns true if the data is as expected. - * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header - * object and returns true if the headers match the current definition. - * @returns {requestHandler} Returns an object with `respond` method that controls how a matched - * request is handled. - * - * - respond – - * `{function([status,] data[, headers])|function(function(method, url, data, headers)}` - * – The respond method takes a set of static data to be returned or a function that can return - * an array containing response status (number), response data (string) and response headers - * (Object). - */ - $httpBackend.when = function(method, url, data, headers) { - var definition = new MockHttpExpectation(method, url, data, headers), - chain = { - respond: function(status, data, headers) { - definition.response = createResponse(status, data, headers); - } + this.matchData = function (d) { + if (angular.isUndefined(data)) return true; + if (data && angular.isFunction(data.test)) return data.test(d); + if (data && angular.isFunction(data)) return data(d); + if (data && !angular.isString(data)) return angular.equals(data, angular.fromJson(d)); + return data == d; }; - if ($browser) { - chain.passThrough = function() { - definition.passThrough = true; - }; + this.toString = function () { + return method + ' ' + url; + }; } - definitions.push(definition); - return chain; - }; - - /** - * @ngdoc method - * @name ngMock.$httpBackend#whenGET - * @methodOf ngMock.$httpBackend - * @description - * Creates a new backend definition for GET requests. For more info see `when()`. - * - * @param {string|RegExp} url HTTP url. - * @param {(Object|function(Object))=} headers HTTP headers. - * @returns {requestHandler} Returns an object with `respond` method that control how a matched - * request is handled. - */ - - /** - * @ngdoc method - * @name ngMock.$httpBackend#whenHEAD - * @methodOf ngMock.$httpBackend - * @description - * Creates a new backend definition for HEAD requests. For more info see `when()`. - * - * @param {string|RegExp} url HTTP url. - * @param {(Object|function(Object))=} headers HTTP headers. - * @returns {requestHandler} Returns an object with `respond` method that control how a matched - * request is handled. - */ - - /** - * @ngdoc method - * @name ngMock.$httpBackend#whenDELETE - * @methodOf ngMock.$httpBackend - * @description - * Creates a new backend definition for DELETE requests. For more info see `when()`. - * - * @param {string|RegExp} url HTTP url. - * @param {(Object|function(Object))=} headers HTTP headers. - * @returns {requestHandler} Returns an object with `respond` method that control how a matched - * request is handled. - */ - - /** - * @ngdoc method - * @name ngMock.$httpBackend#whenPOST - * @methodOf ngMock.$httpBackend - * @description - * Creates a new backend definition for POST requests. For more info see `when()`. - * - * @param {string|RegExp} url HTTP url. - * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives - * data string and returns true if the data is as expected. - * @param {(Object|function(Object))=} headers HTTP headers. - * @returns {requestHandler} Returns an object with `respond` method that control how a matched - * request is handled. - */ - - /** - * @ngdoc method - * @name ngMock.$httpBackend#whenPUT - * @methodOf ngMock.$httpBackend - * @description - * Creates a new backend definition for PUT requests. For more info see `when()`. - * - * @param {string|RegExp} url HTTP url. - * @param {(string|RegExp|function(string))=} data HTTP request body or function that receives - * data string and returns true if the data is as expected. - * @param {(Object|function(Object))=} headers HTTP headers. - * @returns {requestHandler} Returns an object with `respond` method that control how a matched - * request is handled. - */ - - /** - * @ngdoc method - * @name ngMock.$httpBackend#whenJSONP - * @methodOf ngMock.$httpBackend - * @description - * Creates a new backend definition for JSONP requests. For more info see `when()`. - * - * @param {string|RegExp} url HTTP url. - * @returns {requestHandler} Returns an object with `respond` method that control how a matched - * request is handled. - */ - createShortMethods('when'); - - - /** - * @ngdoc method - * @name ngMock.$httpBackend#expect - * @methodOf ngMock.$httpBackend - * @description - * Creates a new request expectation. - * - * @param {string} method HTTP method. - * @param {string|RegExp} url HTTP url. - * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that - * receives data string and returns true if the data is as expected, or Object if request body - * is in JSON format. - * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header - * object and returns true if the headers match the current expectation. - * @returns {requestHandler} Returns an object with `respond` method that control how a matched - * request is handled. - * - * - respond – - * `{function([status,] data[, headers])|function(function(method, url, data, headers)}` - * – The respond method takes a set of static data to be returned or a function that can return - * an array containing response status (number), response data (string) and response headers - * (Object). - */ - $httpBackend.expect = function(method, url, data, headers) { - var expectation = new MockHttpExpectation(method, url, data, headers); - expectations.push(expectation); - return { - respond: function(status, data, headers) { - expectation.response = createResponse(status, data, headers); - } - }; - }; - - - /** - * @ngdoc method - * @name ngMock.$httpBackend#expectGET - * @methodOf ngMock.$httpBackend - * @description - * Creates a new request expectation for GET requests. For more info see `expect()`. - * - * @param {string|RegExp} url HTTP url. - * @param {Object=} headers HTTP headers. - * @returns {requestHandler} Returns an object with `respond` method that control how a matched - * request is handled. See #expect for more info. - */ - - /** - * @ngdoc method - * @name ngMock.$httpBackend#expectHEAD - * @methodOf ngMock.$httpBackend - * @description - * Creates a new request expectation for HEAD requests. For more info see `expect()`. - * - * @param {string|RegExp} url HTTP url. - * @param {Object=} headers HTTP headers. - * @returns {requestHandler} Returns an object with `respond` method that control how a matched - * request is handled. - */ - - /** - * @ngdoc method - * @name ngMock.$httpBackend#expectDELETE - * @methodOf ngMock.$httpBackend - * @description - * Creates a new request expectation for DELETE requests. For more info see `expect()`. - * - * @param {string|RegExp} url HTTP url. - * @param {Object=} headers HTTP headers. - * @returns {requestHandler} Returns an object with `respond` method that control how a matched - * request is handled. - */ - - /** - * @ngdoc method - * @name ngMock.$httpBackend#expectPOST - * @methodOf ngMock.$httpBackend - * @description - * Creates a new request expectation for POST requests. For more info see `expect()`. - * - * @param {string|RegExp} url HTTP url. - * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that - * receives data string and returns true if the data is as expected, or Object if request body - * is in JSON format. - * @param {Object=} headers HTTP headers. - * @returns {requestHandler} Returns an object with `respond` method that control how a matched - * request is handled. - */ - - /** - * @ngdoc method - * @name ngMock.$httpBackend#expectPUT - * @methodOf ngMock.$httpBackend - * @description - * Creates a new request expectation for PUT requests. For more info see `expect()`. - * - * @param {string|RegExp} url HTTP url. - * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that - * receives data string and returns true if the data is as expected, or Object if request body - * is in JSON format. - * @param {Object=} headers HTTP headers. - * @returns {requestHandler} Returns an object with `respond` method that control how a matched - * request is handled. - */ - - /** - * @ngdoc method - * @name ngMock.$httpBackend#expectPATCH - * @methodOf ngMock.$httpBackend - * @description - * Creates a new request expectation for PATCH requests. For more info see `expect()`. - * - * @param {string|RegExp} url HTTP url. - * @param {(string|RegExp|function(string)|Object)=} data HTTP request body or function that - * receives data string and returns true if the data is as expected, or Object if request body - * is in JSON format. - * @param {Object=} headers HTTP headers. - * @returns {requestHandler} Returns an object with `respond` method that control how a matched - * request is handled. - */ - - /** - * @ngdoc method - * @name ngMock.$httpBackend#expectJSONP - * @methodOf ngMock.$httpBackend - * @description - * Creates a new request expectation for JSONP requests. For more info see `expect()`. - * - * @param {string|RegExp} url HTTP url. - * @returns {requestHandler} Returns an object with `respond` method that control how a matched - * request is handled. - */ - createShortMethods('expect'); - - - /** - * @ngdoc method - * @name ngMock.$httpBackend#flush - * @methodOf ngMock.$httpBackend - * @description - * Flushes all pending requests using the trained responses. - * - * @param {number=} count Number of responses to flush (in the order they arrived). If undefined, - * all pending requests will be flushed. If there are no pending requests when the flush method - * is called an exception is thrown (as this typically a sign of programming error). - */ - $httpBackend.flush = function(count) { - $rootScope.$digest(); - if (!responses.length) throw new Error('No pending request to flush !'); - - if (angular.isDefined(count)) { - while (count--) { - if (!responses.length) throw new Error('No more pending request to flush !'); - responses.shift()(); - } - } else { - while (responses.length) { - responses.shift()(); - } - } - $httpBackend.verifyNoOutstandingExpectation(); - }; - - - /** - * @ngdoc method - * @name ngMock.$httpBackend#verifyNoOutstandingExpectation - * @methodOf ngMock.$httpBackend - * @description - * Verifies that all of the requests defined via the `expect` api were made. If any of the - * requests were not made, verifyNoOutstandingExpectation throws an exception. - * - * Typically, you would call this method following each test case that asserts requests using an - * "afterEach" clause. - * - *
-   *   afterEach($httpBackend.verifyNoOutstandingExpectation);
-   * 
- */ - $httpBackend.verifyNoOutstandingExpectation = function() { - $rootScope.$digest(); - if (expectations.length) { - throw new Error('Unsatisfied requests: ' + expectations.join(', ')); - } - }; - - - /** - * @ngdoc method - * @name ngMock.$httpBackend#verifyNoOutstandingRequest - * @methodOf ngMock.$httpBackend - * @description - * Verifies that there are no outstanding requests that need to be flushed. - * - * Typically, you would call this method following each test case that asserts requests using an - * "afterEach" clause. - * - *
-   *   afterEach($httpBackend.verifyNoOutstandingRequest);
-   * 
- */ - $httpBackend.verifyNoOutstandingRequest = function() { - if (responses.length) { - throw new Error('Unflushed requests: ' + responses.length); + function createMockXhr() { + return new MockXhr(); } - }; - - - /** - * @ngdoc method - * @name ngMock.$httpBackend#resetExpectations - * @methodOf ngMock.$httpBackend - * @description - * Resets all request expectations, but preserves all backend definitions. Typically, you would - * call resetExpectations during a multiple-phase test when you want to reuse the same instance of - * $httpBackend mock. - */ - $httpBackend.resetExpectations = function() { - expectations.length = 0; - responses.length = 0; - }; - - return $httpBackend; - - - function createShortMethods(prefix) { - angular.forEach(['GET', 'DELETE', 'JSONP'], function(method) { - $httpBackend[prefix + method] = function(url, headers) { - return $httpBackend[prefix](method, url, undefined, headers); - }; - }); - angular.forEach(['PUT', 'POST', 'PATCH'], function(method) { - $httpBackend[prefix + method] = function(url, data, headers) { - return $httpBackend[prefix](method, url, data, headers); - }; - }); - } -} - -function MockHttpExpectation(method, url, data, headers) { - - this.data = data; - this.headers = headers; - - this.match = function(m, u, d, h) { - if (method != m) return false; - if (!this.matchUrl(u)) return false; - if (angular.isDefined(d) && !this.matchData(d)) return false; - if (angular.isDefined(h) && !this.matchHeaders(h)) return false; - return true; - }; - - this.matchUrl = function(u) { - if (!url) return true; - if (angular.isFunction(url.test)) return url.test(u); - return url == u; - }; - - this.matchHeaders = function(h) { - if (angular.isUndefined(headers)) return true; - if (angular.isFunction(headers)) return headers(h); - return angular.equals(headers, h); - }; - - this.matchData = function(d) { - if (angular.isUndefined(data)) return true; - if (data && angular.isFunction(data.test)) return data.test(d); - if (data && angular.isFunction(data)) return data(d); - if (data && !angular.isString(data)) return angular.equals(data, angular.fromJson(d)); - return data == d; - }; - - this.toString = function() { - return method + ' ' + url; - }; -} - -function createMockXhr() { - return new MockXhr(); -} - -function MockXhr() { - - // hack for testing $http, $httpBackend - MockXhr.$$lastInstance = this; - - this.open = function(method, url, async) { - this.$$method = method; - this.$$url = url; - this.$$async = async; - this.$$reqHeaders = {}; - this.$$respHeaders = {}; - }; - - this.send = function(data) { - this.$$data = data; - }; - - this.setRequestHeader = function(key, value) { - this.$$reqHeaders[key] = value; - }; - - this.getResponseHeader = function(name) { - // the lookup must be case insensitive, - // that's why we try two quick lookups first and full scan last - var header = this.$$respHeaders[name]; - if (header) return header; - - name = angular.lowercase(name); - header = this.$$respHeaders[name]; - if (header) return header; - - header = undefined; - angular.forEach(this.$$respHeaders, function(headerVal, headerName) { - if (!header && angular.lowercase(headerName) == name) header = headerVal; - }); - return header; - }; + function MockXhr() { - this.getAllResponseHeaders = function() { - var lines = []; + // hack for testing $http, $httpBackend + MockXhr.$$lastInstance = this; - angular.forEach(this.$$respHeaders, function(value, key) { - lines.push(key + ': ' + value); - }); - return lines.join('\n'); - }; + this.open = function (method, url, async) { + this.$$method = method; + this.$$url = url; + this.$$async = async; + this.$$reqHeaders = {}; + this.$$respHeaders = {}; + }; - this.abort = angular.noop; -} + this.send = function (data) { + this.$$data = data; + }; + this.setRequestHeader = function (key, value) { + this.$$reqHeaders[key] = value; + }; -/** - * @ngdoc function - * @name ngMock.$timeout - * @description - * - * This service is just a simple decorator for {@link ng.$timeout $timeout} service - * that adds a "flush" and "verifyNoPendingTasks" methods. - */ + this.getResponseHeader = function (name) { + // the lookup must be case insensitive, + // that's why we try two quick lookups first and full scan last + var header = this.$$respHeaders[name]; + if (header) return header; + + name = angular.lowercase(name); + header = this.$$respHeaders[name]; + if (header) return header; + + header = undefined; + angular.forEach(this.$$respHeaders, function (headerVal, headerName) { + if (!header && angular.lowercase(headerName) == name) header = headerVal; + }); + return header; + }; + + this.getAllResponseHeaders = function () { + var lines = []; -angular.mock.$TimeoutDecorator = function($delegate, $browser) { - - /** - * @ngdoc method - * @name ngMock.$timeout#flush - * @methodOf ngMock.$timeout - * @description - * - * Flushes the queue of pending tasks. - * - * @param {number=} delay maximum timeout amount to flush up until - */ - $delegate.flush = function(delay) { - $browser.defer.flush(delay); - }; - - /** - * @ngdoc method - * @name ngMock.$timeout#verifyNoPendingTasks - * @methodOf ngMock.$timeout - * @description - * - * Verifies that there are no pending tasks that need to be flushed. - */ - $delegate.verifyNoPendingTasks = function() { - if ($browser.deferredFns.length) { - throw new Error('Deferred tasks to flush (' + $browser.deferredFns.length + '): ' + - formatPendingTasksAsString($browser.deferredFns)); + angular.forEach(this.$$respHeaders, function (value, key) { + lines.push(key + ': ' + value); + }); + return lines.join('\n'); + }; + + this.abort = angular.noop; } - }; - function formatPendingTasksAsString(tasks) { - var result = []; - angular.forEach(tasks, function(task) { - result.push('{id: ' + task.id + ', ' + 'time: ' + task.time + '}'); - }); - return result.join(', '); - } + /** + * @ngdoc function + * @name ngMock.$timeout + * @description + * + * This service is just a simple decorator for {@link ng.$timeout $timeout} service + * that adds a "flush" and "verifyNoPendingTasks" methods. + */ - return $delegate; -}; + angular.mock.$TimeoutDecorator = function ($delegate, $browser) { -/** - * - */ -angular.mock.$RootElementProvider = function() { - this.$get = function() { - return angular.element('
'); - }; -}; + /** + * @ngdoc method + * @name ngMock.$timeout#flush + * @methodOf ngMock.$timeout + * @description + * + * Flushes the queue of pending tasks. + * + * @param {number=} delay maximum timeout amount to flush up until + */ + $delegate.flush = function (delay) { + $browser.defer.flush(delay); + }; -/** - * @ngdoc overview - * @name ngMock - * @description - * - * # ngMock - * - * The `ngMock` module providers support to inject and mock Angular services into unit tests. - * In addition, ngMock also extends various core ng services such that they can be - * inspected and controlled in a synchronous manner within test code. - * - * {@installModule mock} - * - *
- * - */ -angular.module('ngMock', ['ng']).provider({ - $browser: angular.mock.$BrowserProvider, - $exceptionHandler: angular.mock.$ExceptionHandlerProvider, - $log: angular.mock.$LogProvider, - $interval: angular.mock.$IntervalProvider, - $httpBackend: angular.mock.$HttpBackendProvider, - $rootElement: angular.mock.$RootElementProvider -}).config(['$provide', function($provide) { - $provide.decorator('$timeout', angular.mock.$TimeoutDecorator); -}]); + /** + * @ngdoc method + * @name ngMock.$timeout#verifyNoPendingTasks + * @methodOf ngMock.$timeout + * @description + * + * Verifies that there are no pending tasks that need to be flushed. + */ + $delegate.verifyNoPendingTasks = function () { + if ($browser.deferredFns.length) { + throw new Error('Deferred tasks to flush (' + $browser.deferredFns.length + '): ' + + formatPendingTasksAsString($browser.deferredFns)); + } + }; -/** - * @ngdoc overview - * @name ngMockE2E - * @description - * - * The `ngMockE2E` is an angular module which contains mocks suitable for end-to-end testing. - * Currently there is only one mock present in this module - - * the {@link ngMockE2E.$httpBackend e2e $httpBackend} mock. - */ -angular.module('ngMockE2E', ['ng']).config(['$provide', function($provide) { - $provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator); -}]); + function formatPendingTasksAsString(tasks) { + var result = []; + angular.forEach(tasks, function (task) { + result.push('{id: ' + task.id + ', ' + 'time: ' + task.time + '}'); + }); -/** - * @ngdoc object - * @name ngMockE2E.$httpBackend - * @description - * Fake HTTP backend implementation suitable for end-to-end testing or backend-less development of - * applications that use the {@link ng.$http $http service}. - * - * *Note*: For fake http backend implementation suitable for unit testing please see - * {@link ngMock.$httpBackend unit-testing $httpBackend mock}. - * - * This implementation can be used to respond with static or dynamic responses via the `when` api - * and its shortcuts (`whenGET`, `whenPOST`, etc) and optionally pass through requests to the - * real $httpBackend for specific requests (e.g. to interact with certain remote apis or to fetch - * templates from a webserver). - * - * As opposed to unit-testing, in an end-to-end testing scenario or in scenario when an application - * is being developed with the real backend api replaced with a mock, it is often desirable for - * certain category of requests to bypass the mock and issue a real http request (e.g. to fetch - * templates or static files from the webserver). To configure the backend with this behavior - * use the `passThrough` request handler of `when` instead of `respond`. - * - * Additionally, we don't want to manually have to flush mocked out requests like we do during unit - * testing. For this reason the e2e $httpBackend automatically flushes mocked out requests - * automatically, closely simulating the behavior of the XMLHttpRequest object. - * - * To setup the application to run with this http backend, you have to create a module that depends - * on the `ngMockE2E` and your application modules and defines the fake backend: - * - *
- *   myAppDev = angular.module('myAppDev', ['myApp', 'ngMockE2E']);
- *   myAppDev.run(function($httpBackend) {
- *     phones = [{name: 'phone1'}, {name: 'phone2'}];
- *
- *     // returns the current list of phones
- *     $httpBackend.whenGET('/phones').respond(phones);
- *
- *     // adds a new phone to the phones array
- *     $httpBackend.whenPOST('/phones').respond(function(method, url, data) {
- *       phones.push(angular.fromJson(data));
- *     });
- *     $httpBackend.whenGET(/^\/templates\//).passThrough();
- *     //...
- *   });
- * 
- * - * Afterwards, bootstrap your app with this new module. - */ + return result.join(', '); + } -/** - * @ngdoc method - * @name ngMockE2E.$httpBackend#when - * @methodOf ngMockE2E.$httpBackend - * @description - * Creates a new backend definition. - * - * @param {string} method HTTP method. - * @param {string|RegExp} url HTTP url. - * @param {(string|RegExp)=} data HTTP request body. - * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header - * object and returns true if the headers match the current definition. - * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that - * control how a matched request is handled. - * - * - respond – - * `{function([status,] data[, headers])|function(function(method, url, data, headers)}` - * – The respond method takes a set of static data to be returned or a function that can return - * an array containing response status (number), response data (string) and response headers - * (Object). - * - passThrough – `{function()}` – Any request matching a backend definition with `passThrough` - * handler, will be pass through to the real backend (an XHR request will be made to the - * server. - */ + return $delegate; + }; -/** - * @ngdoc method - * @name ngMockE2E.$httpBackend#whenGET - * @methodOf ngMockE2E.$httpBackend - * @description - * Creates a new backend definition for GET requests. For more info see `when()`. - * - * @param {string|RegExp} url HTTP url. - * @param {(Object|function(Object))=} headers HTTP headers. - * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that - * control how a matched request is handled. - */ + /** + * + */ + angular.mock.$RootElementProvider = function () { + this.$get = function () { + return angular.element('
'); + }; + }; -/** - * @ngdoc method - * @name ngMockE2E.$httpBackend#whenHEAD - * @methodOf ngMockE2E.$httpBackend - * @description - * Creates a new backend definition for HEAD requests. For more info see `when()`. - * - * @param {string|RegExp} url HTTP url. - * @param {(Object|function(Object))=} headers HTTP headers. - * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that - * control how a matched request is handled. - */ + /** + * @ngdoc overview + * @name ngMock + * @description + * + * # ngMock + * + * The `ngMock` module providers support to inject and mock Angular services into unit tests. + * In addition, ngMock also extends various core ng services such that they can be + * inspected and controlled in a synchronous manner within test code. + * + * {@installModule mock} + * + *
+ * + */ + angular.module('ngMock', ['ng']).provider({ + $browser: angular.mock.$BrowserProvider, + $exceptionHandler: angular.mock.$ExceptionHandlerProvider, + $log: angular.mock.$LogProvider, + $interval: angular.mock.$IntervalProvider, + $httpBackend: angular.mock.$HttpBackendProvider, + $rootElement: angular.mock.$RootElementProvider + }).config(['$provide', function ($provide) { + $provide.decorator('$timeout', angular.mock.$TimeoutDecorator); + }]); -/** - * @ngdoc method - * @name ngMockE2E.$httpBackend#whenDELETE - * @methodOf ngMockE2E.$httpBackend - * @description - * Creates a new backend definition for DELETE requests. For more info see `when()`. - * - * @param {string|RegExp} url HTTP url. - * @param {(Object|function(Object))=} headers HTTP headers. - * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that - * control how a matched request is handled. - */ + /** + * @ngdoc overview + * @name ngMockE2E + * @description + * + * The `ngMockE2E` is an angular module which contains mocks suitable for end-to-end testing. + * Currently there is only one mock present in this module - + * the {@link ngMockE2E.$httpBackend e2e $httpBackend} mock. + */ + angular.module('ngMockE2E', ['ng']).config(['$provide', function ($provide) { + $provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator); + }]); -/** - * @ngdoc method - * @name ngMockE2E.$httpBackend#whenPOST - * @methodOf ngMockE2E.$httpBackend - * @description - * Creates a new backend definition for POST requests. For more info see `when()`. - * - * @param {string|RegExp} url HTTP url. - * @param {(string|RegExp)=} data HTTP request body. - * @param {(Object|function(Object))=} headers HTTP headers. - * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that - * control how a matched request is handled. - */ + /** + * @ngdoc object + * @name ngMockE2E.$httpBackend + * @description + * Fake HTTP backend implementation suitable for end-to-end testing or backend-less development of + * applications that use the {@link ng.$http $http service}. + * + * *Note*: For fake http backend implementation suitable for unit testing please see + * {@link ngMock.$httpBackend unit-testing $httpBackend mock}. + * + * This implementation can be used to respond with static or dynamic responses via the `when` api + * and its shortcuts (`whenGET`, `whenPOST`, etc) and optionally pass through requests to the + * real $httpBackend for specific requests (e.g. to interact with certain remote apis or to fetch + * templates from a webserver). + * + * As opposed to unit-testing, in an end-to-end testing scenario or in scenario when an application + * is being developed with the real backend api replaced with a mock, it is often desirable for + * certain category of requests to bypass the mock and issue a real http request (e.g. to fetch + * templates or static files from the webserver). To configure the backend with this behavior + * use the `passThrough` request handler of `when` instead of `respond`. + * + * Additionally, we don't want to manually have to flush mocked out requests like we do during unit + * testing. For this reason the e2e $httpBackend automatically flushes mocked out requests + * automatically, closely simulating the behavior of the XMLHttpRequest object. + * + * To setup the application to run with this http backend, you have to create a module that depends + * on the `ngMockE2E` and your application modules and defines the fake backend: + * + *
+     *   myAppDev = angular.module('myAppDev', ['myApp', 'ngMockE2E']);
+     *   myAppDev.run(function($httpBackend) {
+     *     phones = [{name: 'phone1'}, {name: 'phone2'}];
+     *
+     *     // returns the current list of phones
+     *     $httpBackend.whenGET('/phones').respond(phones);
+     *
+     *     // adds a new phone to the phones array
+     *     $httpBackend.whenPOST('/phones').respond(function(method, url, data) {
+     *       phones.push(angular.fromJson(data));
+     *     });
+     *     $httpBackend.whenGET(/^\/templates\//).passThrough();
+     *     //...
+     *   });
+     * 
+ * + * Afterwards, bootstrap your app with this new module. + */ -/** - * @ngdoc method - * @name ngMockE2E.$httpBackend#whenPUT - * @methodOf ngMockE2E.$httpBackend - * @description - * Creates a new backend definition for PUT requests. For more info see `when()`. - * - * @param {string|RegExp} url HTTP url. - * @param {(string|RegExp)=} data HTTP request body. - * @param {(Object|function(Object))=} headers HTTP headers. - * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that - * control how a matched request is handled. - */ + /** + * @ngdoc method + * @name ngMockE2E.$httpBackend#when + * @methodOf ngMockE2E.$httpBackend + * @description + * Creates a new backend definition. + * + * @param {string} method HTTP method. + * @param {string|RegExp} url HTTP url. + * @param {(string|RegExp)=} data HTTP request body. + * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header + * object and returns true if the headers match the current definition. + * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that + * control how a matched request is handled. + * + * - respond – + * `{function([status,] data[, headers])|function(function(method, url, data, headers)}` + * – The respond method takes a set of static data to be returned or a function that can return + * an array containing response status (number), response data (string) and response headers + * (Object). + * - passThrough – `{function()}` – Any request matching a backend definition with `passThrough` + * handler, will be pass through to the real backend (an XHR request will be made to the + * server. + */ -/** - * @ngdoc method - * @name ngMockE2E.$httpBackend#whenPATCH - * @methodOf ngMockE2E.$httpBackend - * @description - * Creates a new backend definition for PATCH requests. For more info see `when()`. - * - * @param {string|RegExp} url HTTP url. - * @param {(string|RegExp)=} data HTTP request body. - * @param {(Object|function(Object))=} headers HTTP headers. - * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that - * control how a matched request is handled. - */ + /** + * @ngdoc method + * @name ngMockE2E.$httpBackend#whenGET + * @methodOf ngMockE2E.$httpBackend + * @description + * Creates a new backend definition for GET requests. For more info see `when()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(Object|function(Object))=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that + * control how a matched request is handled. + */ -/** - * @ngdoc method - * @name ngMockE2E.$httpBackend#whenJSONP - * @methodOf ngMockE2E.$httpBackend - * @description - * Creates a new backend definition for JSONP requests. For more info see `when()`. - * - * @param {string|RegExp} url HTTP url. - * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that - * control how a matched request is handled. - */ -angular.mock.e2e = {}; -angular.mock.e2e.$httpBackendDecorator = - ['$rootScope', '$delegate', '$browser', createHttpBackendMock]; + /** + * @ngdoc method + * @name ngMockE2E.$httpBackend#whenHEAD + * @methodOf ngMockE2E.$httpBackend + * @description + * Creates a new backend definition for HEAD requests. For more info see `when()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(Object|function(Object))=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that + * control how a matched request is handled. + */ + /** + * @ngdoc method + * @name ngMockE2E.$httpBackend#whenDELETE + * @methodOf ngMockE2E.$httpBackend + * @description + * Creates a new backend definition for DELETE requests. For more info see `when()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(Object|function(Object))=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that + * control how a matched request is handled. + */ -angular.mock.clearDataCache = function() { - var key, - cache = angular.element.cache; + /** + * @ngdoc method + * @name ngMockE2E.$httpBackend#whenPOST + * @methodOf ngMockE2E.$httpBackend + * @description + * Creates a new backend definition for POST requests. For more info see `when()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(string|RegExp)=} data HTTP request body. + * @param {(Object|function(Object))=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that + * control how a matched request is handled. + */ - for(key in cache) { - if (Object.prototype.hasOwnProperty.call(cache,key)) { - var handle = cache[key].handle; + /** + * @ngdoc method + * @name ngMockE2E.$httpBackend#whenPUT + * @methodOf ngMockE2E.$httpBackend + * @description + * Creates a new backend definition for PUT requests. For more info see `when()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(string|RegExp)=} data HTTP request body. + * @param {(Object|function(Object))=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that + * control how a matched request is handled. + */ - handle && angular.element(handle.elem).off(); - delete cache[key]; - } - } -}; + /** + * @ngdoc method + * @name ngMockE2E.$httpBackend#whenPATCH + * @methodOf ngMockE2E.$httpBackend + * @description + * Creates a new backend definition for PATCH requests. For more info see `when()`. + * + * @param {string|RegExp} url HTTP url. + * @param {(string|RegExp)=} data HTTP request body. + * @param {(Object|function(Object))=} headers HTTP headers. + * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that + * control how a matched request is handled. + */ + + /** + * @ngdoc method + * @name ngMockE2E.$httpBackend#whenJSONP + * @methodOf ngMockE2E.$httpBackend + * @description + * Creates a new backend definition for JSONP requests. For more info see `when()`. + * + * @param {string|RegExp} url HTTP url. + * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that + * control how a matched request is handled. + */ + angular.mock.e2e = {}; + angular.mock.e2e.$httpBackendDecorator = + ['$rootScope', '$delegate', '$browser', createHttpBackendMock]; -if(window.jasmine || window.mocha) { + angular.mock.clearDataCache = function () { + var key, + cache = angular.element.cache; - var currentSpec = null, - isSpecRunning = function() { - return !!currentSpec; - }; + for (key in cache) { + if (Object.prototype.hasOwnProperty.call(cache, key)) { + var handle = cache[key].handle; + handle && angular.element(handle.elem).off(); + delete cache[key]; + } + } + }; - beforeEach(function() { - currentSpec = this; - }); - afterEach(function() { - var injector = currentSpec.$injector; + if (window.jasmine || window.mocha) { - currentSpec.$injector = null; - currentSpec.$modules = null; - currentSpec = null; + var currentSpec = null, + isSpecRunning = function () { + return !!currentSpec; + }; - if (injector) { - injector.get('$rootElement').off(); - injector.get('$browser').pollFns.length = 0; - } - angular.mock.clearDataCache(); + beforeEach(function () { + currentSpec = this; + }); - // clean up jquery's fragment cache - angular.forEach(angular.element.fragments, function(val, key) { - delete angular.element.fragments[key]; - }); + afterEach(function () { + var injector = currentSpec.$injector; - MockXhr.$$lastInstance = null; + currentSpec.$injector = null; + currentSpec.$modules = null; + currentSpec = null; - angular.forEach(angular.callbacks, function(val, key) { - delete angular.callbacks[key]; - }); - angular.callbacks.counter = 0; - }); - - /** - * @ngdoc function - * @name angular.mock.module - * @description - * - * *NOTE*: This function is also published on window for easy access.
- * - * This function registers a module configuration code. It collects the configuration information - * which will be used when the injector is created by {@link angular.mock.inject inject}. - * - * See {@link angular.mock.inject inject} for usage example - * - * @param {...(string|Function|Object)} fns any number of modules which are represented as string - * aliases or as anonymous module initialization functions. The modules are used to - * configure the injector. The 'ng' and 'ngMock' modules are automatically loaded. If an - * object literal is passed they will be register as values in the module, the key being - * the module name and the value being what is returned. - */ - window.module = angular.mock.module = function() { - var moduleFns = Array.prototype.slice.call(arguments, 0); - return isSpecRunning() ? workFn() : workFn; - ///////////////////// - function workFn() { - if (currentSpec.$injector) { - throw new Error('Injector already created, can not register a module!'); - } else { - var modules = currentSpec.$modules || (currentSpec.$modules = []); - angular.forEach(moduleFns, function(module) { - if (angular.isObject(module) && !angular.isArray(module)) { - modules.push(function($provide) { - angular.forEach(module, function(value, key) { - $provide.value(key, value); - }); + if (injector) { + injector.get('$rootElement').off(); + injector.get('$browser').pollFns.length = 0; + } + + angular.mock.clearDataCache(); + + // clean up jquery's fragment cache + angular.forEach(angular.element.fragments, function (val, key) { + delete angular.element.fragments[key]; + }); + + MockXhr.$$lastInstance = null; + + angular.forEach(angular.callbacks, function (val, key) { + delete angular.callbacks[key]; }); - } else { - modules.push(module); - } + angular.callbacks.counter = 0; }); - } - } - }; - - /** - * @ngdoc function - * @name angular.mock.inject - * @description - * - * *NOTE*: This function is also published on window for easy access.
- * - * The inject function wraps a function into an injectable function. The inject() creates new - * instance of {@link AUTO.$injector $injector} per test, which is then used for - * resolving references. - * - * - * ## Resolving References (Underscore Wrapping) - * Often, we would like to inject a reference once, in a `beforeEach()` block and reuse this - * in multiple `it()` clauses. To be able to do this we must assign the reference to a variable - * that is declared in the scope of the `describe()` block. Since we would, most likely, want - * the variable to have the same name of the reference we have a problem, since the parameter - * to the `inject()` function would hide the outer variable. - * - * To help with this, the injected parameters can, optionally, be enclosed with underscores. - * These are ignored by the injector when the reference name is resolved. - * - * For example, the parameter `_myService_` would be resolved as the reference `myService`. - * Since it is available in the function body as _myService_, we can then assign it to a variable - * defined in an outer scope. - * - * ``` - * // Defined out reference variable outside - * var myService; - * - * // Wrap the parameter in underscores - * beforeEach( inject( function(_myService_){ - * myService = _myService_; - * })); - * - * // Use myService in a series of tests. - * it('makes use of myService', function() { - * myService.doStuff(); - * }); - * - * ``` - * - * See also {@link angular.mock.module angular.mock.module} - * - * ## Example - * Example of what a typical jasmine tests looks like with the inject method. - *
-   *
-   *   angular.module('myApplicationModule', [])
-   *       .value('mode', 'app')
-   *       .value('version', 'v1.0.1');
-   *
-   *
-   *   describe('MyApp', function() {
-   *
-   *     // You need to load modules that you want to test,
-   *     // it loads only the "ng" module by default.
-   *     beforeEach(module('myApplicationModule'));
-   *
-   *
-   *     // inject() is used to inject arguments of all given functions
-   *     it('should provide a version', inject(function(mode, version) {
-   *       expect(version).toEqual('v1.0.1');
-   *       expect(mode).toEqual('app');
-   *     }));
-   *
-   *
-   *     // The inject and module method can also be used inside of the it or beforeEach
-   *     it('should override a version and test the new version is injected', function() {
-   *       // module() takes functions or strings (module aliases)
-   *       module(function($provide) {
-   *         $provide.value('version', 'overridden'); // override version here
-   *       });
-   *
-   *       inject(function(version) {
-   *         expect(version).toEqual('overridden');
-   *       });
-   *     });
-   *   });
-   *
-   * 
- * - * @param {...Function} fns any number of functions which will be injected using the injector. - */ - - - - var ErrorAddingDeclarationLocationStack = function(e, errorForStack) { - this.message = e.message; - this.name = e.name; - if (e.line) this.line = e.line; - if (e.sourceId) this.sourceId = e.sourceId; - if (e.stack && errorForStack) - this.stack = e.stack + '\n' + errorForStack.stack; - if (e.stackArray) this.stackArray = e.stackArray; - }; - ErrorAddingDeclarationLocationStack.prototype.toString = Error.prototype.toString; - - window.inject = angular.mock.inject = function() { - var blockFns = Array.prototype.slice.call(arguments, 0); - var errorForStack = new Error('Declaration Location'); - return isSpecRunning() ? workFn.call(currentSpec) : workFn; - ///////////////////// - function workFn() { - var modules = currentSpec.$modules || []; - - modules.unshift('ngMock'); - modules.unshift('ng'); - var injector = currentSpec.$injector; - if (!injector) { - injector = currentSpec.$injector = angular.injector(modules); - } - for(var i = 0, ii = blockFns.length; i < ii; i++) { - try { - /* jshint -W040 *//* Jasmine explicitly provides a `this` object when calling functions */ - injector.invoke(blockFns[i] || angular.noop, this); - /* jshint +W040 */ - } catch (e) { - if (e.stack && errorForStack) { - throw new ErrorAddingDeclarationLocationStack(e, errorForStack); - } - throw e; - } finally { - errorForStack = null; - } - } + + /** + * @ngdoc function + * @name angular.mock.module + * @description + * + * *NOTE*: This function is also published on window for easy access.
+ * + * This function registers a module configuration code. It collects the configuration information + * which will be used when the injector is created by {@link angular.mock.inject inject}. + * + * See {@link angular.mock.inject inject} for usage example + * + * @param {...(string|Function|Object)} fns any number of modules which are represented as string + * aliases or as anonymous module initialization functions. The modules are used to + * configure the injector. The 'ng' and 'ngMock' modules are automatically loaded. If an + * object literal is passed they will be register as values in the module, the key being + * the module name and the value being what is returned. + */ + window.module = angular.mock.module = function () { + var moduleFns = Array.prototype.slice.call(arguments, 0); + return isSpecRunning() ? workFn() : workFn; + + ///////////////////// + function workFn() { + if (currentSpec.$injector) { + throw new Error('Injector already created, can not register a module!'); + } else { + var modules = currentSpec.$modules || (currentSpec.$modules = []); + angular.forEach(moduleFns, function (module) { + if (angular.isObject(module) && !angular.isArray(module)) { + modules.push(function ($provide) { + angular.forEach(module, function (value, key) { + $provide.value(key, value); + }); + }); + } else { + modules.push(module); + } + }); + } + } + }; + + /** + * @ngdoc function + * @name angular.mock.inject + * @description + * + * *NOTE*: This function is also published on window for easy access.
+ * + * The inject function wraps a function into an injectable function. The inject() creates new + * instance of {@link AUTO.$injector $injector} per test, which is then used for + * resolving references. + * + * + * ## Resolving References (Underscore Wrapping) + * Often, we would like to inject a reference once, in a `beforeEach()` block and reuse this + * in multiple `it()` clauses. To be able to do this we must assign the reference to a variable + * that is declared in the scope of the `describe()` block. Since we would, most likely, want + * the variable to have the same name of the reference we have a problem, since the parameter + * to the `inject()` function would hide the outer variable. + * + * To help with this, the injected parameters can, optionally, be enclosed with underscores. + * These are ignored by the injector when the reference name is resolved. + * + * For example, the parameter `_myService_` would be resolved as the reference `myService`. + * Since it is available in the function body as _myService_, we can then assign it to a variable + * defined in an outer scope. + * + * ``` + * // Defined out reference variable outside + * var myService; + * + * // Wrap the parameter in underscores + * beforeEach( inject( function(_myService_){ + * myService = _myService_; + * })); + * + * // Use myService in a series of tests. + * it('makes use of myService', function() { + * myService.doStuff(); + * }); + * + * ``` + * + * See also {@link angular.mock.module angular.mock.module} + * + * ## Example + * Example of what a typical jasmine tests looks like with the inject method. + *
+         *
+         *   angular.module('myApplicationModule', [])
+         *       .value('mode', 'app')
+         *       .value('version', 'v1.0.1');
+         *
+         *
+         *   describe('MyApp', function() {
+         *
+         *     // You need to load modules that you want to test,
+         *     // it loads only the "ng" module by default.
+         *     beforeEach(module('myApplicationModule'));
+         *
+         *
+         *     // inject() is used to inject arguments of all given functions
+         *     it('should provide a version', inject(function(mode, version) {
+         *       expect(version).toEqual('v1.0.1');
+         *       expect(mode).toEqual('app');
+         *     }));
+         *
+         *
+         *     // The inject and module method can also be used inside of the it or beforeEach
+         *     it('should override a version and test the new version is injected', function() {
+         *       // module() takes functions or strings (module aliases)
+         *       module(function($provide) {
+         *         $provide.value('version', 'overridden'); // override version here
+         *       });
+         *
+         *       inject(function(version) {
+         *         expect(version).toEqual('overridden');
+         *       });
+         *     });
+         *   });
+         *
+         * 
+ * + * @param {...Function} fns any number of functions which will be injected using the injector. + */ + + + + var ErrorAddingDeclarationLocationStack = function (e, errorForStack) { + this.message = e.message; + this.name = e.name; + if (e.line) this.line = e.line; + if (e.sourceId) this.sourceId = e.sourceId; + if (e.stack && errorForStack) + this.stack = e.stack + '\n' + errorForStack.stack; + if (e.stackArray) this.stackArray = e.stackArray; + }; + ErrorAddingDeclarationLocationStack.prototype.toString = Error.prototype.toString; + + window.inject = angular.mock.inject = function () { + var blockFns = Array.prototype.slice.call(arguments, 0); + var errorForStack = new Error('Declaration Location'); + return isSpecRunning() ? workFn.call(currentSpec) : workFn; + + ///////////////////// + function workFn() { + var modules = currentSpec.$modules || []; + + modules.unshift('ngMock'); + modules.unshift('ng'); + var injector = currentSpec.$injector; + if (!injector) { + injector = currentSpec.$injector = angular.injector(modules); + } + for (var i = 0, ii = blockFns.length; i < ii; i++) { + try { + /* jshint -W040 *//* Jasmine explicitly provides a `this` object when calling functions */ + injector.invoke(blockFns[i] || angular.noop, this); + /* jshint +W040 */ + } catch (e) { + if (e.stack && errorForStack) { + throw new ErrorAddingDeclarationLocationStack(e, errorForStack); + } + throw e; + } finally { + errorForStack = null; + } + } + } + }; } - }; -} -})(window, window.angular); \ No newline at end of file +})(window, window.angular); diff --git a/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-resource_1.2.13/angular-resource.js b/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-resource_1.2.13/angular-resource.js index 36b34b48453497c84fd1af4839aca9ec9cbf0310..62f1dcab30d168c7a1a924eb432e4e6c976199c7 100644 --- a/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-resource_1.2.13/angular-resource.js +++ b/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-resource_1.2.13/angular-resource.js @@ -3,218 +3,219 @@ * (c) 2010-2014 Google, Inc. http://angularjs.org * License: MIT */ -(function(window, angular, undefined) {'use strict'; +(function (window, angular, undefined) { + 'use strict'; -var $resourceMinErr = angular.$$minErr('$resource'); + var $resourceMinErr = angular.$$minErr('$resource'); // Helper functions and regex to lookup a dotted path on an object // stopping at undefined/null. The path must be composed of ASCII // identifiers (just like $parse) -var MEMBER_NAME_REGEX = /^(\.[a-zA-Z_$][0-9a-zA-Z_$]*)+$/; - -function isValidDottedPath(path) { - return (path != null && path !== '' && path !== 'hasOwnProperty' && - MEMBER_NAME_REGEX.test('.' + path)); -} - -function lookupDottedPath(obj, path) { - if (!isValidDottedPath(path)) { - throw $resourceMinErr('badmember', 'Dotted member path "@{0}" is invalid.', path); - } - var keys = path.split('.'); - for (var i = 0, ii = keys.length; i < ii && obj !== undefined; i++) { - var key = keys[i]; - obj = (obj !== null) ? obj[key] : undefined; - } - return obj; -} + var MEMBER_NAME_REGEX = /^(\.[a-zA-Z_$][0-9a-zA-Z_$]*)+$/; -/** - * Create a shallow copy of an object and clear other fields from the destination - */ -function shallowClearAndCopy(src, dst) { - dst = dst || {}; - - angular.forEach(dst, function(value, key){ - delete dst[key]; - }); + function isValidDottedPath(path) { + return (path != null && path !== '' && path !== 'hasOwnProperty' && + MEMBER_NAME_REGEX.test('.' + path)); + } - for (var key in src) { - if (src.hasOwnProperty(key) && !(key.charAt(0) === '$' && key.charAt(1) === '$')) { - dst[key] = src[key]; + function lookupDottedPath(obj, path) { + if (!isValidDottedPath(path)) { + throw $resourceMinErr('badmember', 'Dotted member path "@{0}" is invalid.', path); + } + var keys = path.split('.'); + for (var i = 0, ii = keys.length; i < ii && obj !== undefined; i++) { + var key = keys[i]; + obj = (obj !== null) ? obj[key] : undefined; + } + return obj; } - } - return dst; -} + /** + * Create a shallow copy of an object and clear other fields from the destination + */ + function shallowClearAndCopy(src, dst) { + dst = dst || {}; -/** - * @ngdoc overview - * @name ngResource - * @description - * - * # ngResource - * - * The `ngResource` module provides interaction support with RESTful services - * via the $resource service. - * - * {@installModule resource} - * - *
- * - * See {@link ngResource.$resource `$resource`} for usage. - */ + angular.forEach(dst, function (value, key) { + delete dst[key]; + }); -/** - * @ngdoc object - * @name ngResource.$resource - * @requires $http - * - * @description - * A factory which creates a resource object that lets you interact with - * [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources. - * - * The returned resource object has action methods which provide high-level behaviors without - * the need to interact with the low level {@link ng.$http $http} service. - * - * Requires the {@link ngResource `ngResource`} module to be installed. - * - * @param {string} url A parametrized URL template with parameters prefixed by `:` as in - * `/user/:username`. If you are using a URL with a port number (e.g. - * `http://example.com:8080/api`), it will be respected. - * - * If you are using a url with a suffix, just add the suffix, like this: - * `$resource('http://example.com/resource.json')` or `$resource('http://example.com/:id.json')` - * or even `$resource('http://example.com/resource/:resource_id.:format')` - * If the parameter before the suffix is empty, :resource_id in this case, then the `/.` will be - * collapsed down to a single `.`. If you need this sequence to appear and not collapse then you - * can escape it with `/\.`. - * - * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in - * `actions` methods. If any of the parameter value is a function, it will be executed every time - * when a param value needs to be obtained for a request (unless the param was overridden). - * - * Each key value in the parameter object is first bound to url template if present and then any - * excess keys are appended to the url search query after the `?`. - * - * Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in - * URL `/path/greet?salutation=Hello`. - * - * If the parameter value is prefixed with `@` then the value of that parameter is extracted from - * the data object (useful for non-GET operations). - * - * @param {Object.=} actions Hash with declaration of custom action that should extend the - * default set of resource actions. The declaration should be created in the format of {@link - * ng.$http#usage_parameters $http.config}: - * - * {action1: {method:?, params:?, isArray:?, headers:?, ...}, - * action2: {method:?, params:?, isArray:?, headers:?, ...}, - * ...} - * - * Where: - * - * - **`action`** – {string} – The name of action. This name becomes the name of the method on - * your resource object. - * - **`method`** – {string} – HTTP request method. Valid methods are: `GET`, `POST`, `PUT`, - * `DELETE`, and `JSONP`. - * - **`params`** – {Object=} – Optional set of pre-bound parameters for this action. If any of - * the parameter value is a function, it will be executed every time when a param value needs to - * be obtained for a request (unless the param was overridden). - * - **`url`** – {string} – action specific `url` override. The url templating is supported just - * like for the resource-level urls. - * - **`isArray`** – {boolean=} – If true then the returned object for this action is an array, - * see `returns` section. - * - **`transformRequest`** – - * `{function(data, headersGetter)|Array.}` – - * transform function or an array of such functions. The transform function takes the http - * request body and headers and returns its transformed (typically serialized) version. - * - **`transformResponse`** – - * `{function(data, headersGetter)|Array.}` – - * transform function or an array of such functions. The transform function takes the http - * response body and headers and returns its transformed (typically deserialized) version. - * - **`cache`** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the - * GET request, otherwise if a cache instance built with - * {@link ng.$cacheFactory $cacheFactory}, this cache will be used for - * caching. - * - **`timeout`** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise} that - * should abort the request when resolved. - * - **`withCredentials`** - `{boolean}` - whether to set the `withCredentials` flag on the - * XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5 + for (var key in src) { + if (src.hasOwnProperty(key) && !(key.charAt(0) === '$' && key.charAt(1) === '$')) { + dst[key] = src[key]; + } + } + + return dst; + } + + /** + * @ngdoc overview + * @name ngResource + * @description + * + * # ngResource + * + * The `ngResource` module provides interaction support with RESTful services + * via the $resource service. + * + * {@installModule resource} + * + *
+ * + * See {@link ngResource.$resource `$resource`} for usage. + */ + + /** + * @ngdoc object + * @name ngResource.$resource + * @requires $http + * + * @description + * A factory which creates a resource object that lets you interact with + * [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources. + * + * The returned resource object has action methods which provide high-level behaviors without + * the need to interact with the low level {@link ng.$http $http} service. + * + * Requires the {@link ngResource `ngResource`} module to be installed. + * + * @param {string} url A parametrized URL template with parameters prefixed by `:` as in + * `/user/:username`. If you are using a URL with a port number (e.g. + * `http://example.com:8080/api`), it will be respected. + * + * If you are using a url with a suffix, just add the suffix, like this: + * `$resource('http://example.com/resource.json')` or `$resource('http://example.com/:id.json')` + * or even `$resource('http://example.com/resource/:resource_id.:format')` + * If the parameter before the suffix is empty, :resource_id in this case, then the `/.` will be + * collapsed down to a single `.`. If you need this sequence to appear and not collapse then you + * can escape it with `/\.`. + * + * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in + * `actions` methods. If any of the parameter value is a function, it will be executed every time + * when a param value needs to be obtained for a request (unless the param was overridden). + * + * Each key value in the parameter object is first bound to url template if present and then any + * excess keys are appended to the url search query after the `?`. + * + * Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in + * URL `/path/greet?salutation=Hello`. + * + * If the parameter value is prefixed with `@` then the value of that parameter is extracted from + * the data object (useful for non-GET operations). + * + * @param {Object.=} actions Hash with declaration of custom action that should extend the + * default set of resource actions. The declaration should be created in the format of {@link + * ng.$http#usage_parameters $http.config}: + * + * {action1: {method:?, params:?, isArray:?, headers:?, ...}, + * action2: {method:?, params:?, isArray:?, headers:?, ...}, + * ...} + * + * Where: + * + * - **`action`** – {string} – The name of action. This name becomes the name of the method on + * your resource object. + * - **`method`** – {string} – HTTP request method. Valid methods are: `GET`, `POST`, `PUT`, + * `DELETE`, and `JSONP`. + * - **`params`** – {Object=} – Optional set of pre-bound parameters for this action. If any of + * the parameter value is a function, it will be executed every time when a param value needs to + * be obtained for a request (unless the param was overridden). + * - **`url`** – {string} – action specific `url` override. The url templating is supported just + * like for the resource-level urls. + * - **`isArray`** – {boolean=} – If true then the returned object for this action is an array, + * see `returns` section. + * - **`transformRequest`** – + * `{function(data, headersGetter)|Array.}` – + * transform function or an array of such functions. The transform function takes the http + * request body and headers and returns its transformed (typically serialized) version. + * - **`transformResponse`** – + * `{function(data, headersGetter)|Array.}` – + * transform function or an array of such functions. The transform function takes the http + * response body and headers and returns its transformed (typically deserialized) version. + * - **`cache`** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the + * GET request, otherwise if a cache instance built with + * {@link ng.$cacheFactory $cacheFactory}, this cache will be used for + * caching. + * - **`timeout`** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise} that + * should abort the request when resolved. + * - **`withCredentials`** - `{boolean}` - whether to set the `withCredentials` flag on the + * XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5 * requests with credentials} for more information. - * - **`responseType`** - `{string}` - see {@link - * https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType requestType}. - * - **`interceptor`** - `{Object=}` - The interceptor object has two optional methods - - * `response` and `responseError`. Both `response` and `responseError` interceptors get called - * with `http response` object. See {@link ng.$http $http interceptors}. - * - * @returns {Object} A resource "class" object with methods for the default set of resource actions - * optionally extended with custom `actions`. The default set contains these actions: - * - * { 'get': {method:'GET'}, - * 'save': {method:'POST'}, - * 'query': {method:'GET', isArray:true}, - * 'remove': {method:'DELETE'}, - * 'delete': {method:'DELETE'} }; - * - * Calling these methods invoke an {@link ng.$http} with the specified http method, - * destination and parameters. When the data is returned from the server then the object is an - * instance of the resource class. The actions `save`, `remove` and `delete` are available on it - * as methods with the `$` prefix. This allows you to easily perform CRUD operations (create, - * read, update, delete) on server-side data like this: - *
-        var User = $resource('/user/:userId', {userId:'@id'});
-        var user = User.get({userId:123}, function() {
+     *   - **`responseType`** - `{string}` - see {@link
+        *     https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType requestType}.
+     *   - **`interceptor`** - `{Object=}` - The interceptor object has two optional methods -
+     *     `response` and `responseError`. Both `response` and `responseError` interceptors get called
+     *     with `http response` object. See {@link ng.$http $http interceptors}.
+     *
+     * @returns {Object} A resource "class" object with methods for the default set of resource actions
+     *   optionally extended with custom `actions`. The default set contains these actions:
+     *
+     *       { 'get':    {method:'GET'},
+     *         'save':   {method:'POST'},
+     *         'query':  {method:'GET', isArray:true},
+     *         'remove': {method:'DELETE'},
+     *         'delete': {method:'DELETE'} };
+     *
+     *   Calling these methods invoke an {@link ng.$http} with the specified http method,
+     *   destination and parameters. When the data is returned from the server then the object is an
+     *   instance of the resource class. The actions `save`, `remove` and `delete` are available on it
+     *   as  methods with the `$` prefix. This allows you to easily perform CRUD operations (create,
+     *   read, update, delete) on server-side data like this:
+     *   
+     var User = $resource('/user/:userId', {userId:'@id'});
+     var user = User.get({userId:123}, function() {
           user.abc = true;
           user.$save();
         });
      
- * - * It is important to realize that invoking a $resource object method immediately returns an - * empty reference (object or array depending on `isArray`). Once the data is returned from the - * server the existing reference is populated with the actual data. This is a useful trick since - * usually the resource is assigned to a model which is then rendered by the view. Having an empty - * object results in no rendering, once the data arrives from the server then the object is - * populated with the data and the view automatically re-renders itself showing the new data. This - * means that in most cases one never has to write a callback function for the action methods. - * - * The action methods on the class object or instance object can be invoked with the following - * parameters: - * - * - HTTP GET "class" actions: `Resource.action([parameters], [success], [error])` - * - non-GET "class" actions: `Resource.action([parameters], postData, [success], [error])` - * - non-GET instance actions: `instance.$action([parameters], [success], [error])` - * - * Success callback is called with (value, responseHeaders) arguments. Error callback is called - * with (httpResponse) argument. - * - * Class actions return empty instance (with additional properties below). - * Instance actions return promise of the action. - * - * The Resource instances and collection have these additional properties: - * - * - `$promise`: the {@link ng.$q promise} of the original server interaction that created this - * instance or collection. - * - * On success, the promise is resolved with the same resource instance or collection object, - * updated with data from server. This makes it easy to use in - * {@link ngRoute.$routeProvider resolve section of $routeProvider.when()} to defer view - * rendering until the resource(s) are loaded. - * - * On failure, the promise is resolved with the {@link ng.$http http response} object, without - * the `resource` property. - * - * - `$resolved`: `true` after first server interaction is completed (either with success or - * rejection), `false` before that. Knowing if the Resource has been resolved is useful in - * data-binding. - * - * @example - * - * # Credit card resource - * - *
+     *
+     *   It is important to realize that invoking a $resource object method immediately returns an
+     *   empty reference (object or array depending on `isArray`). Once the data is returned from the
+     *   server the existing reference is populated with the actual data. This is a useful trick since
+     *   usually the resource is assigned to a model which is then rendered by the view. Having an empty
+     *   object results in no rendering, once the data arrives from the server then the object is
+     *   populated with the data and the view automatically re-renders itself showing the new data. This
+     *   means that in most cases one never has to write a callback function for the action methods.
+     *
+     *   The action methods on the class object or instance object can be invoked with the following
+     *   parameters:
+     *
+     *   - HTTP GET "class" actions: `Resource.action([parameters], [success], [error])`
+     *   - non-GET "class" actions: `Resource.action([parameters], postData, [success], [error])`
+     *   - non-GET instance actions:  `instance.$action([parameters], [success], [error])`
+     *
+     *   Success callback is called with (value, responseHeaders) arguments. Error callback is called
+     *   with (httpResponse) argument.
+     *
+     *   Class actions return empty instance (with additional properties below).
+     *   Instance actions return promise of the action.
+     *
+     *   The Resource instances and collection have these additional properties:
+     *
+     *   - `$promise`: the {@link ng.$q promise} of the original server interaction that created this
+     *     instance or collection.
+     *
+     *     On success, the promise is resolved with the same resource instance or collection object,
+     *     updated with data from server. This makes it easy to use in
+     *     {@link ngRoute.$routeProvider resolve section of $routeProvider.when()} to defer view
+     *     rendering until the resource(s) are loaded.
+     *
+     *     On failure, the promise is resolved with the {@link ng.$http http response} object, without
+     *     the `resource` property.
+     *
+     *   - `$resolved`: `true` after first server interaction is completed (either with success or
+     *      rejection), `false` before that. Knowing if the Resource has been resolved is useful in
+     *      data-binding.
+     *
+     * @example
+     *
+     * # Credit card resource
+     *
+     * 
      // Define CreditCard class
      var CreditCard = $resource('/user/:userId/card/:cardId',
-      {userId:123, cardId:'@id'}, {
+     {userId:123, cardId:'@id'}, {
        charge: {method:'POST', params:{charge:true}}
       });
 
@@ -244,30 +245,30 @@ function shallowClearAndCopy(src, dst) {
      // POST: /user/123/card {number:'0123', name:'Mike Smith'}
      // server returns: {id:789, number:'0123', name: 'Mike Smith'};
      expect(newCard.id).toEqual(789);
- * 
- * - * The object returned from this function execution is a resource "class" which has "static" method - * for each action in the definition. - * - * Calling these methods invoke `$http` on the `url` template with the given `method`, `params` and - * `headers`. - * When the data is returned from the server then the object is an instance of the resource type and - * all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD - * operations (create, read, update, delete) on server-side data. - -
+     * 
+ * + * The object returned from this function execution is a resource "class" which has "static" method + * for each action in the definition. + * + * Calling these methods invoke `$http` on the `url` template with the given `method`, `params` and + * `headers`. + * When the data is returned from the server then the object is an instance of the resource type and + * all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD + * operations (create, read, update, delete) on server-side data. + +
      var User = $resource('/user/:userId', {userId:'@id'});
      var user = User.get({userId:123}, function() {
        user.abc = true;
        user.$save();
      });
-   
- * - * It's worth noting that the success callback for `get`, `query` and other methods gets passed - * in the response that came from the server as well as $http header getter function, so one - * could rewrite the above example and get access to http headers as: - * -
+     
+ * + * It's worth noting that the success callback for `get`, `query` and other methods gets passed + * in the response that came from the server as well as $http header getter function, so one + * could rewrite the above example and get access to http headers as: + * +
      var User = $resource('/user/:userId', {userId:'@id'});
      User.get({userId:123}, function(u, getResponseHeaders){
        u.abc = true;
@@ -276,321 +277,317 @@ function shallowClearAndCopy(src, dst) {
          //putResponseHeaders => $http header getter
        });
      });
-   
- - * # Creating a custom 'PUT' request - * In this example we create a custom method on our resource to make a PUT request - *
- *		var app = angular.module('app', ['ngResource', 'ngRoute']);
- *
- *		// Some APIs expect a PUT request in the format URL/object/ID
- *		// Here we are creating an 'update' method 
- *		app.factory('Notes', ['$resource', function($resource) {
- *    return $resource('/notes/:id', null,
- *        {
- *            'update': { method:'PUT' }
- *        });
- *		}]);
- *
- *		// In our controller we get the ID from the URL using ngRoute and $routeParams
- *		// We pass in $routeParams and our Notes factory along with $scope
- *		app.controller('NotesCtrl', ['$scope', '$routeParams', 'Notes',
-                                      function($scope, $routeParams, Notes) {
- *    // First get a note object from the factory
- *    var note = Notes.get({ id:$routeParams.id });
- *    $id = note.id;
- *
- *    // Now call update passing in the ID first then the object you are updating
- *    Notes.update({ id:$id }, note);
- *
- *    // This will PUT /notes/ID with the note object in the request payload
- *		}]);
- * 
- */ -angular.module('ngResource', ['ng']). - factory('$resource', ['$http', '$q', function($http, $q) { - - var DEFAULT_ACTIONS = { - 'get': {method:'GET'}, - 'save': {method:'POST'}, - 'query': {method:'GET', isArray:true}, - 'remove': {method:'DELETE'}, - 'delete': {method:'DELETE'} - }; - var noop = angular.noop, - forEach = angular.forEach, - extend = angular.extend, - copy = angular.copy, - isFunction = angular.isFunction; - - /** - * We need our custom method because encodeURIComponent is too aggressive and doesn't follow - * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path - * segments: - * segment = *pchar - * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" - * pct-encoded = "%" HEXDIG HEXDIG - * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" - * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" - * / "*" / "+" / "," / ";" / "=" - */ - function encodeUriSegment(val) { - return encodeUriQuery(val, true). - replace(/%26/gi, '&'). - replace(/%3D/gi, '='). - replace(/%2B/gi, '+'); - } - +
- /** - * This method is intended for encoding *key* or *value* parts of query component. We need a - * custom method because encodeURIComponent is too aggressive and encodes stuff that doesn't - * have to be encoded per http://tools.ietf.org/html/rfc3986: - * query = *( pchar / "/" / "?" ) - * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" - * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" - * pct-encoded = "%" HEXDIG HEXDIG - * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" - * / "*" / "+" / "," / ";" / "=" + * # Creating a custom 'PUT' request + * In this example we create a custom method on our resource to make a PUT request + *
+     *        var app = angular.module('app', ['ngResource', 'ngRoute']);
+     *
+     *        // Some APIs expect a PUT request in the format URL/object/ID
+     *        // Here we are creating an 'update' method
+     *        app.factory('Notes', ['$resource', function($resource) {
+     *    return $resource('/notes/:id', null,
+     *        {
+     *            'update': { method:'PUT' }
+     *        });
+     *		}]);
+     *
+     *        // In our controller we get the ID from the URL using ngRoute and $routeParams
+     *        // We pass in $routeParams and our Notes factory along with $scope
+     *        app.controller('NotesCtrl', ['$scope', '$routeParams', 'Notes',
+     function($scope, $routeParams, Notes) {
+     *    // First get a note object from the factory
+     *    var note = Notes.get({ id:$routeParams.id });
+     *    $id = note.id;
+     *
+     *    // Now call update passing in the ID first then the object you are updating
+     *    Notes.update({ id:$id }, note);
+     *
+     *    // This will PUT /notes/ID with the note object in the request payload
+     *		}]);
+     * 
*/ - function encodeUriQuery(val, pctEncodeSpaces) { - return encodeURIComponent(val). - replace(/%40/gi, '@'). - replace(/%3A/gi, ':'). - replace(/%24/g, '$'). - replace(/%2C/gi, ','). - replace(/%20/g, (pctEncodeSpaces ? '%20' : '+')); - } - - function Route(template, defaults) { - this.template = template; - this.defaults = defaults || {}; - this.urlParams = {}; - } - - Route.prototype = { - setUrlParams: function(config, params, actionUrl) { - var self = this, - url = actionUrl || self.template, - val, - encodedVal; - - var urlParams = self.urlParams = {}; - forEach(url.split(/\W/), function(param){ - if (param === 'hasOwnProperty') { - throw $resourceMinErr('badname', "hasOwnProperty is not a valid parameter name."); - } - if (!(new RegExp("^\\d+$").test(param)) && param && - (new RegExp("(^|[^\\\\]):" + param + "(\\W|$)").test(url))) { - urlParams[param] = true; - } - }); - url = url.replace(/\\:/g, ':'); - - params = params || {}; - forEach(self.urlParams, function(_, urlParam){ - val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam]; - if (angular.isDefined(val) && val !== null) { - encodedVal = encodeUriSegment(val); - url = url.replace(new RegExp(":" + urlParam + "(\\W|$)", "g"), function(match, p1) { - return encodedVal + p1; - }); - } else { - url = url.replace(new RegExp("(\/?):" + urlParam + "(\\W|$)", "g"), function(match, - leadingSlashes, tail) { - if (tail.charAt(0) == '/') { - return tail; - } else { - return leadingSlashes + tail; - } - }); - } - }); - - // strip trailing slashes and set the url - url = url.replace(/\/+$/, '') || '/'; - // then replace collapse `/.` if found in the last URL path segment before the query - // E.g. `http://url.com/id./format?q=x` becomes `http://url.com/id.format?q=x` - url = url.replace(/\/\.(?=\w+($|\?))/, '.'); - // replace escaped `/\.` with `/.` - config.url = url.replace(/\/\\\./, '/.'); - - - // set params - delegate param encoding to $http - forEach(params, function(value, key){ - if (!self.urlParams[key]) { - config.params = config.params || {}; - config.params[key] = value; - } - }); - } - }; - - - function resourceFactory(url, paramDefaults, actions) { - var route = new Route(url); - - actions = extend({}, DEFAULT_ACTIONS, actions); + angular.module('ngResource', ['ng']).factory('$resource', ['$http', '$q', function ($http, $q) { + + var DEFAULT_ACTIONS = { + 'get': {method: 'GET'}, + 'save': {method: 'POST'}, + 'query': {method: 'GET', isArray: true}, + 'remove': {method: 'DELETE'}, + 'delete': {method: 'DELETE'} + }; + var noop = angular.noop, + forEach = angular.forEach, + extend = angular.extend, + copy = angular.copy, + isFunction = angular.isFunction; + + /** + * We need our custom method because encodeURIComponent is too aggressive and doesn't follow + * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path + * segments: + * segment = *pchar + * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + * pct-encoded = "%" HEXDIG HEXDIG + * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" + * / "*" / "+" / "," / ";" / "=" + */ + function encodeUriSegment(val) { + return encodeUriQuery(val, true).replace(/%26/gi, '&').replace(/%3D/gi, '=').replace(/%2B/gi, '+'); + } + + + /** + * This method is intended for encoding *key* or *value* parts of query component. We need a + * custom method because encodeURIComponent is too aggressive and encodes stuff that doesn't + * have to be encoded per http://tools.ietf.org/html/rfc3986: + * query = *( pchar / "/" / "?" ) + * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + * pct-encoded = "%" HEXDIG HEXDIG + * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" + * / "*" / "+" / "," / ";" / "=" + */ + function encodeUriQuery(val, pctEncodeSpaces) { + return encodeURIComponent(val).replace(/%40/gi, '@').replace(/%3A/gi, ':').replace(/%24/g, '$').replace(/%2C/gi, ',').replace(/%20/g, (pctEncodeSpaces ? '%20' : '+')); + } + + function Route(template, defaults) { + this.template = template; + this.defaults = defaults || {}; + this.urlParams = {}; + } + + Route.prototype = { + setUrlParams: function (config, params, actionUrl) { + var self = this, + url = actionUrl || self.template, + val, + encodedVal; + + var urlParams = self.urlParams = {}; + forEach(url.split(/\W/), function (param) { + if (param === 'hasOwnProperty') { + throw $resourceMinErr('badname', "hasOwnProperty is not a valid parameter name."); + } + if (!(new RegExp("^\\d+$").test(param)) && param && + (new RegExp("(^|[^\\\\]):" + param + "(\\W|$)").test(url))) { + urlParams[param] = true; + } + }); + url = url.replace(/\\:/g, ':'); + + params = params || {}; + forEach(self.urlParams, function (_, urlParam) { + val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam]; + if (angular.isDefined(val) && val !== null) { + encodedVal = encodeUriSegment(val); + url = url.replace(new RegExp(":" + urlParam + "(\\W|$)", "g"), function (match, p1) { + return encodedVal + p1; + }); + } else { + url = url.replace(new RegExp("(\/?):" + urlParam + "(\\W|$)", "g"), function (match, + leadingSlashes, tail) { + if (tail.charAt(0) == '/') { + return tail; + } else { + return leadingSlashes + tail; + } + }); + } + }); - function extractParams(data, actionParams){ - var ids = {}; - actionParams = extend({}, paramDefaults, actionParams); - forEach(actionParams, function(value, key){ - if (isFunction(value)) { value = value(); } - ids[key] = value && value.charAt && value.charAt(0) == '@' ? - lookupDottedPath(data, value.substr(1)) : value; - }); - return ids; - } - - function defaultResponseInterceptor(response) { - return response.resource; - } - - function Resource(value){ - shallowClearAndCopy(value || {}, this); - } - - forEach(actions, function(action, name) { - var hasBody = /^(POST|PUT|PATCH)$/i.test(action.method); - - Resource[name] = function(a1, a2, a3, a4) { - var params = {}, data, success, error; - - /* jshint -W086 */ /* (purposefully fall through case statements) */ - switch(arguments.length) { - case 4: - error = a4; - success = a3; - //fallthrough - case 3: - case 2: - if (isFunction(a2)) { - if (isFunction(a1)) { - success = a1; - error = a2; - break; - } - - success = a2; - error = a3; - //fallthrough - } else { - params = a1; - data = a2; - success = a3; - break; - } - case 1: - if (isFunction(a1)) success = a1; - else if (hasBody) data = a1; - else params = a1; - break; - case 0: break; - default: - throw $resourceMinErr('badargs', - "Expected up to 4 arguments [params, data, success, error], got {0} arguments", - arguments.length); - } - /* jshint +W086 */ /* (purposefully fall through case statements) */ - - var isInstanceCall = this instanceof Resource; - var value = isInstanceCall ? data : (action.isArray ? [] : new Resource(data)); - var httpConfig = {}; - var responseInterceptor = action.interceptor && action.interceptor.response || - defaultResponseInterceptor; - var responseErrorInterceptor = action.interceptor && action.interceptor.responseError || - undefined; - - forEach(action, function(value, key) { - if (key != 'params' && key != 'isArray' && key != 'interceptor') { - httpConfig[key] = copy(value); - } - }); - - if (hasBody) httpConfig.data = data; - route.setUrlParams(httpConfig, - extend({}, extractParams(data, action.params || {}), params), - action.url); - - var promise = $http(httpConfig).then(function(response) { - var data = response.data, - promise = value.$promise; - - if (data) { - // Need to convert action.isArray to boolean in case it is undefined - // jshint -W018 - if (angular.isArray(data) !== (!!action.isArray)) { - throw $resourceMinErr('badcfg', 'Error in resource configuration. Expected ' + - 'response to contain an {0} but got an {1}', - action.isArray?'array':'object', angular.isArray(data)?'array':'object'); - } - // jshint +W018 - if (action.isArray) { - value.length = 0; - forEach(data, function(item) { - value.push(new Resource(item)); + // strip trailing slashes and set the url + url = url.replace(/\/+$/, '') || '/'; + // then replace collapse `/.` if found in the last URL path segment before the query + // E.g. `http://url.com/id./format?q=x` becomes `http://url.com/id.format?q=x` + url = url.replace(/\/\.(?=\w+($|\?))/, '.'); + // replace escaped `/\.` with `/.` + config.url = url.replace(/\/\\\./, '/.'); + + + // set params - delegate param encoding to $http + forEach(params, function (value, key) { + if (!self.urlParams[key]) { + config.params = config.params || {}; + config.params[key] = value; + } }); - } else { - shallowClearAndCopy(data, value); - value.$promise = promise; - } } + }; - value.$resolved = true; - - response.resource = value; - - return response; - }, function(response) { - value.$resolved = true; - - (error||noop)(response); - - return $q.reject(response); - }); - promise = promise.then( - function(response) { - var value = responseInterceptor(response); - (success||noop)(value, response.headers); - return value; - }, - responseErrorInterceptor); + function resourceFactory(url, paramDefaults, actions) { + var route = new Route(url); - if (!isInstanceCall) { - // we are creating instance / collection - // - set the initial promise - // - return the instance / collection - value.$promise = promise; - value.$resolved = false; + actions = extend({}, DEFAULT_ACTIONS, actions); - return value; - } + function extractParams(data, actionParams) { + var ids = {}; + actionParams = extend({}, paramDefaults, actionParams); + forEach(actionParams, function (value, key) { + if (isFunction(value)) { + value = value(); + } + ids[key] = value && value.charAt && value.charAt(0) == '@' ? + lookupDottedPath(data, value.substr(1)) : value; + }); + return ids; + } - // instance call - return promise; - }; + function defaultResponseInterceptor(response) { + return response.resource; + } + function Resource(value) { + shallowClearAndCopy(value || {}, this); + } - Resource.prototype['$' + name] = function(params, success, error) { - if (isFunction(params)) { - error = success; success = params; params = {}; - } - var result = Resource[name].call(this, params, this, success, error); - return result.$promise || result; - }; - }); + forEach(actions, function (action, name) { + var hasBody = /^(POST|PUT|PATCH)$/i.test(action.method); + + Resource[name] = function (a1, a2, a3, a4) { + var params = {}, data, success, error; + + /* jshint -W086 */ /* (purposefully fall through case statements) */ + switch (arguments.length) { + case 4: + error = a4; + success = a3; + //fallthrough + case 3: + case 2: + if (isFunction(a2)) { + if (isFunction(a1)) { + success = a1; + error = a2; + break; + } + + success = a2; + error = a3; + //fallthrough + } else { + params = a1; + data = a2; + success = a3; + break; + } + case 1: + if (isFunction(a1)) success = a1; + else if (hasBody) data = a1; + else params = a1; + break; + case 0: + break; + default: + throw $resourceMinErr('badargs', + "Expected up to 4 arguments [params, data, success, error], got {0} arguments", + arguments.length); + } + /* jshint +W086 */ /* (purposefully fall through case statements) */ + + var isInstanceCall = this instanceof Resource; + var value = isInstanceCall ? data : (action.isArray ? [] : new Resource(data)); + var httpConfig = {}; + var responseInterceptor = action.interceptor && action.interceptor.response || + defaultResponseInterceptor; + var responseErrorInterceptor = action.interceptor && action.interceptor.responseError || + undefined; + + forEach(action, function (value, key) { + if (key != 'params' && key != 'isArray' && key != 'interceptor') { + httpConfig[key] = copy(value); + } + }); + + if (hasBody) httpConfig.data = data; + route.setUrlParams(httpConfig, + extend({}, extractParams(data, action.params || {}), params), + action.url); + + var promise = $http(httpConfig).then(function (response) { + var data = response.data, + promise = value.$promise; + + if (data) { + // Need to convert action.isArray to boolean in case it is undefined + // jshint -W018 + if (angular.isArray(data) !== (!!action.isArray)) { + throw $resourceMinErr('badcfg', 'Error in resource configuration. Expected ' + + 'response to contain an {0} but got an {1}', + action.isArray ? 'array' : 'object', angular.isArray(data) ? 'array' : 'object'); + } + // jshint +W018 + if (action.isArray) { + value.length = 0; + forEach(data, function (item) { + value.push(new Resource(item)); + }); + } else { + shallowClearAndCopy(data, value); + value.$promise = promise; + } + } + + value.$resolved = true; + + response.resource = value; + + return response; + }, function (response) { + value.$resolved = true; + + (error || noop)(response); + + return $q.reject(response); + }); + + promise = promise.then( + function (response) { + var value = responseInterceptor(response); + (success || noop)(value, response.headers); + return value; + }, + responseErrorInterceptor); + + if (!isInstanceCall) { + // we are creating instance / collection + // - set the initial promise + // - return the instance / collection + value.$promise = promise; + value.$resolved = false; + + return value; + } + + // instance call + return promise; + }; + + + Resource.prototype['$' + name] = function (params, success, error) { + if (isFunction(params)) { + error = success; + success = params; + params = {}; + } + var result = Resource[name].call(this, params, this, success, error); + return result.$promise || result; + }; + }); - Resource.bind = function(additionalParamDefaults){ - return resourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions); - }; + Resource.bind = function (additionalParamDefaults) { + return resourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions); + }; - return Resource; - } + return Resource; + } - return resourceFactory; - }]); + return resourceFactory; + }]); })(window, window.angular); diff --git a/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-resource_1.2.13/angular-resource.min.js.map b/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-resource_1.2.13/angular-resource.min.js.map index 90492df88bad63edee888622e361b3d4c17e2ef1..61a23d98734a2e23818d2cd4bcde360326e65d14 100644 --- a/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-resource_1.2.13/angular-resource.min.js.map +++ b/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-resource_1.2.13/angular-resource.min.js.map @@ -1,8 +1,109 @@ { -"version":3, -"file":"angular-resource.min.js", -"lineCount":12, -"mappings":"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", -"sources":["angular-resource.js"], -"names":["window","angular","undefined","shallowClearAndCopy","src","dst","forEach","value","key","hasOwnProperty","charAt","$resourceMinErr","$$minErr","MEMBER_NAME_REGEX","module","factory","$http","$q","Route","template","defaults","urlParams","resourceFactory","url","paramDefaults","actions","extractParams","data","actionParams","ids","extend","isFunction","path","test","keys","split","i","ii","length","obj","defaultResponseInterceptor","response","resource","Resource","route","DEFAULT_ACTIONS","action","name","hasBody","method","a1","a2","a3","a4","params","success","error","arguments","isInstanceCall","isArray","httpConfig","responseInterceptor","interceptor","responseErrorInterceptor","responseError","copy","setUrlParams","promise","then","$promise","item","push","$resolved","noop","reject","headers","prototype","result","call","bind","Resource.bind","additionalParamDefaults","config","actionUrl","self","val","encodedVal","param","RegExp","replace","_","urlParam","isDefined","encodeURIComponent","match","p1","leadingSlashes","tail"] + "version": 3, + "file": "angular-resource.min.js", + "lineCount": 12, + "mappings": "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", + "sources": [ + "angular-resource.js" + ], + "names": [ + "window", + "angular", + "undefined", + "shallowClearAndCopy", + "src", + "dst", + "forEach", + "value", + "key", + "hasOwnProperty", + "charAt", + "$resourceMinErr", + "$$minErr", + "MEMBER_NAME_REGEX", + "module", + "factory", + "$http", + "$q", + "Route", + "template", + "defaults", + "urlParams", + "resourceFactory", + "url", + "paramDefaults", + "actions", + "extractParams", + "data", + "actionParams", + "ids", + "extend", + "isFunction", + "path", + "test", + "keys", + "split", + "i", + "ii", + "length", + "obj", + "defaultResponseInterceptor", + "response", + "resource", + "Resource", + "route", + "DEFAULT_ACTIONS", + "action", + "name", + "hasBody", + "method", + "a1", + "a2", + "a3", + "a4", + "params", + "success", + "error", + "arguments", + "isInstanceCall", + "isArray", + "httpConfig", + "responseInterceptor", + "interceptor", + "responseErrorInterceptor", + "responseError", + "copy", + "setUrlParams", + "promise", + "then", + "$promise", + "item", + "push", + "$resolved", + "noop", + "reject", + "headers", + "prototype", + "result", + "call", + "bind", + "Resource.bind", + "additionalParamDefaults", + "config", + "actionUrl", + "self", + "val", + "encodedVal", + "param", + "RegExp", + "replace", + "_", + "urlParam", + "isDefined", + "encodeURIComponent", + "match", + "p1", + "leadingSlashes", + "tail" + ] } diff --git a/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-route_1.2.13/angular-route.js b/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-route_1.2.13/angular-route.js index 9bb5af108e0e1341ea81595cf744318b19e88a54..2f141574415cfa3c1306170f7ccee3555db4378d 100644 --- a/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-route_1.2.13/angular-route.js +++ b/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-route_1.2.13/angular-route.js @@ -3,315 +3,316 @@ * (c) 2010-2014 Google, Inc. http://angularjs.org * License: MIT */ -(function(window, angular, undefined) {'use strict'; - -/** - * @ngdoc overview - * @name ngRoute - * @description - * - * # ngRoute - * - * The `ngRoute` module provides routing and deeplinking services and directives for angular apps. - * - * ## Example - * See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`. - * - * {@installModule route} - * - *
- */ - /* global -ngRouteModule */ -var ngRouteModule = angular.module('ngRoute', ['ng']). - provider('$route', $RouteProvider); - -/** - * @ngdoc object - * @name ngRoute.$routeProvider - * @function - * - * @description - * - * Used for configuring routes. - * - * ## Example - * See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`. - * - * ## Dependencies - * Requires the {@link ngRoute `ngRoute`} module to be installed. - */ -function $RouteProvider(){ - function inherit(parent, extra) { - return angular.extend(new (angular.extend(function() {}, {prototype:parent}))(), extra); - } - - var routes = {}; - - /** - * @ngdoc method - * @name ngRoute.$routeProvider#when - * @methodOf ngRoute.$routeProvider - * - * @param {string} path Route path (matched against `$location.path`). If `$location.path` - * contains redundant trailing slash or is missing one, the route will still match and the - * `$location.path` will be updated to add or drop the trailing slash to exactly match the - * route definition. - * - * * `path` can contain named groups starting with a colon: e.g. `:name`. All characters up - * to the next slash are matched and stored in `$routeParams` under the given `name` - * when the route matches. - * * `path` can contain named groups starting with a colon and ending with a star: - * e.g.`:name*`. All characters are eagerly stored in `$routeParams` under the given `name` - * when the route matches. - * * `path` can contain optional named groups with a question mark: e.g.`:name?`. - * - * For example, routes like `/color/:color/largecode/:largecode*\/edit` will match - * `/color/brown/largecode/code/with/slashs/edit` and extract: - * - * * `color: brown` - * * `largecode: code/with/slashs`. - * - * - * @param {Object} route Mapping information to be assigned to `$route.current` on route - * match. - * - * Object properties: - * - * - `controller` – `{(string|function()=}` – Controller fn that should be associated with - * newly created scope or the name of a {@link angular.Module#controller registered - * controller} if passed as a string. - * - `controllerAs` – `{string=}` – A controller alias name. If present the controller will be - * published to scope under the `controllerAs` name. - * - `template` – `{string=|function()=}` – html template as a string or a function that - * returns an html template as a string which should be used by {@link - * ngRoute.directive:ngView ngView} or {@link ng.directive:ngInclude ngInclude} directives. - * This property takes precedence over `templateUrl`. - * - * If `template` is a function, it will be called with the following parameters: - * - * - `{Array.}` - route parameters extracted from the current - * `$location.path()` by applying the current route - * - * - `templateUrl` – `{string=|function()=}` – path or function that returns a path to an html - * template that should be used by {@link ngRoute.directive:ngView ngView}. - * - * If `templateUrl` is a function, it will be called with the following parameters: - * - * - `{Array.}` - route parameters extracted from the current - * `$location.path()` by applying the current route - * - * - `resolve` - `{Object.=}` - An optional map of dependencies which should - * be injected into the controller. If any of these dependencies are promises, the router - * will wait for them all to be resolved or one to be rejected before the controller is - * instantiated. - * If all the promises are resolved successfully, the values of the resolved promises are - * injected and {@link ngRoute.$route#$routeChangeSuccess $routeChangeSuccess} event is - * fired. If any of the promises are rejected the - * {@link ngRoute.$route#$routeChangeError $routeChangeError} event is fired. The map object - * is: - * - * - `key` – `{string}`: a name of a dependency to be injected into the controller. - * - `factory` - `{string|function}`: If `string` then it is an alias for a service. - * Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected} - * and the return value is treated as the dependency. If the result is a promise, it is - * resolved before its value is injected into the controller. Be aware that - * `ngRoute.$routeParams` will still refer to the previous route within these resolve - * functions. Use `$route.current.params` to access the new route parameters, instead. - * - * - `redirectTo` – {(string|function())=} – value to update - * {@link ng.$location $location} path with and trigger route redirection. - * - * If `redirectTo` is a function, it will be called with the following parameters: - * - * - `{Object.}` - route parameters extracted from the current - * `$location.path()` by applying the current route templateUrl. - * - `{string}` - current `$location.path()` - * - `{Object}` - current `$location.search()` - * - * The custom `redirectTo` function is expected to return a string which will be used - * to update `$location.path()` and `$location.search()`. - * - * - `[reloadOnSearch=true]` - {boolean=} - reload route when only `$location.search()` - * or `$location.hash()` changes. - * - * If the option is set to `false` and url in the browser changes, then - * `$routeUpdate` event is broadcasted on the root scope. - * - * - `[caseInsensitiveMatch=false]` - {boolean=} - match routes without being case sensitive - * - * If the option is set to `true`, then the particular route can be matched without being - * case sensitive - * - * @returns {Object} self - * - * @description - * Adds a new route definition to the `$route` service. - */ - this.when = function(path, route) { - routes[path] = angular.extend( - {reloadOnSearch: true}, - route, - path && pathRegExp(path, route) - ); - - // create redirection for trailing slashes - if (path) { - var redirectPath = (path[path.length-1] == '/') - ? path.substr(0, path.length-1) - : path +'/'; - - routes[redirectPath] = angular.extend( - {redirectTo: path}, - pathRegExp(redirectPath, route) - ); - } - - return this; - }; - - /** - * @param path {string} path - * @param opts {Object} options - * @return {?Object} - * - * @description - * Normalizes the given path, returning a regular expression - * and the original path. - * - * Inspired by pathRexp in visionmedia/express/lib/utils.js. - */ - function pathRegExp(path, opts) { - var insensitive = opts.caseInsensitiveMatch, - ret = { - originalPath: path, - regexp: path - }, - keys = ret.keys = []; - - path = path - .replace(/([().])/g, '\\$1') - .replace(/(\/)?:(\w+)([\?\*])?/g, function(_, slash, key, option){ - var optional = option === '?' ? option : null; - var star = option === '*' ? option : null; - keys.push({ name: key, optional: !!optional }); - slash = slash || ''; - return '' - + (optional ? '' : slash) - + '(?:' - + (optional ? slash : '') - + (star && '(.+?)' || '([^/]+)') - + (optional || '') - + ')' - + (optional || ''); - }) - .replace(/([\/$\*])/g, '\\$1'); - - ret.regexp = new RegExp('^' + path + '$', insensitive ? 'i' : ''); - return ret; - } - - /** - * @ngdoc method - * @name ngRoute.$routeProvider#otherwise - * @methodOf ngRoute.$routeProvider - * - * @description - * Sets route definition that will be used on route change when no other route definition - * is matched. - * - * @param {Object} params Mapping information to be assigned to `$route.current`. - * @returns {Object} self - */ - this.otherwise = function(params) { - this.when(null, params); - return this; - }; - - - this.$get = ['$rootScope', - '$location', - '$routeParams', - '$q', - '$injector', - '$http', - '$templateCache', - '$sce', - function($rootScope, $location, $routeParams, $q, $injector, $http, $templateCache, $sce) { +(function (window, angular, undefined) { + 'use strict'; /** - * @ngdoc object - * @name ngRoute.$route - * @requires $location - * @requires $routeParams + * @ngdoc overview + * @name ngRoute + * @description * - * @property {Object} current Reference to the current route definition. - * The route definition contains: + * # ngRoute * - * - `controller`: The controller constructor as define in route definition. - * - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for - * controller instantiation. The `locals` contain - * the resolved values of the `resolve` map. Additionally the `locals` also contain: + * The `ngRoute` module provides routing and deeplinking services and directives for angular apps. * - * - `$scope` - The current route scope. - * - `$template` - The current route template HTML. + * ## Example + * See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`. * - * @property {Array.} routes Array of all configured routes. + * {@installModule route} * - * @description - * `$route` is used for deep-linking URLs to controllers and views (HTML partials). - * It watches `$location.url()` and tries to map the path to an existing route definition. + *
+ */ + /* global -ngRouteModule */ + var ngRouteModule = angular.module('ngRoute', ['ng']).provider('$route', $RouteProvider); + + /** + * @ngdoc object + * @name ngRoute.$routeProvider + * @function * - * Requires the {@link ngRoute `ngRoute`} module to be installed. + * @description * - * You can define routes through {@link ngRoute.$routeProvider $routeProvider}'s API. + * Used for configuring routes. * - * The `$route` service is typically used in conjunction with the - * {@link ngRoute.directive:ngView `ngView`} directive and the - * {@link ngRoute.$routeParams `$routeParams`} service. + * ## Example + * See {@link ngRoute.$route#example $route} for an example of configuring and using `ngRoute`. * - * @example - This example shows how changing the URL hash causes the `$route` to match a route against the - URL, and the `ngView` pulls in the partial. - - Note that this example is using {@link ng.directive:script inlined templates} - to get it working on jsfiddle as well. - - - -
- Choose: - Moby | - Moby: Ch1 | - Gatsby | - Gatsby: Ch4 | - Scarlet Letter
- -
-
- -
$location.path() = {{$location.path()}}
-
$route.current.templateUrl = {{$route.current.templateUrl}}
-
$route.current.params = {{$route.current.params}}
-
$route.current.scope.name = {{$route.current.scope.name}}
-
$routeParams = {{$routeParams}}
-
-
- - - controller: {{name}}
- Book Id: {{params.bookId}}
-
- - - controller: {{name}}
- Book Id: {{params.bookId}}
- Chapter Id: {{params.chapterId}} -
- - - angular.module('ngViewExample', ['ngRoute']) - - .config(function($routeProvider, $locationProvider) { + * ## Dependencies + * Requires the {@link ngRoute `ngRoute`} module to be installed. + */ + function $RouteProvider() { + function inherit(parent, extra) { + return angular.extend(new (angular.extend(function () { + }, {prototype: parent}))(), extra); + } + + var routes = {}; + + /** + * @ngdoc method + * @name ngRoute.$routeProvider#when + * @methodOf ngRoute.$routeProvider + * + * @param {string} path Route path (matched against `$location.path`). If `$location.path` + * contains redundant trailing slash or is missing one, the route will still match and the + * `$location.path` will be updated to add or drop the trailing slash to exactly match the + * route definition. + * + * * `path` can contain named groups starting with a colon: e.g. `:name`. All characters up + * to the next slash are matched and stored in `$routeParams` under the given `name` + * when the route matches. + * * `path` can contain named groups starting with a colon and ending with a star: + * e.g.`:name*`. All characters are eagerly stored in `$routeParams` under the given `name` + * when the route matches. + * * `path` can contain optional named groups with a question mark: e.g.`:name?`. + * + * For example, routes like `/color/:color/largecode/:largecode*\/edit` will match + * `/color/brown/largecode/code/with/slashs/edit` and extract: + * + * * `color: brown` + * * `largecode: code/with/slashs`. + * + * + * @param {Object} route Mapping information to be assigned to `$route.current` on route + * match. + * + * Object properties: + * + * - `controller` – `{(string|function()=}` – Controller fn that should be associated with + * newly created scope or the name of a {@link angular.Module#controller registered + * controller} if passed as a string. + * - `controllerAs` – `{string=}` – A controller alias name. If present the controller will be + * published to scope under the `controllerAs` name. + * - `template` – `{string=|function()=}` – html template as a string or a function that + * returns an html template as a string which should be used by {@link + * ngRoute.directive:ngView ngView} or {@link ng.directive:ngInclude ngInclude} directives. + * This property takes precedence over `templateUrl`. + * + * If `template` is a function, it will be called with the following parameters: + * + * - `{Array.}` - route parameters extracted from the current + * `$location.path()` by applying the current route + * + * - `templateUrl` – `{string=|function()=}` – path or function that returns a path to an html + * template that should be used by {@link ngRoute.directive:ngView ngView}. + * + * If `templateUrl` is a function, it will be called with the following parameters: + * + * - `{Array.}` - route parameters extracted from the current + * `$location.path()` by applying the current route + * + * - `resolve` - `{Object.=}` - An optional map of dependencies which should + * be injected into the controller. If any of these dependencies are promises, the router + * will wait for them all to be resolved or one to be rejected before the controller is + * instantiated. + * If all the promises are resolved successfully, the values of the resolved promises are + * injected and {@link ngRoute.$route#$routeChangeSuccess $routeChangeSuccess} event is + * fired. If any of the promises are rejected the + * {@link ngRoute.$route#$routeChangeError $routeChangeError} event is fired. The map object + * is: + * + * - `key` – `{string}`: a name of a dependency to be injected into the controller. + * - `factory` - `{string|function}`: If `string` then it is an alias for a service. + * Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected} + * and the return value is treated as the dependency. If the result is a promise, it is + * resolved before its value is injected into the controller. Be aware that + * `ngRoute.$routeParams` will still refer to the previous route within these resolve + * functions. Use `$route.current.params` to access the new route parameters, instead. + * + * - `redirectTo` – {(string|function())=} – value to update + * {@link ng.$location $location} path with and trigger route redirection. + * + * If `redirectTo` is a function, it will be called with the following parameters: + * + * - `{Object.}` - route parameters extracted from the current + * `$location.path()` by applying the current route templateUrl. + * - `{string}` - current `$location.path()` + * - `{Object}` - current `$location.search()` + * + * The custom `redirectTo` function is expected to return a string which will be used + * to update `$location.path()` and `$location.search()`. + * + * - `[reloadOnSearch=true]` - {boolean=} - reload route when only `$location.search()` + * or `$location.hash()` changes. + * + * If the option is set to `false` and url in the browser changes, then + * `$routeUpdate` event is broadcasted on the root scope. + * + * - `[caseInsensitiveMatch=false]` - {boolean=} - match routes without being case sensitive + * + * If the option is set to `true`, then the particular route can be matched without being + * case sensitive + * + * @returns {Object} self + * + * @description + * Adds a new route definition to the `$route` service. + */ + this.when = function (path, route) { + routes[path] = angular.extend( + {reloadOnSearch: true}, + route, + path && pathRegExp(path, route) + ); + + // create redirection for trailing slashes + if (path) { + var redirectPath = (path[path.length - 1] == '/') + ? path.substr(0, path.length - 1) + : path + '/'; + + routes[redirectPath] = angular.extend( + {redirectTo: path}, + pathRegExp(redirectPath, route) + ); + } + + return this; + }; + + /** + * @param path {string} path + * @param opts {Object} options + * @return {?Object} + * + * @description + * Normalizes the given path, returning a regular expression + * and the original path. + * + * Inspired by pathRexp in visionmedia/express/lib/utils.js. + */ + function pathRegExp(path, opts) { + var insensitive = opts.caseInsensitiveMatch, + ret = { + originalPath: path, + regexp: path + }, + keys = ret.keys = []; + + path = path + .replace(/([().])/g, '\\$1') + .replace(/(\/)?:(\w+)([\?\*])?/g, function (_, slash, key, option) { + var optional = option === '?' ? option : null; + var star = option === '*' ? option : null; + keys.push({name: key, optional: !!optional}); + slash = slash || ''; + return '' + + (optional ? '' : slash) + + '(?:' + + (optional ? slash : '') + + (star && '(.+?)' || '([^/]+)') + + (optional || '') + + ')' + + (optional || ''); + }) + .replace(/([\/$\*])/g, '\\$1'); + + ret.regexp = new RegExp('^' + path + '$', insensitive ? 'i' : ''); + return ret; + } + + /** + * @ngdoc method + * @name ngRoute.$routeProvider#otherwise + * @methodOf ngRoute.$routeProvider + * + * @description + * Sets route definition that will be used on route change when no other route definition + * is matched. + * + * @param {Object} params Mapping information to be assigned to `$route.current`. + * @returns {Object} self + */ + this.otherwise = function (params) { + this.when(null, params); + return this; + }; + + + this.$get = ['$rootScope', + '$location', + '$routeParams', + '$q', + '$injector', + '$http', + '$templateCache', + '$sce', + function ($rootScope, $location, $routeParams, $q, $injector, $http, $templateCache, $sce) { + + /** + * @ngdoc object + * @name ngRoute.$route + * @requires $location + * @requires $routeParams + * + * @property {Object} current Reference to the current route definition. + * The route definition contains: + * + * - `controller`: The controller constructor as define in route definition. + * - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for + * controller instantiation. The `locals` contain + * the resolved values of the `resolve` map. Additionally the `locals` also contain: + * + * - `$scope` - The current route scope. + * - `$template` - The current route template HTML. + * + * @property {Array.} routes Array of all configured routes. + * + * @description + * `$route` is used for deep-linking URLs to controllers and views (HTML partials). + * It watches `$location.url()` and tries to map the path to an existing route definition. + * + * Requires the {@link ngRoute `ngRoute`} module to be installed. + * + * You can define routes through {@link ngRoute.$routeProvider $routeProvider}'s API. + * + * The `$route` service is typically used in conjunction with the + * {@link ngRoute.directive:ngView `ngView`} directive and the + * {@link ngRoute.$routeParams `$routeParams`} service. + * + * @example + This example shows how changing the URL hash causes the `$route` to match a route against the + URL, and the `ngView` pulls in the partial. + + Note that this example is using {@link ng.directive:script inlined templates} + to get it working on jsfiddle as well. + + + +
+ Choose: + Moby | + Moby: Ch1 | + Gatsby | + Gatsby: Ch4 | + Scarlet Letter
+ +
+
+ +
$location.path() = {{$location.path()}}
+
$route.current.templateUrl = {{$route.current.templateUrl}}
+
$route.current.params = {{$route.current.params}}
+
$route.current.scope.name = {{$route.current.scope.name}}
+
$routeParams = {{$routeParams}}
+
+
+ + + controller: {{name}}
+ Book Id: {{params.bookId}}
+
+ + + controller: {{name}}
+ Book Id: {{params.bookId}}
+ Chapter Id: {{params.chapterId}} +
+ + + angular.module('ngViewExample', ['ngRoute']) + + .config(function($routeProvider, $locationProvider) { $routeProvider.when('/Book/:bookId', { templateUrl: 'book.html', controller: BookCntl, @@ -333,25 +334,25 @@ function $RouteProvider(){ $locationProvider.html5Mode(true); }); - function MainCntl($scope, $route, $routeParams, $location) { + function MainCntl($scope, $route, $routeParams, $location) { $scope.$route = $route; $scope.$location = $location; $scope.$routeParams = $routeParams; } - function BookCntl($scope, $routeParams) { + function BookCntl($scope, $routeParams) { $scope.name = "BookCntl"; $scope.params = $routeParams; } - function ChapterCntl($scope, $routeParams) { + function ChapterCntl($scope, $routeParams) { $scope.name = "ChapterCntl"; $scope.params = $routeParams; } - + - - it('should load and compile correct template', function() { + + it('should load and compile correct template', function() { element(by.linkText('Moby: Ch1')).click(); var content = element(by.css('.doc-example-live [ng-view]')).getText(); expect(content).toMatch(/controller\: ChapterCntl/); @@ -364,361 +365,364 @@ function $RouteProvider(){ expect(content).toMatch(/controller\: BookCntl/); expect(content).toMatch(/Book Id\: Scarlet/); }); - -
- */ - - /** - * @ngdoc event - * @name ngRoute.$route#$routeChangeStart - * @eventOf ngRoute.$route - * @eventType broadcast on root scope - * @description - * Broadcasted before a route change. At this point the route services starts - * resolving all of the dependencies needed for the route change to occur. - * Typically this involves fetching the view template as well as any dependencies - * defined in `resolve` route property. Once all of the dependencies are resolved - * `$routeChangeSuccess` is fired. - * - * @param {Object} angularEvent Synthetic event object. - * @param {Route} next Future route information. - * @param {Route} current Current route information. - */ - - /** - * @ngdoc event - * @name ngRoute.$route#$routeChangeSuccess - * @eventOf ngRoute.$route - * @eventType broadcast on root scope - * @description - * Broadcasted after a route dependencies are resolved. - * {@link ngRoute.directive:ngView ngView} listens for the directive - * to instantiate the controller and render the view. - * - * @param {Object} angularEvent Synthetic event object. - * @param {Route} current Current route information. - * @param {Route|Undefined} previous Previous route information, or undefined if current is - * first route entered. - */ + + + */ + + /** + * @ngdoc event + * @name ngRoute.$route#$routeChangeStart + * @eventOf ngRoute.$route + * @eventType broadcast on root scope + * @description + * Broadcasted before a route change. At this point the route services starts + * resolving all of the dependencies needed for the route change to occur. + * Typically this involves fetching the view template as well as any dependencies + * defined in `resolve` route property. Once all of the dependencies are resolved + * `$routeChangeSuccess` is fired. + * + * @param {Object} angularEvent Synthetic event object. + * @param {Route} next Future route information. + * @param {Route} current Current route information. + */ + + /** + * @ngdoc event + * @name ngRoute.$route#$routeChangeSuccess + * @eventOf ngRoute.$route + * @eventType broadcast on root scope + * @description + * Broadcasted after a route dependencies are resolved. + * {@link ngRoute.directive:ngView ngView} listens for the directive + * to instantiate the controller and render the view. + * + * @param {Object} angularEvent Synthetic event object. + * @param {Route} current Current route information. + * @param {Route|Undefined} previous Previous route information, or undefined if current is + * first route entered. + */ + + /** + * @ngdoc event + * @name ngRoute.$route#$routeChangeError + * @eventOf ngRoute.$route + * @eventType broadcast on root scope + * @description + * Broadcasted if any of the resolve promises are rejected. + * + * @param {Object} angularEvent Synthetic event object + * @param {Route} current Current route information. + * @param {Route} previous Previous route information. + * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise. + */ + + /** + * @ngdoc event + * @name ngRoute.$route#$routeUpdate + * @eventOf ngRoute.$route + * @eventType broadcast on root scope + * @description + * + * The `reloadOnSearch` property has been set to false, and we are reusing the same + * instance of the Controller. + */ + + var forceReload = false, + $route = { + routes: routes, + + /** + * @ngdoc method + * @name ngRoute.$route#reload + * @methodOf ngRoute.$route + * + * @description + * Causes `$route` service to reload the current route even if + * {@link ng.$location $location} hasn't changed. + * + * As a result of that, {@link ngRoute.directive:ngView ngView} + * creates new scope, reinstantiates the controller. + */ + reload: function () { + forceReload = true; + $rootScope.$evalAsync(updateRoute); + } + }; + + $rootScope.$on('$locationChangeSuccess', updateRoute); + + return $route; + + ///////////////////////////////////////////////////// + + /** + * @param on {string} current url + * @param route {Object} route regexp to match the url against + * @return {?Object} + * + * @description + * Check if the route matches the current url. + * + * Inspired by match in + * visionmedia/express/lib/router/router.js. + */ + function switchRouteMatcher(on, route) { + var keys = route.keys, + params = {}; + + if (!route.regexp) return null; + + var m = route.regexp.exec(on); + if (!m) return null; + + for (var i = 1, len = m.length; i < len; ++i) { + var key = keys[i - 1]; + + var val = 'string' == typeof m[i] + ? decodeURIComponent(m[i]) + : m[i]; + + if (key && val) { + params[key.name] = val; + } + } + return params; + } - /** - * @ngdoc event - * @name ngRoute.$route#$routeChangeError - * @eventOf ngRoute.$route - * @eventType broadcast on root scope - * @description - * Broadcasted if any of the resolve promises are rejected. - * - * @param {Object} angularEvent Synthetic event object - * @param {Route} current Current route information. - * @param {Route} previous Previous route information. - * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise. - */ + function updateRoute() { + var next = parseRoute(), + last = $route.current; + + if (next && last && next.$$route === last.$$route + && angular.equals(next.pathParams, last.pathParams) + && !next.reloadOnSearch && !forceReload) { + last.params = next.params; + angular.copy(last.params, $routeParams); + $rootScope.$broadcast('$routeUpdate', last); + } else if (next || last) { + forceReload = false; + $rootScope.$broadcast('$routeChangeStart', next, last); + $route.current = next; + if (next) { + if (next.redirectTo) { + if (angular.isString(next.redirectTo)) { + $location.path(interpolate(next.redirectTo, next.params)).search(next.params) + .replace(); + } else { + $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search())) + .replace(); + } + } + } + + $q.when(next).then(function () { + if (next) { + var locals = angular.extend({}, next.resolve), + template, templateUrl; + + angular.forEach(locals, function (value, key) { + locals[key] = angular.isString(value) ? + $injector.get(value) : $injector.invoke(value); + }); + + if (angular.isDefined(template = next.template)) { + if (angular.isFunction(template)) { + template = template(next.params); + } + } else if (angular.isDefined(templateUrl = next.templateUrl)) { + if (angular.isFunction(templateUrl)) { + templateUrl = templateUrl(next.params); + } + templateUrl = $sce.getTrustedResourceUrl(templateUrl); + if (angular.isDefined(templateUrl)) { + next.loadedTemplateUrl = templateUrl; + template = $http.get(templateUrl, {cache: $templateCache}).then(function (response) { + return response.data; + }); + } + } + if (angular.isDefined(template)) { + locals['$template'] = template; + } + return $q.all(locals); + } + }). + // after route change + then(function (locals) { + if (next == $route.current) { + if (next) { + next.locals = locals; + angular.copy(next.params, $routeParams); + } + $rootScope.$broadcast('$routeChangeSuccess', next, last); + } + }, function (error) { + if (next == $route.current) { + $rootScope.$broadcast('$routeChangeError', next, last, error); + } + }); + } + } - /** - * @ngdoc event - * @name ngRoute.$route#$routeUpdate - * @eventOf ngRoute.$route - * @eventType broadcast on root scope - * @description - * - * The `reloadOnSearch` property has been set to false, and we are reusing the same - * instance of the Controller. - */ - var forceReload = false, - $route = { - routes: routes, - - /** - * @ngdoc method - * @name ngRoute.$route#reload - * @methodOf ngRoute.$route - * - * @description - * Causes `$route` service to reload the current route even if - * {@link ng.$location $location} hasn't changed. - * - * As a result of that, {@link ngRoute.directive:ngView ngView} - * creates new scope, reinstantiates the controller. - */ - reload: function() { - forceReload = true; - $rootScope.$evalAsync(updateRoute); - } - }; + /** + * @returns the current active route, by matching it against the URL + */ + function parseRoute() { + // Match a route + var params, match; + angular.forEach(routes, function (route, path) { + if (!match && (params = switchRouteMatcher($location.path(), route))) { + match = inherit(route, { + params: angular.extend({}, $location.search(), params), + pathParams: params + }); + match.$$route = route; + } + }); + // No route matched; fallback to "otherwise" route + return match || routes[null] && inherit(routes[null], {params: {}, pathParams: {}}); + } - $rootScope.$on('$locationChangeSuccess', updateRoute); + /** + * @returns interpolation of the redirect path with the parameters + */ + function interpolate(string, params) { + var result = []; + angular.forEach((string || '').split(':'), function (segment, i) { + if (i === 0) { + result.push(segment); + } else { + var segmentMatch = segment.match(/(\w+)(.*)/); + var key = segmentMatch[1]; + result.push(params[key]); + result.push(segmentMatch[2] || ''); + delete params[key]; + } + }); + return result.join(''); + } + }]; + } - return $route; + ngRouteModule.provider('$routeParams', $RouteParamsProvider); - ///////////////////////////////////////////////////// /** - * @param on {string} current url - * @param route {Object} route regexp to match the url against - * @return {?Object} + * @ngdoc object + * @name ngRoute.$routeParams + * @requires $route * * @description - * Check if the route matches the current url. + * The `$routeParams` service allows you to retrieve the current set of route parameters. + * + * Requires the {@link ngRoute `ngRoute`} module to be installed. + * + * The route parameters are a combination of {@link ng.$location `$location`}'s + * {@link ng.$location#methods_search `search()`} and {@link ng.$location#methods_path `path()`}. + * The `path` parameters are extracted when the {@link ngRoute.$route `$route`} path is matched. + * + * In case of parameter name collision, `path` params take precedence over `search` params. + * + * The service guarantees that the identity of the `$routeParams` object will remain unchanged + * (but its properties will likely change) even when a route change occurs. * - * Inspired by match in - * visionmedia/express/lib/router/router.js. + * Note that the `$routeParams` are only updated *after* a route change completes successfully. + * This means that you cannot rely on `$routeParams` being correct in route resolve functions. + * Instead you can use `$route.current.params` to access the new route's parameters. + * + * @example + *
+     *  // Given:
+     *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby
+     *  // Route: /Chapter/:chapterId/Section/:sectionId
+     *  //
+     *  // Then
+     *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}
+     * 
*/ - function switchRouteMatcher(on, route) { - var keys = route.keys, - params = {}; - - if (!route.regexp) return null; - - var m = route.regexp.exec(on); - if (!m) return null; - - for (var i = 1, len = m.length; i < len; ++i) { - var key = keys[i - 1]; - - var val = 'string' == typeof m[i] - ? decodeURIComponent(m[i]) - : m[i]; - - if (key && val) { - params[key.name] = val; - } - } - return params; - } - - function updateRoute() { - var next = parseRoute(), - last = $route.current; - - if (next && last && next.$$route === last.$$route - && angular.equals(next.pathParams, last.pathParams) - && !next.reloadOnSearch && !forceReload) { - last.params = next.params; - angular.copy(last.params, $routeParams); - $rootScope.$broadcast('$routeUpdate', last); - } else if (next || last) { - forceReload = false; - $rootScope.$broadcast('$routeChangeStart', next, last); - $route.current = next; - if (next) { - if (next.redirectTo) { - if (angular.isString(next.redirectTo)) { - $location.path(interpolate(next.redirectTo, next.params)).search(next.params) - .replace(); - } else { - $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search())) - .replace(); - } - } - } - - $q.when(next). - then(function() { - if (next) { - var locals = angular.extend({}, next.resolve), - template, templateUrl; - - angular.forEach(locals, function(value, key) { - locals[key] = angular.isString(value) ? - $injector.get(value) : $injector.invoke(value); - }); - - if (angular.isDefined(template = next.template)) { - if (angular.isFunction(template)) { - template = template(next.params); - } - } else if (angular.isDefined(templateUrl = next.templateUrl)) { - if (angular.isFunction(templateUrl)) { - templateUrl = templateUrl(next.params); - } - templateUrl = $sce.getTrustedResourceUrl(templateUrl); - if (angular.isDefined(templateUrl)) { - next.loadedTemplateUrl = templateUrl; - template = $http.get(templateUrl, {cache: $templateCache}). - then(function(response) { return response.data; }); - } - } - if (angular.isDefined(template)) { - locals['$template'] = template; - } - return $q.all(locals); - } - }). - // after route change - then(function(locals) { - if (next == $route.current) { - if (next) { - next.locals = locals; - angular.copy(next.params, $routeParams); - } - $rootScope.$broadcast('$routeChangeSuccess', next, last); - } - }, function(error) { - if (next == $route.current) { - $rootScope.$broadcast('$routeChangeError', next, last, error); - } - }); - } + function $RouteParamsProvider() { + this.$get = function () { + return {}; + }; } + ngRouteModule.directive('ngView', ngViewFactory); + ngRouteModule.directive('ngView', ngViewFillContentFactory); - /** - * @returns the current active route, by matching it against the URL - */ - function parseRoute() { - // Match a route - var params, match; - angular.forEach(routes, function(route, path) { - if (!match && (params = switchRouteMatcher($location.path(), route))) { - match = inherit(route, { - params: angular.extend({}, $location.search(), params), - pathParams: params}); - match.$$route = route; - } - }); - // No route matched; fallback to "otherwise" route - return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}}); - } /** - * @returns interpolation of the redirect path with the parameters - */ - function interpolate(string, params) { - var result = []; - angular.forEach((string||'').split(':'), function(segment, i) { - if (i === 0) { - result.push(segment); - } else { - var segmentMatch = segment.match(/(\w+)(.*)/); - var key = segmentMatch[1]; - result.push(params[key]); - result.push(segmentMatch[2] || ''); - delete params[key]; - } - }); - return result.join(''); - } - }]; -} - -ngRouteModule.provider('$routeParams', $RouteParamsProvider); - - -/** - * @ngdoc object - * @name ngRoute.$routeParams - * @requires $route - * - * @description - * The `$routeParams` service allows you to retrieve the current set of route parameters. - * - * Requires the {@link ngRoute `ngRoute`} module to be installed. - * - * The route parameters are a combination of {@link ng.$location `$location`}'s - * {@link ng.$location#methods_search `search()`} and {@link ng.$location#methods_path `path()`}. - * The `path` parameters are extracted when the {@link ngRoute.$route `$route`} path is matched. - * - * In case of parameter name collision, `path` params take precedence over `search` params. - * - * The service guarantees that the identity of the `$routeParams` object will remain unchanged - * (but its properties will likely change) even when a route change occurs. - * - * Note that the `$routeParams` are only updated *after* a route change completes successfully. - * This means that you cannot rely on `$routeParams` being correct in route resolve functions. - * Instead you can use `$route.current.params` to access the new route's parameters. - * - * @example - *
- *  // Given:
- *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby
- *  // Route: /Chapter/:chapterId/Section/:sectionId
- *  //
- *  // Then
- *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}
- * 
- */ -function $RouteParamsProvider() { - this.$get = function() { return {}; }; -} - -ngRouteModule.directive('ngView', ngViewFactory); -ngRouteModule.directive('ngView', ngViewFillContentFactory); - - -/** - * @ngdoc directive - * @name ngRoute.directive:ngView - * @restrict ECA - * - * @description - * # Overview - * `ngView` is a directive that complements the {@link ngRoute.$route $route} service by - * including the rendered template of the current route into the main layout (`index.html`) file. - * Every time the current route changes, the included view changes with it according to the - * configuration of the `$route` service. - * - * Requires the {@link ngRoute `ngRoute`} module to be installed. - * - * @animations - * enter - animation is used to bring new content into the browser. - * leave - animation is used to animate existing content away. - * - * The enter and leave animation occur concurrently. - * - * @scope - * @priority 400 - * @param {string=} onload Expression to evaluate whenever the view updates. - * - * @param {string=} autoscroll Whether `ngView` should call {@link ng.$anchorScroll + * @ngdoc directive + * @name ngRoute.directive:ngView + * @restrict ECA + * + * @description + * # Overview + * `ngView` is a directive that complements the {@link ngRoute.$route $route} service by + * including the rendered template of the current route into the main layout (`index.html`) file. + * Every time the current route changes, the included view changes with it according to the + * configuration of the `$route` service. + * + * Requires the {@link ngRoute `ngRoute`} module to be installed. + * + * @animations + * enter - animation is used to bring new content into the browser. + * leave - animation is used to animate existing content away. + * + * The enter and leave animation occur concurrently. + * + * @scope + * @priority 400 + * @param {string=} onload Expression to evaluate whenever the view updates. + * + * @param {string=} autoscroll Whether `ngView` should call {@link ng.$anchorScroll * $anchorScroll} to scroll the viewport after the view is updated. - * - * - If the attribute is not set, disable scrolling. - * - If the attribute is set without value, enable scrolling. - * - Otherwise enable scrolling only if the `autoscroll` attribute value evaluated - * as an expression yields a truthy value. - * @example - - -
- Choose: - Moby | - Moby: Ch1 | - Gatsby | - Gatsby: Ch4 | - Scarlet Letter
- -
-
-
-
- -
$location.path() = {{main.$location.path()}}
-
$route.current.templateUrl = {{main.$route.current.templateUrl}}
-
$route.current.params = {{main.$route.current.params}}
-
$route.current.scope.name = {{main.$route.current.scope.name}}
-
$routeParams = {{main.$routeParams}}
-
-
- - -
- controller: {{book.name}}
- Book Id: {{book.params.bookId}}
-
-
- - -
- controller: {{chapter.name}}
- Book Id: {{chapter.params.bookId}}
- Chapter Id: {{chapter.params.chapterId}} -
-
- - - .view-animate-container { + * + * - If the attribute is not set, disable scrolling. + * - If the attribute is set without value, enable scrolling. + * - Otherwise enable scrolling only if the `autoscroll` attribute value evaluated + * as an expression yields a truthy value. + * @example + + +
+ Choose: + Moby | + Moby: Ch1 | + Gatsby | + Gatsby: Ch4 | + Scarlet Letter
+ +
+
+
+
+ +
$location.path() = {{main.$location.path()}}
+
$route.current.templateUrl = {{main.$route.current.templateUrl}}
+
$route.current.params = {{main.$route.current.params}}
+
$route.current.scope.name = {{main.$route.current.scope.name}}
+
$routeParams = {{main.$routeParams}}
+
+
+ + +
+ controller: {{book.name}}
+ Book Id: {{book.params.bookId}}
+
+
+ + +
+ controller: {{chapter.name}}
+ Book Id: {{chapter.params.bookId}}
+ Chapter Id: {{chapter.params.chapterId}} +
+
+ + + .view-animate-container { position:relative; height:100px!important; position:relative; @@ -728,11 +732,11 @@ ngRouteModule.directive('ngView', ngViewFillContentFactory); overflow:hidden; } - .view-animate { + .view-animate { padding:10px; } - .view-animate.ng-enter, .view-animate.ng-leave { + .view-animate.ng-enter, .view-animate.ng-leave { -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s; transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s; @@ -748,20 +752,20 @@ ngRouteModule.directive('ngView', ngViewFillContentFactory); padding:10px; } - .view-animate.ng-enter { + .view-animate.ng-enter { left:100%; } - .view-animate.ng-enter.ng-enter-active { + .view-animate.ng-enter.ng-enter-active { left:0; } - .view-animate.ng-leave.ng-leave-active { + .view-animate.ng-leave.ng-leave-active { left:-100%; } - +
- - angular.module('ngViewExample', ['ngRoute', 'ngAnimate'], - function($routeProvider, $locationProvider) { + + angular.module('ngViewExample', ['ngRoute', 'ngAnimate'], + function($routeProvider, $locationProvider) { $routeProvider.when('/Book/:bookId', { templateUrl: 'book.html', controller: BookCntl, @@ -777,25 +781,25 @@ ngRouteModule.directive('ngView', ngViewFillContentFactory); $locationProvider.html5Mode(true); }); - function MainCntl($route, $routeParams, $location) { + function MainCntl($route, $routeParams, $location) { this.$route = $route; this.$location = $location; this.$routeParams = $routeParams; } - function BookCntl($routeParams) { + function BookCntl($routeParams) { this.name = "BookCntl"; this.params = $routeParams; } - function ChapterCntl($routeParams) { + function ChapterCntl($routeParams) { this.name = "ChapterCntl"; this.params = $routeParams; } - + - - it('should load and compile correct template', function() { + + it('should load and compile correct template', function() { element(by.linkText('Moby: Ch1')).click(); var content = element(by.css('.doc-example-live [ng-view]')).getText(); expect(content).toMatch(/controller\: ChapterCntl/); @@ -808,114 +812,116 @@ ngRouteModule.directive('ngView', ngViewFillContentFactory); expect(content).toMatch(/controller\: BookCntl/); expect(content).toMatch(/Book Id\: Scarlet/); }); - -
- */ - + + + */ -/** - * @ngdoc event - * @name ngRoute.directive:ngView#$viewContentLoaded - * @eventOf ngRoute.directive:ngView - * @eventType emit on the current ngView scope - * @description - * Emitted every time the ngView content is reloaded. - */ -ngViewFactory.$inject = ['$route', '$anchorScroll', '$animate']; -function ngViewFactory( $route, $anchorScroll, $animate) { - return { - restrict: 'ECA', - terminal: true, - priority: 400, - transclude: 'element', - link: function(scope, $element, attr, ctrl, $transclude) { - var currentScope, - currentElement, - autoScrollExp = attr.autoscroll, - onloadExp = attr.onload || ''; - - scope.$on('$routeChangeSuccess', update); - update(); - - function cleanupLastView() { - if (currentScope) { - currentScope.$destroy(); - currentScope = null; - } - if(currentElement) { - $animate.leave(currentElement); - currentElement = null; - } - } - function update() { - var locals = $route.current && $route.current.locals, - template = locals && locals.$template; - - if (angular.isDefined(template)) { - var newScope = scope.$new(); - var current = $route.current; - - // Note: This will also link all children of ng-view that were contained in the original - // html. If that content contains controllers, ... they could pollute/change the scope. - // However, using ng-view on an element with additional content does not make sense... - // Note: We can't remove them in the cloneAttchFn of $transclude as that - // function is called before linking the content, which would apply child - // directives to non existing elements. - var clone = $transclude(newScope, function(clone) { - $animate.enter(clone, null, currentElement || $element, function onNgViewEnter () { - if (angular.isDefined(autoScrollExp) - && (!autoScrollExp || scope.$eval(autoScrollExp))) { - $anchorScroll(); + /** + * @ngdoc event + * @name ngRoute.directive:ngView#$viewContentLoaded + * @eventOf ngRoute.directive:ngView + * @eventType emit on the current ngView scope + * @description + * Emitted every time the ngView content is reloaded. + */ + ngViewFactory.$inject = ['$route', '$anchorScroll', '$animate']; + + function ngViewFactory($route, $anchorScroll, $animate) { + return { + restrict: 'ECA', + terminal: true, + priority: 400, + transclude: 'element', + link: function (scope, $element, attr, ctrl, $transclude) { + var currentScope, + currentElement, + autoScrollExp = attr.autoscroll, + onloadExp = attr.onload || ''; + + scope.$on('$routeChangeSuccess', update); + update(); + + function cleanupLastView() { + if (currentScope) { + currentScope.$destroy(); + currentScope = null; + } + if (currentElement) { + $animate.leave(currentElement); + currentElement = null; + } } - }); - cleanupLastView(); - }); - currentElement = clone; - currentScope = current.scope = newScope; - currentScope.$emit('$viewContentLoaded'); - currentScope.$eval(onloadExp); - } else { - cleanupLastView(); - } - } + function update() { + var locals = $route.current && $route.current.locals, + template = locals && locals.$template; + + if (angular.isDefined(template)) { + var newScope = scope.$new(); + var current = $route.current; + + // Note: This will also link all children of ng-view that were contained in the original + // html. If that content contains controllers, ... they could pollute/change the scope. + // However, using ng-view on an element with additional content does not make sense... + // Note: We can't remove them in the cloneAttchFn of $transclude as that + // function is called before linking the content, which would apply child + // directives to non existing elements. + var clone = $transclude(newScope, function (clone) { + $animate.enter(clone, null, currentElement || $element, function onNgViewEnter() { + if (angular.isDefined(autoScrollExp) + && (!autoScrollExp || scope.$eval(autoScrollExp))) { + $anchorScroll(); + } + }); + cleanupLastView(); + }); + + currentElement = clone; + currentScope = current.scope = newScope; + currentScope.$emit('$viewContentLoaded'); + currentScope.$eval(onloadExp); + } else { + cleanupLastView(); + } + } + } + }; } - }; -} // This directive is called during the $transclude call of the first `ngView` directive. // It will replace and compile the content of the element with the loaded template. // We need this directive so that the element content is already filled when // the link function of another directive on the same element as ngView // is called. -ngViewFillContentFactory.$inject = ['$compile', '$controller', '$route']; -function ngViewFillContentFactory($compile, $controller, $route) { - return { - restrict: 'ECA', - priority: -400, - link: function(scope, $element) { - var current = $route.current, - locals = current.locals; - - $element.html(locals.$template); - - var link = $compile($element.contents()); - - if (current.controller) { - locals.$scope = scope; - var controller = $controller(current.controller, locals); - if (current.controllerAs) { - scope[current.controllerAs] = controller; - } - $element.data('$ngControllerController', controller); - $element.children().data('$ngControllerController', controller); - } + ngViewFillContentFactory.$inject = ['$compile', '$controller', '$route']; + + function ngViewFillContentFactory($compile, $controller, $route) { + return { + restrict: 'ECA', + priority: -400, + link: function (scope, $element) { + var current = $route.current, + locals = current.locals; + + $element.html(locals.$template); + + var link = $compile($element.contents()); + + if (current.controller) { + locals.$scope = scope; + var controller = $controller(current.controller, locals); + if (current.controllerAs) { + scope[current.controllerAs] = controller; + } + $element.data('$ngControllerController', controller); + $element.children().data('$ngControllerController', controller); + } - link(scope); + link(scope); + } + }; } - }; -} })(window, window.angular); diff --git a/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-route_1.2.13/angular-route.min.js.map b/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-route_1.2.13/angular-route.min.js.map index 01c289286ad8a73f1ecd532b5824b0f56f363e57..4bd08a62f3dc77fd0ace7a1526132168f64288a4 100644 --- a/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-route_1.2.13/angular-route.min.js.map +++ b/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-route_1.2.13/angular-route.min.js.map @@ -1,8 +1,151 @@ { -"version":3, -"file":"angular-route.min.js", -"lineCount":13, -"mappings":"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", -"sources":["angular-route.js"], -"names":["window","angular","undefined","ngViewFactory","$route","$anchorScroll","$animate","link","scope","$element","attr","ctrl","$transclude","cleanupLastView","currentScope","$destroy","currentElement","leave","update","locals","current","isDefined","$template","newScope","$new","clone","enter","onNgViewEnter","autoScrollExp","$eval","$emit","onloadExp","autoscroll","onload","$on","ngViewFillContentFactory","$compile","$controller","html","contents","controller","$scope","controllerAs","data","children","ngRouteModule","module","provider","$RouteProvider","inherit","parent","extra","extend","pathRegExp","path","opts","insensitive","caseInsensitiveMatch","ret","keys","replace","_","slash","key","option","optional","star","push","regexp","RegExp","routes","when","this.when","route","redirectPath","length","substr","otherwise","this.otherwise","params","$get","$rootScope","$location","$routeParams","$q","$injector","$http","$templateCache","$sce","updateRoute","next","parseRoute","last","$$route","equals","pathParams","reloadOnSearch","forceReload","copy","$broadcast","redirectTo","isString","interpolate","search","url","then","resolve","template","templateUrl","forEach","value","get","invoke","isFunction","getTrustedResourceUrl","loadedTemplateUrl","response","all","error","match","m","exec","on","i","len","val","decodeURIComponent","name","string","result","split","segment","segmentMatch","join","reload","$evalAsync","$RouteParamsProvider","this.$get","directive","$inject"] + "version": 3, + "file": "angular-route.min.js", + "lineCount": 13, + "mappings": "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", + "sources": [ + "angular-route.js" + ], + "names": [ + "window", + "angular", + "undefined", + "ngViewFactory", + "$route", + "$anchorScroll", + "$animate", + "link", + "scope", + "$element", + "attr", + "ctrl", + "$transclude", + "cleanupLastView", + "currentScope", + "$destroy", + "currentElement", + "leave", + "update", + "locals", + "current", + "isDefined", + "$template", + "newScope", + "$new", + "clone", + "enter", + "onNgViewEnter", + "autoScrollExp", + "$eval", + "$emit", + "onloadExp", + "autoscroll", + "onload", + "$on", + "ngViewFillContentFactory", + "$compile", + "$controller", + "html", + "contents", + "controller", + "$scope", + "controllerAs", + "data", + "children", + "ngRouteModule", + "module", + "provider", + "$RouteProvider", + "inherit", + "parent", + "extra", + "extend", + "pathRegExp", + "path", + "opts", + "insensitive", + "caseInsensitiveMatch", + "ret", + "keys", + "replace", + "_", + "slash", + "key", + "option", + "optional", + "star", + "push", + "regexp", + "RegExp", + "routes", + "when", + "this.when", + "route", + "redirectPath", + "length", + "substr", + "otherwise", + "this.otherwise", + "params", + "$get", + "$rootScope", + "$location", + "$routeParams", + "$q", + "$injector", + "$http", + "$templateCache", + "$sce", + "updateRoute", + "next", + "parseRoute", + "last", + "$$route", + "equals", + "pathParams", + "reloadOnSearch", + "forceReload", + "copy", + "$broadcast", + "redirectTo", + "isString", + "interpolate", + "search", + "url", + "then", + "resolve", + "template", + "templateUrl", + "forEach", + "value", + "get", + "invoke", + "isFunction", + "getTrustedResourceUrl", + "loadedTemplateUrl", + "response", + "all", + "error", + "match", + "m", + "exec", + "on", + "i", + "len", + "val", + "decodeURIComponent", + "name", + "string", + "result", + "split", + "segment", + "segmentMatch", + "join", + "reload", + "$evalAsync", + "$RouteParamsProvider", + "this.$get", + "directive", + "$inject" + ] } diff --git a/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-sanitize_1.2.13/angular-sanitize.js b/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-sanitize_1.2.13/angular-sanitize.js index 9259ca2f1c2b52df63e82f9f7e05a0f5e00564e6..24bf8215eeabc4a71e15943025ffca3659b1f2dc 100644 --- a/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-sanitize_1.2.13/angular-sanitize.js +++ b/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-sanitize_1.2.13/angular-sanitize.js @@ -3,65 +3,66 @@ * (c) 2010-2014 Google, Inc. http://angularjs.org * License: MIT */ -(function(window, angular, undefined) {'use strict'; - -var $sanitizeMinErr = angular.$$minErr('$sanitize'); - -/** - * @ngdoc overview - * @name ngSanitize - * @description - * - * # ngSanitize - * - * The `ngSanitize` module provides functionality to sanitize HTML. - * - * {@installModule sanitize} - * - *
- * - * See {@link ngSanitize.$sanitize `$sanitize`} for usage. - */ - -/* - * HTML Parser By Misko Hevery (misko@hevery.com) - * based on: HTML Parser By John Resig (ejohn.org) - * Original code by Erik Arvidsson, Mozilla Public License - * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js - * - * // Use like so: - * htmlParser(htmlString, { - * start: function(tag, attrs, unary) {}, - * end: function(tag) {}, - * chars: function(text) {}, - * comment: function(text) {} - * }); - * - */ - - -/** - * @ngdoc service - * @name ngSanitize.$sanitize - * @function - * - * @description - * The input is sanitized by parsing the html into tokens. All safe tokens (from a whitelist) are - * then serialized back to properly escaped html string. This means that no unsafe input can make - * it into the returned string, however, since our parser is more strict than a typical browser - * parser, it's possible that some obscure input, which would be recognized as valid HTML by a - * browser, won't make it through the sanitizer. - * The whitelist is configured using the functions `aHrefSanitizationWhitelist` and - * `imgSrcSanitizationWhitelist` of {@link ng.$compileProvider `$compileProvider`}. - * - * @param {string} html Html input. - * @returns {string} Sanitized html. - * - * @example - - +(function (window, angular, undefined) { + 'use strict'; + + var $sanitizeMinErr = angular.$$minErr('$sanitize'); + + /** + * @ngdoc overview + * @name ngSanitize + * @description + * + * # ngSanitize + * + * The `ngSanitize` module provides functionality to sanitize HTML. + * + * {@installModule sanitize} + * + *
+ * + * See {@link ngSanitize.$sanitize `$sanitize`} for usage. + */ + + /* + * HTML Parser By Misko Hevery (misko@hevery.com) + * based on: HTML Parser By John Resig (ejohn.org) + * Original code by Erik Arvidsson, Mozilla Public License + * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js + * + * // Use like so: + * htmlParser(htmlString, { + * start: function(tag, attrs, unary) {}, + * end: function(tag) {}, + * chars: function(text) {}, + * comment: function(text) {} + * }); + * + */ + + + /** + * @ngdoc service + * @name ngSanitize.$sanitize + * @function + * + * @description + * The input is sanitized by parsing the html into tokens. All safe tokens (from a whitelist) are + * then serialized back to properly escaped html string. This means that no unsafe input can make + * it into the returned string, however, since our parser is more strict than a typical browser + * parser, it's possible that some obscure input, which would be recognized as valid HTML by a + * browser, won't make it through the sanitizer. + * The whitelist is configured using the functions `aHrefSanitizationWhitelist` and + * `imgSrcSanitizationWhitelist` of {@link ng.$compileProvider `$compileProvider`}. + * + * @param {string} html Html input. + * @returns {string} Sanitized html. + * + * @example + +
- Snippet: - - - - - - - - - - - - - - - - - - - - - - - - - -
DirectiveHowSourceRendered
ng-bind-htmlAutomatically uses $sanitize
<div ng-bind-html="snippet">
</div>
ng-bind-htmlBypass $sanitize by explicitly trusting the dangerous value -
<div ng-bind-html="deliberatelyTrustDangerousSnippet()">
-</div>
-
ng-bindAutomatically escapes
<div ng-bind="snippet">
</div>
-
-
- + Snippet: + + + + + + + + + + + + + + + + + + + + + + + + + +
DirectiveHowSourceRendered
ng-bind-htmlAutomatically uses $sanitize
<div ng-bind-html="snippet">
</div>
ng-bind-htmlBypass $sanitize by explicitly trusting the dangerous value +
<div ng-bind-html="deliberatelyTrustDangerousSnippet()">
+     </div>
+
ng-bindAutomatically escapes
<div ng-bind="snippet">
</div>
+ +
+ it('should sanitize the html snippet by default', function() { expect(element(by.css('#bind-html-with-sanitize div')).getInnerHtml()). toBe('

an html\nclick here\nsnippet

'); @@ -134,41 +135,41 @@ var $sanitizeMinErr = angular.$$minErr('$sanitize'); expect(element(by.css('#bind-default div')).getInnerHtml()).toBe( "new <b onclick=\"alert(1)\">text</b>"); }); -
-
- */ -function $SanitizeProvider() { - this.$get = ['$$sanitizeUri', function($$sanitizeUri) { - return function(html) { - var buf = []; - htmlParser(html, htmlSanitizeWriter(buf, function(uri, isImage) { - return !/^unsafe/.test($$sanitizeUri(uri, isImage)); - })); - return buf.join(''); - }; - }]; -} - -function sanitizeText(chars) { - var buf = []; - var writer = htmlSanitizeWriter(buf, angular.noop); - writer.chars(chars); - return buf.join(''); -} + + + */ + function $SanitizeProvider() { + this.$get = ['$$sanitizeUri', function ($$sanitizeUri) { + return function (html) { + var buf = []; + htmlParser(html, htmlSanitizeWriter(buf, function (uri, isImage) { + return !/^unsafe/.test($$sanitizeUri(uri, isImage)); + })); + return buf.join(''); + }; + }]; + } + + function sanitizeText(chars) { + var buf = []; + var writer = htmlSanitizeWriter(buf, angular.noop); + writer.chars(chars); + return buf.join(''); + } // Regular Expressions for parsing tags and attributes -var START_TAG_REGEXP = - /^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*>/, - END_TAG_REGEXP = /^<\s*\/\s*([\w:-]+)[^>]*>/, - ATTR_REGEXP = /([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g, - BEGIN_TAG_REGEXP = /^/g, - DOCTYPE_REGEXP = /]*?)>/i, - CDATA_REGEXP = //g, - // Match everything outside of normal chars and " (quote character) - NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g; + var START_TAG_REGEXP = + /^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*>/, + END_TAG_REGEXP = /^<\s*\/\s*([\w:-]+)[^>]*>/, + ATTR_REGEXP = /([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g, + BEGIN_TAG_REGEXP = /^/g, + DOCTYPE_REGEXP = /]*?)>/i, + CDATA_REGEXP = //g, + // Match everything outside of normal chars and " (quote character) + NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g; // Good source of info about elements and attributes @@ -177,326 +178,327 @@ var START_TAG_REGEXP = // Safe Void Elements - HTML5 // http://dev.w3.org/html5/spec/Overview.html#void-elements -var voidElements = makeMap("area,br,col,hr,img,wbr"); + var voidElements = makeMap("area,br,col,hr,img,wbr"); // Elements that you can, intentionally, leave open (and which close themselves) // http://dev.w3.org/html5/spec/Overview.html#optional-tags -var optionalEndTagBlockElements = makeMap("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"), - optionalEndTagInlineElements = makeMap("rp,rt"), - optionalEndTagElements = angular.extend({}, - optionalEndTagInlineElements, - optionalEndTagBlockElements); + var optionalEndTagBlockElements = makeMap("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"), + optionalEndTagInlineElements = makeMap("rp,rt"), + optionalEndTagElements = angular.extend({}, + optionalEndTagInlineElements, + optionalEndTagBlockElements); // Safe Block Elements - HTML5 -var blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap("address,article," + + var blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap("address,article," + "aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5," + "h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul")); // Inline Elements - HTML5 -var inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap("a,abbr,acronym,b," + + var inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap("a,abbr,acronym,b," + "bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s," + "samp,small,span,strike,strong,sub,sup,time,tt,u,var")); // Special Elements (can contain anything) -var specialElements = makeMap("script,style"); + var specialElements = makeMap("script,style"); -var validElements = angular.extend({}, - voidElements, - blockElements, - inlineElements, - optionalEndTagElements); + var validElements = angular.extend({}, + voidElements, + blockElements, + inlineElements, + optionalEndTagElements); //Attributes that have href and hence need to be sanitized -var uriAttrs = makeMap("background,cite,href,longdesc,src,usemap"); -var validAttrs = angular.extend({}, uriAttrs, makeMap( - 'abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+ - 'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,'+ - 'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,'+ - 'scope,scrolling,shape,size,span,start,summary,target,title,type,'+ - 'valign,value,vspace,width')); - -function makeMap(str) { - var obj = {}, items = str.split(','), i; - for (i = 0; i < items.length; i++) obj[items[i]] = true; - return obj; -} - - -/** - * @example - * htmlParser(htmlString, { - * start: function(tag, attrs, unary) {}, - * end: function(tag) {}, - * chars: function(text) {}, - * comment: function(text) {} - * }); - * - * @param {string} html string - * @param {object} handler - */ -function htmlParser( html, handler ) { - var index, chars, match, stack = [], last = html; - stack.last = function() { return stack[ stack.length - 1 ]; }; - - while ( html ) { - chars = true; - - // Make sure we're not in a script or style element - if ( !stack.last() || !specialElements[ stack.last() ] ) { + var uriAttrs = makeMap("background,cite,href,longdesc,src,usemap"); + var validAttrs = angular.extend({}, uriAttrs, makeMap( + 'abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,' + + 'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,' + + 'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,' + + 'scope,scrolling,shape,size,span,start,summary,target,title,type,' + + 'valign,value,vspace,width')); + + function makeMap(str) { + var obj = {}, items = str.split(','), i; + for (i = 0; i < items.length; i++) obj[items[i]] = true; + return obj; + } - // Comment - if ( html.indexOf("", index) === index) { - if (handler.comment) handler.comment( html.substring( 4, index ) ); - html = html.substring( index + 3 ); - chars = false; + /** + * @example + * htmlParser(htmlString, { + * start: function(tag, attrs, unary) {}, + * end: function(tag) {}, + * chars: function(text) {}, + * comment: function(text) {} + * }); + * + * @param {string} html string + * @param {object} handler + */ + function htmlParser(html, handler) { + var index, chars, match, stack = [], last = html; + stack.last = function () { + return stack[stack.length - 1]; + }; + + while (html) { + chars = true; + + // Make sure we're not in a script or style element + if (!stack.last() || !specialElements[stack.last()]) { + + // Comment + if (html.indexOf("", index) === index) { + if (handler.comment) handler.comment(html.substring(4, index)); + html = html.substring(index + 3); + chars = false; + } + // DOCTYPE + } else if (DOCTYPE_REGEXP.test(html)) { + match = html.match(DOCTYPE_REGEXP); + + if (match) { + html = html.replace(match[0], ''); + chars = false; + } + // end tag + } else if (BEGING_END_TAGE_REGEXP.test(html)) { + match = html.match(END_TAG_REGEXP); + + if (match) { + html = html.substring(match[0].length); + match[0].replace(END_TAG_REGEXP, parseEndTag); + chars = false; + } + + // start tag + } else if (BEGIN_TAG_REGEXP.test(html)) { + match = html.match(START_TAG_REGEXP); + + if (match) { + html = html.substring(match[0].length); + match[0].replace(START_TAG_REGEXP, parseStartTag); + chars = false; + } + } + + if (chars) { + index = html.indexOf("<"); + + var text = index < 0 ? html : html.substring(0, index); + html = index < 0 ? "" : html.substring(index); + + if (handler.chars) handler.chars(decodeEntities(text)); + } + + } else { + html = html.replace(new RegExp("(.*)<\\s*\\/\\s*" + stack.last() + "[^>]*>", 'i'), + function (all, text) { + text = text.replace(COMMENT_REGEXP, "$1").replace(CDATA_REGEXP, "$1"); + + if (handler.chars) handler.chars(decodeEntities(text)); + + return ""; + }); + + parseEndTag("", stack.last()); + } + + if (html == last) { + throw $sanitizeMinErr('badparse', "The sanitizer was unable to parse the following block " + + "of html: {0}", html); + } + last = html; } - // DOCTYPE - } else if ( DOCTYPE_REGEXP.test(html) ) { - match = html.match( DOCTYPE_REGEXP ); - if ( match ) { - html = html.replace( match[0] , ''); - chars = false; - } - // end tag - } else if ( BEGING_END_TAGE_REGEXP.test(html) ) { - match = html.match( END_TAG_REGEXP ); - - if ( match ) { - html = html.substring( match[0].length ); - match[0].replace( END_TAG_REGEXP, parseEndTag ); - chars = false; - } + // Clean up any remaining tags + parseEndTag(); - // start tag - } else if ( BEGIN_TAG_REGEXP.test(html) ) { - match = html.match( START_TAG_REGEXP ); + function parseStartTag(tag, tagName, rest, unary) { + tagName = angular.lowercase(tagName); + if (blockElements[tagName]) { + while (stack.last() && inlineElements[stack.last()]) { + parseEndTag("", stack.last()); + } + } - if ( match ) { - html = html.substring( match[0].length ); - match[0].replace( START_TAG_REGEXP, parseStartTag ); - chars = false; - } - } - - if ( chars ) { - index = html.indexOf("<"); + if (optionalEndTagElements[tagName] && stack.last() == tagName) { + parseEndTag("", tagName); + } - var text = index < 0 ? html : html.substring( 0, index ); - html = index < 0 ? "" : html.substring( index ); + unary = voidElements[tagName] || !!unary; - if (handler.chars) handler.chars( decodeEntities(text) ); - } + if (!unary) + stack.push(tagName); - } else { - html = html.replace(new RegExp("(.*)<\\s*\\/\\s*" + stack.last() + "[^>]*>", 'i'), - function(all, text){ - text = text.replace(COMMENT_REGEXP, "$1").replace(CDATA_REGEXP, "$1"); + var attrs = {}; - if (handler.chars) handler.chars( decodeEntities(text) ); + rest.replace(ATTR_REGEXP, + function (match, name, doubleQuotedValue, singleQuotedValue, unquotedValue) { + var value = doubleQuotedValue + || singleQuotedValue + || unquotedValue + || ''; - return ""; - }); + attrs[name] = decodeEntities(value); + }); + if (handler.start) handler.start(tagName, attrs, unary); + } - parseEndTag( "", stack.last() ); + function parseEndTag(tag, tagName) { + var pos = 0, i; + tagName = angular.lowercase(tagName); + if (tagName) + // Find the closest opened tag of the same type + for (pos = stack.length - 1; pos >= 0; pos--) + if (stack[pos] == tagName) + break; + + if (pos >= 0) { + // Close all the open elements, up the stack + for (i = stack.length - 1; i >= pos; i--) + if (handler.end) handler.end(stack[i]); + + // Remove the open elements from the stack + stack.length = pos; + } + } } - if ( html == last ) { - throw $sanitizeMinErr('badparse', "The sanitizer was unable to parse the following block " + - "of html: {0}", html); - } - last = html; - } - - // Clean up any remaining tags - parseEndTag(); - - function parseStartTag( tag, tagName, rest, unary ) { - tagName = angular.lowercase(tagName); - if ( blockElements[ tagName ] ) { - while ( stack.last() && inlineElements[ stack.last() ] ) { - parseEndTag( "", stack.last() ); - } - } + var hiddenPre = document.createElement("pre"); + var spaceRe = /^(\s*)([\s\S]*?)(\s*)$/; + + /** + * decodes all entities into regular string + * @param value + * @returns {string} A string with decoded entities. + */ + function decodeEntities(value) { + if (!value) { + return ''; + } - if ( optionalEndTagElements[ tagName ] && stack.last() == tagName ) { - parseEndTag( "", tagName ); + // Note: IE8 does not preserve spaces at the start/end of innerHTML + // so we must capture them and reattach them afterward + var parts = spaceRe.exec(value); + var spaceBefore = parts[1]; + var spaceAfter = parts[3]; + var content = parts[2]; + if (content) { + hiddenPre.innerHTML = content.replace(/= 0; pos-- ) - if ( stack[ pos ] == tagName ) - break; - - if ( pos >= 0 ) { - // Close all the open elements, up the stack - for ( i = stack.length - 1; i >= pos; i-- ) - if (handler.end) handler.end( stack[ i ] ); - - // Remove the open elements from the stack - stack.length = pos; + /** + * Escapes all potentially dangerous characters, so that the + * resulting string can be safely inserted into attribute or + * element text. + * @param value + * @returns escaped text + */ + function encodeEntities(value) { + return value.replace(/&/g, '&').replace(NON_ALPHANUMERIC_REGEXP, function (value) { + return '&#' + value.charCodeAt(0) + ';'; + }).replace(//g, '>'); } - } -} - -var hiddenPre=document.createElement("pre"); -var spaceRe = /^(\s*)([\s\S]*?)(\s*)$/; -/** - * decodes all entities into regular string - * @param value - * @returns {string} A string with decoded entities. - */ -function decodeEntities(value) { - if (!value) { return ''; } - - // Note: IE8 does not preserve spaces at the start/end of innerHTML - // so we must capture them and reattach them afterward - var parts = spaceRe.exec(value); - var spaceBefore = parts[1]; - var spaceAfter = parts[3]; - var content = parts[2]; - if (content) { - hiddenPre.innerHTML=content.replace(//g, '>'); -} - -/** - * create an HTML/XML writer which writes to buffer - * @param {Array} buf use buf.jain('') to get out sanitized html string - * @returns {object} in the form of { - * start: function(tag, attrs, unary) {}, - * end: function(tag) {}, - * chars: function(text) {}, - * comment: function(text) {} - * } - */ -function htmlSanitizeWriter(buf, uriValidator){ - var ignore = false; - var out = angular.bind(buf, buf.push); - return { - start: function(tag, attrs, unary){ - tag = angular.lowercase(tag); - if (!ignore && specialElements[tag]) { - ignore = tag; - } - if (!ignore && validElements[tag] === true) { - out('<'); - out(tag); - angular.forEach(attrs, function(value, key){ - var lkey=angular.lowercase(key); - var isImage = (tag === 'img' && lkey === 'src') || (lkey === 'background'); - if (validAttrs[lkey] === true && - (uriAttrs[lkey] !== true || uriValidator(value, isImage))) { - out(' '); - out(key); - out('="'); - out(encodeEntities(value)); - out('"'); - } - }); - out(unary ? '/>' : '>'); - } - }, - end: function(tag){ - tag = angular.lowercase(tag); - if (!ignore && validElements[tag] === true) { - out(''); - } - if (tag == ignore) { - ignore = false; - } - }, - chars: function(chars){ - if (!ignore) { - out(encodeEntities(chars)); - } - } - }; -} + /** + * create an HTML/XML writer which writes to buffer + * @param {Array} buf use buf.jain('') to get out sanitized html string + * @returns {object} in the form of { + * start: function(tag, attrs, unary) {}, + * end: function(tag) {}, + * chars: function(text) {}, + * comment: function(text) {} + * } + */ + function htmlSanitizeWriter(buf, uriValidator) { + var ignore = false; + var out = angular.bind(buf, buf.push); + return { + start: function (tag, attrs, unary) { + tag = angular.lowercase(tag); + if (!ignore && specialElements[tag]) { + ignore = tag; + } + if (!ignore && validElements[tag] === true) { + out('<'); + out(tag); + angular.forEach(attrs, function (value, key) { + var lkey = angular.lowercase(key); + var isImage = (tag === 'img' && lkey === 'src') || (lkey === 'background'); + if (validAttrs[lkey] === true && + (uriAttrs[lkey] !== true || uriValidator(value, isImage))) { + out(' '); + out(key); + out('="'); + out(encodeEntities(value)); + out('"'); + } + }); + out(unary ? '/>' : '>'); + } + }, + end: function (tag) { + tag = angular.lowercase(tag); + if (!ignore && validElements[tag] === true) { + out(''); + } + if (tag == ignore) { + ignore = false; + } + }, + chars: function (chars) { + if (!ignore) { + out(encodeEntities(chars)); + } + } + }; + } // define ngSanitize module and register $sanitize service -angular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider); - -/* global sanitizeText: false */ - -/** - * @ngdoc filter - * @name ngSanitize.filter:linky - * @function - * - * @description - * Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and - * plain email address links. - * - * Requires the {@link ngSanitize `ngSanitize`} module to be installed. - * - * @param {string} text Input text. - * @param {string} target Window (_blank|_self|_parent|_top) or named frame to open links in. - * @returns {string} Html-linkified text. - * - * @usage - - * - * @example - + angular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider); + + /* global sanitizeText: false */ + + /** + * @ngdoc filter + * @name ngSanitize.filter:linky + * @function + * + * @description + * Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and + * plain email address links. + * + * Requires the {@link ngSanitize `ngSanitize`} module to be installed. + * + * @param {string} text Input text. + * @param {string} target Window (_blank|_self|_parent|_top) or named frame to open links in. + * @returns {string} Html-linkified text. + * + * @usage + + * + * @example + - -
- Snippet: - - - - - - - - - - - - - - - - - - - - - -
FilterSourceRendered
linky filter -
<div ng-bind-html="snippet | linky">
</div>
-
-
-
linky target -
<div ng-bind-html="snippetWithTarget | linky:'_blank'">
</div>
-
-
-
no filter
<div ng-bind="snippet">
</div>
+ +
+ Snippet: + + + + + + + + + + + + + + + + + + + + + +
FilterSourceRendered
linky filter +
<div ng-bind-html="snippet | linky">
</div>
+
+
+
linky target +
<div ng-bind-html="snippetWithTarget | linky:'_blank'">
</div>
+
+
+
no filter
<div ng-bind="snippet">
</div>
- it('should linkify the snippet with urls', function() { + it('should linkify the snippet with urls', function() { expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()). toBe('Pretty text with some links: http://angularjs.org/, us@somewhere.org, ' + 'another@somewhere.org, and one more: ftp://127.0.0.1/.'); expect(element.all(by.css('#linky-filter a')).count()).toEqual(4); }); - it('should not linkify snippet without the linky filter', function() { + it('should not linkify snippet without the linky filter', function() { expect(element(by.id('escaped-html')).element(by.binding('snippet')).getText()). toBe('Pretty text with some links: http://angularjs.org/, mailto:us@somewhere.org, ' + 'another@somewhere.org, and one more: ftp://127.0.0.1/.'); expect(element.all(by.css('#escaped-html a')).count()).toEqual(0); }); - it('should update', function() { + it('should update', function() { element(by.model('snippet')).clear(); element(by.model('snippet')).sendKeys('new http://link.'); expect(element(by.id('linky-filter')).element(by.binding('snippet | linky')).getText()). @@ -564,62 +566,62 @@ angular.module('ngSanitize', []).provider('$sanitize', $SanitizeProvider); .toBe('new http://link.'); }); - it('should work with the target property', function() { + it('should work with the target property', function() { expect(element(by.id('linky-target')). element(by.binding("snippetWithTarget | linky:'_blank'")).getText()). toBe('http://angularjs.org/'); expect(element(by.css('#linky-target a')).getAttribute('target')).toEqual('_blank'); }); - - */ -angular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) { - var LINKY_URL_REGEXP = - /((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>]/, - MAILTO_REGEXP = /^mailto:/; - - return function(text, target) { - if (!text) return text; - var match; - var raw = text; - var html = []; - var url; - var i; - while ((match = raw.match(LINKY_URL_REGEXP))) { - // We can not end in these as they are sometimes found at the end of the sentence - url = match[0]; - // if we did not match ftp/http/mailto then assume mailto - if (match[2] == match[3]) url = 'mailto:' + url; - i = match.index; - addText(raw.substr(0, i)); - addLink(url, match[0].replace(MAILTO_REGEXP, '')); - raw = raw.substring(i + match[0].length); - } - addText(raw); - return $sanitize(html.join('')); - - function addText(text) { - if (!text) { - return; - } - html.push(sanitizeText(text)); - } - - function addLink(url, text) { - html.push(''); - addText(text); - html.push(''); - } - }; -}]); + + */ + angular.module('ngSanitize').filter('linky', ['$sanitize', function ($sanitize) { + var LINKY_URL_REGEXP = + /((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>]/, + MAILTO_REGEXP = /^mailto:/; + + return function (text, target) { + if (!text) return text; + var match; + var raw = text; + var html = []; + var url; + var i; + while ((match = raw.match(LINKY_URL_REGEXP))) { + // We can not end in these as they are sometimes found at the end of the sentence + url = match[0]; + // if we did not match ftp/http/mailto then assume mailto + if (match[2] == match[3]) url = 'mailto:' + url; + i = match.index; + addText(raw.substr(0, i)); + addLink(url, match[0].replace(MAILTO_REGEXP, '')); + raw = raw.substring(i + match[0].length); + } + addText(raw); + return $sanitize(html.join('')); + + function addText(text) { + if (!text) { + return; + } + html.push(sanitizeText(text)); + } + + function addLink(url, text) { + html.push(''); + addText(text); + html.push(''); + } + }; + }]); })(window, window.angular); diff --git a/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-sanitize_1.2.13/angular-sanitize.min.js.map b/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-sanitize_1.2.13/angular-sanitize.min.js.map index c479150a70aec2a520486a76d694ecb87b486fd1..68ff449aea7854a9a85c368da89f1078f1d4a41f 100644 --- a/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-sanitize_1.2.13/angular-sanitize.min.js.map +++ b/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-sanitize_1.2.13/angular-sanitize.min.js.map @@ -1,8 +1,124 @@ { -"version":3, -"file":"angular-sanitize.min.js", -"lineCount":13, -"mappings":"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", -"sources":["angular-sanitize.js"], -"names":["window","angular","undefined","sanitizeText","chars","buf","htmlSanitizeWriter","writer","noop","join","makeMap","str","obj","items","split","i","length","htmlParser","html","handler","parseStartTag","tag","tagName","rest","unary","lowercase","blockElements","stack","last","inlineElements","parseEndTag","optionalEndTagElements","voidElements","push","attrs","replace","ATTR_REGEXP","match","name","doubleQuotedValue","singleQuotedValue","unquotedValue","decodeEntities","start","pos","end","index","stack.last","specialElements","RegExp","all","text","COMMENT_REGEXP","CDATA_REGEXP","indexOf","lastIndexOf","comment","substring","DOCTYPE_REGEXP","test","BEGING_END_TAGE_REGEXP","END_TAG_REGEXP","BEGIN_TAG_REGEXP","START_TAG_REGEXP","$sanitizeMinErr","value","parts","spaceRe","exec","spaceBefore","spaceAfter","content","hiddenPre","innerHTML","textContent","innerText","encodeEntities","NON_ALPHANUMERIC_REGEXP","charCodeAt","uriValidator","ignore","out","bind","validElements","forEach","key","lkey","isImage","validAttrs","uriAttrs","$$minErr","optionalEndTagBlockElements","optionalEndTagInlineElements","extend","document","createElement","module","provider","$SanitizeProvider","$get","$$sanitizeUri","uri","filter","$sanitize","LINKY_URL_REGEXP","MAILTO_REGEXP","target","addText","addLink","url","isDefined","raw","substr"] + "version": 3, + "file": "angular-sanitize.min.js", + "lineCount": 13, + "mappings": "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", + "sources": [ + "angular-sanitize.js" + ], + "names": [ + "window", + "angular", + "undefined", + "sanitizeText", + "chars", + "buf", + "htmlSanitizeWriter", + "writer", + "noop", + "join", + "makeMap", + "str", + "obj", + "items", + "split", + "i", + "length", + "htmlParser", + "html", + "handler", + "parseStartTag", + "tag", + "tagName", + "rest", + "unary", + "lowercase", + "blockElements", + "stack", + "last", + "inlineElements", + "parseEndTag", + "optionalEndTagElements", + "voidElements", + "push", + "attrs", + "replace", + "ATTR_REGEXP", + "match", + "name", + "doubleQuotedValue", + "singleQuotedValue", + "unquotedValue", + "decodeEntities", + "start", + "pos", + "end", + "index", + "stack.last", + "specialElements", + "RegExp", + "all", + "text", + "COMMENT_REGEXP", + "CDATA_REGEXP", + "indexOf", + "lastIndexOf", + "comment", + "substring", + "DOCTYPE_REGEXP", + "test", + "BEGING_END_TAGE_REGEXP", + "END_TAG_REGEXP", + "BEGIN_TAG_REGEXP", + "START_TAG_REGEXP", + "$sanitizeMinErr", + "value", + "parts", + "spaceRe", + "exec", + "spaceBefore", + "spaceAfter", + "content", + "hiddenPre", + "innerHTML", + "textContent", + "innerText", + "encodeEntities", + "NON_ALPHANUMERIC_REGEXP", + "charCodeAt", + "uriValidator", + "ignore", + "out", + "bind", + "validElements", + "forEach", + "key", + "lkey", + "isImage", + "validAttrs", + "uriAttrs", + "$$minErr", + "optionalEndTagBlockElements", + "optionalEndTagInlineElements", + "extend", + "document", + "createElement", + "module", + "provider", + "$SanitizeProvider", + "$get", + "$$sanitizeUri", + "uri", + "filter", + "$sanitize", + "LINKY_URL_REGEXP", + "MAILTO_REGEXP", + "target", + "addText", + "addLink", + "url", + "isDefined", + "raw", + "substr" + ] } diff --git a/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-translate-loader-static-files/angular-translate-loader-static-files.js b/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-translate-loader-static-files/angular-translate-loader-static-files.js index ee3303eb80bf7392473e9a03e83c1eac35e6c11a..c7d33f7499290f1aadc8c0663d51593b0c956ef3 100644 --- a/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-translate-loader-static-files/angular-translate-loader-static-files.js +++ b/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-translate-loader-static-files/angular-translate-loader-static-files.js @@ -4,28 +4,28 @@ * Copyright (c) 2014 ; Licensed MIT */ angular.module('pascalprecht.translate').factory('$translateStaticFilesLoader', [ - '$q', - '$http', - function ($q, $http) { - return function (options) { - if (!options || (!angular.isString(options.prefix) || !angular.isString(options.suffix))) { - throw new Error('Couldn\'t load static files, no prefix or suffix specified!'); - } - var deferred = $q.defer(); - $http(angular.extend({ - url: [ - options.prefix, - options.key, - options.suffix - ].join(''), - method: 'GET', - params: '' - }, options.$http)).success(function (data) { - deferred.resolve(data); - }).error(function (data) { - deferred.reject(options.key); - }); - return deferred.promise; - }; - } -]); \ No newline at end of file + '$q', + '$http', + function ($q, $http) { + return function (options) { + if (!options || (!angular.isString(options.prefix) || !angular.isString(options.suffix))) { + throw new Error('Couldn\'t load static files, no prefix or suffix specified!'); + } + var deferred = $q.defer(); + $http(angular.extend({ + url: [ + options.prefix, + options.key, + options.suffix + ].join(''), + method: 'GET', + params: '' + }, options.$http)).success(function (data) { + deferred.resolve(data); + }).error(function (data) { + deferred.reject(options.key); + }); + return deferred.promise; + }; + } +]); diff --git a/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-translate-storage-cookie/angular-translate-storage-cookie.js b/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-translate-storage-cookie/angular-translate-storage-cookie.js index 34f180b29c5a0e38469c1d5c6a82bd96fabe0017..096d3a45f3ad0ea6648f33f8b992b8084d8d2be5 100644 --- a/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-translate-storage-cookie/angular-translate-storage-cookie.js +++ b/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-translate-storage-cookie/angular-translate-storage-cookie.js @@ -4,16 +4,16 @@ * Copyright (c) 2014 ; Licensed MIT */ angular.module('pascalprecht.translate').factory('$translateCookieStorage', [ - '$cookieStore', - function ($cookieStore) { - var $translateCookieStorage = { - get: function (name) { - return $cookieStore.get(name); - }, - set: function (name, value) { - $cookieStore.put(name, value); - } - }; - return $translateCookieStorage; - } -]); \ No newline at end of file + '$cookieStore', + function ($cookieStore) { + var $translateCookieStorage = { + get: function (name) { + return $cookieStore.get(name); + }, + set: function (name, value) { + $cookieStore.put(name, value); + } + }; + return $translateCookieStorage; + } +]); diff --git a/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-translate_2.4.2/angular-translate.js b/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-translate_2.4.2/angular-translate.js index 46bcb55fd44ef7656829324be46de477acdb0fc5..478a41b371da9865841e12a6f5b3cd4a98255381 100644 --- a/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-translate_2.4.2/angular-translate.js +++ b/pear-modules/pear-process/src/main/resources/static/editor-app/libs/angular-translate_2.4.2/angular-translate.js @@ -4,957 +4,971 @@ * Copyright (c) 2014 ; Licensed MIT */ angular.module('pascalprecht.translate', ['ng']).run([ - '$translate', - function ($translate) { - var key = $translate.storageKey(), storage = $translate.storage(); - if (storage) { - if (!storage.get(key)) { - if (angular.isString($translate.preferredLanguage())) { - $translate.use($translate.preferredLanguage()); - } else { - storage.set(key, $translate.use()); + '$translate', + function ($translate) { + var key = $translate.storageKey(), storage = $translate.storage(); + if (storage) { + if (!storage.get(key)) { + if (angular.isString($translate.preferredLanguage())) { + $translate.use($translate.preferredLanguage()); + } else { + storage.set(key, $translate.use()); + } + } else { + $translate.use(storage.get(key)); + } + } else if (angular.isString($translate.preferredLanguage())) { + $translate.use($translate.preferredLanguage()); } - } else { - $translate.use(storage.get(key)); - } - } else if (angular.isString($translate.preferredLanguage())) { - $translate.use($translate.preferredLanguage()); } - } ]); angular.module('pascalprecht.translate').provider('$translate', [ - '$STORAGE_KEY', - function ($STORAGE_KEY) { - var $translationTable = {}, $preferredLanguage, $availableLanguageKeys = [], $languageKeyAliases, $fallbackLanguage, $fallbackWasString, $uses, $nextLang, $storageFactory, $storageKey = $STORAGE_KEY, $storagePrefix, $missingTranslationHandlerFactory, $interpolationFactory, $interpolatorFactories = [], $interpolationSanitizationStrategy = false, $loaderFactory, $cloakClassName = 'translate-cloak', $loaderOptions, $notFoundIndicatorLeft, $notFoundIndicatorRight, $postCompilingEnabled = false, NESTED_OBJECT_DELIMITER = '.', loaderCache; - var version = '2.4.2'; - var getLocale = function () { - var nav = window.navigator; - return ((angular.isArray(nav.languages) ? nav.languages[0] : nav.language || nav.browserLanguage || nav.systemLanguage || nav.userLanguage) || '').split('-').join('_'); - }; - var indexOf = function (array, searchElement) { - for (var i = 0, len = array.length; i < len; i++) { - if (array[i] === searchElement) { - return i; - } - } - return -1; - }; - var trim = function () { - return this.replace(/^\s+|\s+$/g, ''); - }; - var negotiateLocale = function (preferred) { - var avail = [], locale = angular.lowercase(preferred), i = 0, n = $availableLanguageKeys.length; - for (; i < n; i++) { - avail.push(angular.lowercase($availableLanguageKeys[i])); - } - if (indexOf(avail, locale) > -1) { - return preferred; - } - if ($languageKeyAliases) { - var alias; - for (var langKeyAlias in $languageKeyAliases) { - var hasWildcardKey = false; - var hasExactKey = Object.prototype.hasOwnProperty.call($languageKeyAliases, langKeyAlias) && angular.lowercase(langKeyAlias) === angular.lowercase(preferred); - if (langKeyAlias.slice(-1) === '*') { - hasWildcardKey = langKeyAlias.slice(0, -1) === preferred.slice(0, langKeyAlias.length - 1); - } - if (hasExactKey || hasWildcardKey) { - alias = $languageKeyAliases[langKeyAlias]; - if (indexOf(avail, angular.lowercase(alias)) > -1) { - return alias; - } - } - } - } - var parts = preferred.split('_'); - if (parts.length > 1 && indexOf(avail, angular.lowercase(parts[0])) > -1) { - return parts[0]; - } - return preferred; - }; - var translations = function (langKey, translationTable) { - if (!langKey && !translationTable) { - return $translationTable; - } - if (langKey && !translationTable) { - if (angular.isString(langKey)) { - return $translationTable[langKey]; - } - } else { - if (!angular.isObject($translationTable[langKey])) { - $translationTable[langKey] = {}; - } - angular.extend($translationTable[langKey], flatObject(translationTable)); - } - return this; - }; - this.translations = translations; - this.cloakClassName = function (name) { - if (!name) { - return $cloakClassName; - } - $cloakClassName = name; - return this; - }; - var flatObject = function (data, path, result, prevKey) { - var key, keyWithPath, keyWithShortPath, val; - if (!path) { - path = []; - } - if (!result) { - result = {}; - } - for (key in data) { - if (!Object.prototype.hasOwnProperty.call(data, key)) { - continue; - } - val = data[key]; - if (angular.isObject(val)) { - flatObject(val, path.concat(key), result, key); - } else { - keyWithPath = path.length ? '' + path.join(NESTED_OBJECT_DELIMITER) + NESTED_OBJECT_DELIMITER + key : key; - if (path.length && key === prevKey) { - keyWithShortPath = '' + path.join(NESTED_OBJECT_DELIMITER); - result[keyWithShortPath] = '@:' + keyWithPath; - } - result[keyWithPath] = val; - } - } - return result; - }; - this.addInterpolation = function (factory) { - $interpolatorFactories.push(factory); - return this; - }; - this.useMessageFormatInterpolation = function () { - return this.useInterpolation('$translateMessageFormatInterpolation'); - }; - this.useInterpolation = function (factory) { - $interpolationFactory = factory; - return this; - }; - this.useSanitizeValueStrategy = function (value) { - $interpolationSanitizationStrategy = value; - return this; - }; - this.preferredLanguage = function (langKey) { - setupPreferredLanguage(langKey); - return this; - }; - var setupPreferredLanguage = function (langKey) { - if (langKey) { - $preferredLanguage = langKey; - } - return $preferredLanguage; - }; - this.translationNotFoundIndicator = function (indicator) { - this.translationNotFoundIndicatorLeft(indicator); - this.translationNotFoundIndicatorRight(indicator); - return this; - }; - this.translationNotFoundIndicatorLeft = function (indicator) { - if (!indicator) { - return $notFoundIndicatorLeft; - } - $notFoundIndicatorLeft = indicator; - return this; - }; - this.translationNotFoundIndicatorRight = function (indicator) { - if (!indicator) { - return $notFoundIndicatorRight; - } - $notFoundIndicatorRight = indicator; - return this; - }; - this.fallbackLanguage = function (langKey) { - fallbackStack(langKey); - return this; - }; - var fallbackStack = function (langKey) { - if (langKey) { - if (angular.isString(langKey)) { - $fallbackWasString = true; - $fallbackLanguage = [langKey]; - } else if (angular.isArray(langKey)) { - $fallbackWasString = false; - $fallbackLanguage = langKey; - } - if (angular.isString($preferredLanguage) && indexOf($fallbackLanguage, $preferredLanguage) < 0) { - $fallbackLanguage.push($preferredLanguage); - } - return this; - } else { - if ($fallbackWasString) { - return $fallbackLanguage[0]; - } else { - return $fallbackLanguage; - } - } - }; - this.use = function (langKey) { - if (langKey) { - if (!$translationTable[langKey] && !$loaderFactory) { - throw new Error('$translateProvider couldn\'t find translationTable for langKey: \'' + langKey + '\''); - } - $uses = langKey; - return this; - } - return $uses; - }; - var storageKey = function (key) { - if (!key) { - if ($storagePrefix) { - return $storagePrefix + $storageKey; - } - return $storageKey; - } - $storageKey = key; - }; - this.storageKey = storageKey; - this.useUrlLoader = function (url, options) { - return this.useLoader('$translateUrlLoader', angular.extend({ url: url }, options)); - }; - this.useStaticFilesLoader = function (options) { - return this.useLoader('$translateStaticFilesLoader', options); - }; - this.useLoader = function (loaderFactory, options) { - $loaderFactory = loaderFactory; - $loaderOptions = options || {}; - return this; - }; - this.useLocalStorage = function () { - return this.useStorage('$translateLocalStorage'); - }; - this.useCookieStorage = function () { - return this.useStorage('$translateCookieStorage'); - }; - this.useStorage = function (storageFactory) { - $storageFactory = storageFactory; - return this; - }; - this.storagePrefix = function (prefix) { - if (!prefix) { - return prefix; - } - $storagePrefix = prefix; - return this; - }; - this.useMissingTranslationHandlerLog = function () { - return this.useMissingTranslationHandler('$translateMissingTranslationHandlerLog'); - }; - this.useMissingTranslationHandler = function (factory) { - $missingTranslationHandlerFactory = factory; - return this; - }; - this.usePostCompiling = function (value) { - $postCompilingEnabled = !!value; - return this; - }; - this.determinePreferredLanguage = function (fn) { - var locale = fn && angular.isFunction(fn) ? fn() : getLocale(); - if (!$availableLanguageKeys.length) { - $preferredLanguage = locale; - } else { - $preferredLanguage = negotiateLocale(locale); - } - return this; - }; - this.registerAvailableLanguageKeys = function (languageKeys, aliases) { - if (languageKeys) { - $availableLanguageKeys = languageKeys; - if (aliases) { - $languageKeyAliases = aliases; - } - return this; - } - return $availableLanguageKeys; - }; - this.useLoaderCache = function (cache) { - if (cache === false) { - loaderCache = undefined; - } else if (cache === true) { - loaderCache = true; - } else if (typeof cache === 'undefined') { - loaderCache = '$translationCache'; - } else if (cache) { - loaderCache = cache; - } - return this; - }; - this.$get = [ - '$log', - '$injector', - '$rootScope', - '$q', - function ($log, $injector, $rootScope, $q) { - var Storage, defaultInterpolator = $injector.get($interpolationFactory || '$translateDefaultInterpolation'), pendingLoader = false, interpolatorHashMap = {}, langPromises = {}, fallbackIndex, startFallbackIteration; - var $translate = function (translationId, interpolateParams, interpolationId) { - if (angular.isArray(translationId)) { - var translateAll = function (translationIds) { - var results = {}; - var promises = []; - var translate = function (translationId) { - var deferred = $q.defer(); - var regardless = function (value) { - results[translationId] = value; - deferred.resolve([ - translationId, - value - ]); - }; - $translate(translationId, interpolateParams, interpolationId).then(regardless, regardless); - return deferred.promise; - }; - for (var i = 0, c = translationIds.length; i < c; i++) { - promises.push(translate(translationIds[i])); - } - return $q.all(promises).then(function () { - return results; - }); - }; - return translateAll(translationId); - } - var deferred = $q.defer(); - if (translationId) { - translationId = trim.apply(translationId); - } - var promiseToWaitFor = function () { - var promise = $preferredLanguage ? langPromises[$preferredLanguage] : langPromises[$uses]; - fallbackIndex = 0; - if ($storageFactory && !promise) { - var langKey = Storage.get($storageKey); - promise = langPromises[langKey]; - if ($fallbackLanguage && $fallbackLanguage.length) { - var index = indexOf($fallbackLanguage, langKey); - fallbackIndex = index === 0 ? 1 : 0; - if (indexOf($fallbackLanguage, $preferredLanguage) < 0) { - $fallbackLanguage.push($preferredLanguage); - } + '$STORAGE_KEY', + function ($STORAGE_KEY) { + var $translationTable = {}, $preferredLanguage, $availableLanguageKeys = [], $languageKeyAliases, + $fallbackLanguage, $fallbackWasString, $uses, $nextLang, $storageFactory, $storageKey = $STORAGE_KEY, + $storagePrefix, $missingTranslationHandlerFactory, $interpolationFactory, $interpolatorFactories = [], + $interpolationSanitizationStrategy = false, $loaderFactory, $cloakClassName = 'translate-cloak', + $loaderOptions, $notFoundIndicatorLeft, $notFoundIndicatorRight, $postCompilingEnabled = false, + NESTED_OBJECT_DELIMITER = '.', loaderCache; + var version = '2.4.2'; + var getLocale = function () { + var nav = window.navigator; + return ((angular.isArray(nav.languages) ? nav.languages[0] : nav.language || nav.browserLanguage || nav.systemLanguage || nav.userLanguage) || '').split('-').join('_'); + }; + var indexOf = function (array, searchElement) { + for (var i = 0, len = array.length; i < len; i++) { + if (array[i] === searchElement) { + return i; } - } - return promise; - }(); - if (!promiseToWaitFor) { - determineTranslation(translationId, interpolateParams, interpolationId).then(deferred.resolve, deferred.reject); - } else { - promiseToWaitFor.then(function () { - determineTranslation(translationId, interpolateParams, interpolationId).then(deferred.resolve, deferred.reject); - }, deferred.reject); - } - return deferred.promise; - }; - var applyNotFoundIndicators = function (translationId) { - if ($notFoundIndicatorLeft) { - translationId = [ - $notFoundIndicatorLeft, - translationId - ].join(' '); - } - if ($notFoundIndicatorRight) { - translationId = [ - translationId, - $notFoundIndicatorRight - ].join(' '); - } - return translationId; - }; - var useLanguage = function (key) { - $uses = key; - $rootScope.$emit('$translateChangeSuccess', { language: key }); - if ($storageFactory) { - Storage.set($translate.storageKey(), $uses); - } - defaultInterpolator.setLocale($uses); - angular.forEach(interpolatorHashMap, function (interpolator, id) { - interpolatorHashMap[id].setLocale($uses); - }); - $rootScope.$emit('$translateChangeEnd', { language: key }); - }; - var loadAsync = function (key) { - if (!key) { - throw 'No language key specified for loading.'; - } - var deferred = $q.defer(); - $rootScope.$emit('$translateLoadingStart', { language: key }); - pendingLoader = true; - var cache = loaderCache; - if (typeof cache === 'string') { - cache = $injector.get(cache); - } - var loaderOptions = angular.extend({}, $loaderOptions, { - key: key, - $http: angular.extend({}, { cache: cache }, $loaderOptions.$http) - }); - $injector.get($loaderFactory)(loaderOptions).then(function (data) { - var translationTable = {}; - $rootScope.$emit('$translateLoadingSuccess', { language: key }); - if (angular.isArray(data)) { - angular.forEach(data, function (table) { - angular.extend(translationTable, flatObject(table)); - }); - } else { - angular.extend(translationTable, flatObject(data)); - } - pendingLoader = false; - deferred.resolve({ - key: key, - table: translationTable - }); - $rootScope.$emit('$translateLoadingEnd', { language: key }); - }, function (key) { - $rootScope.$emit('$translateLoadingError', { language: key }); - deferred.reject(key); - $rootScope.$emit('$translateLoadingEnd', { language: key }); - }); - return deferred.promise; - }; - if ($storageFactory) { - Storage = $injector.get($storageFactory); - if (!Storage.get || !Storage.set) { - throw new Error('Couldn\'t use storage \'' + $storageFactory + '\', missing get() or set() method!'); - } - } - if (angular.isFunction(defaultInterpolator.useSanitizeValueStrategy)) { - defaultInterpolator.useSanitizeValueStrategy($interpolationSanitizationStrategy); - } - if ($interpolatorFactories.length) { - angular.forEach($interpolatorFactories, function (interpolatorFactory) { - var interpolator = $injector.get(interpolatorFactory); - interpolator.setLocale($preferredLanguage || $uses); - if (angular.isFunction(interpolator.useSanitizeValueStrategy)) { - interpolator.useSanitizeValueStrategy($interpolationSanitizationStrategy); } - interpolatorHashMap[interpolator.getInterpolationIdentifier()] = interpolator; - }); - } - var getTranslationTable = function (langKey) { - var deferred = $q.defer(); - if (Object.prototype.hasOwnProperty.call($translationTable, langKey)) { - deferred.resolve($translationTable[langKey]); - } else if (langPromises[langKey]) { - langPromises[langKey].then(function (data) { - translations(data.key, data.table); - deferred.resolve(data.table); - }, deferred.reject); - } else { - deferred.reject(); - } - return deferred.promise; - }; - var getFallbackTranslation = function (langKey, translationId, interpolateParams, Interpolator) { - var deferred = $q.defer(); - getTranslationTable(langKey).then(function (translationTable) { - if (Object.prototype.hasOwnProperty.call(translationTable, translationId)) { - Interpolator.setLocale(langKey); - deferred.resolve(Interpolator.interpolate(translationTable[translationId], interpolateParams)); - Interpolator.setLocale($uses); - } else { - deferred.reject(); + return -1; + }; + var trim = function () { + return this.replace(/^\s+|\s+$/g, ''); + }; + var negotiateLocale = function (preferred) { + var avail = [], locale = angular.lowercase(preferred), i = 0, n = $availableLanguageKeys.length; + for (; i < n; i++) { + avail.push(angular.lowercase($availableLanguageKeys[i])); } - }, deferred.reject); - return deferred.promise; - }; - var getFallbackTranslationInstant = function (langKey, translationId, interpolateParams, Interpolator) { - var result, translationTable = $translationTable[langKey]; - if (Object.prototype.hasOwnProperty.call(translationTable, translationId)) { - Interpolator.setLocale(langKey); - result = Interpolator.interpolate(translationTable[translationId], interpolateParams); - Interpolator.setLocale($uses); - } - return result; - }; - var translateByHandler = function (translationId) { - if ($missingTranslationHandlerFactory) { - var resultString = $injector.get($missingTranslationHandlerFactory)(translationId, $uses); - if (resultString !== undefined) { - return resultString; - } else { - return translationId; + if (indexOf(avail, locale) > -1) { + return preferred; } - } else { - return translationId; - } - }; - var resolveForFallbackLanguage = function (fallbackLanguageIndex, translationId, interpolateParams, Interpolator) { - var deferred = $q.defer(); - if (fallbackLanguageIndex < $fallbackLanguage.length) { - var langKey = $fallbackLanguage[fallbackLanguageIndex]; - getFallbackTranslation(langKey, translationId, interpolateParams, Interpolator).then(deferred.resolve, function () { - resolveForFallbackLanguage(fallbackLanguageIndex + 1, translationId, interpolateParams, Interpolator).then(deferred.resolve); - }); - } else { - deferred.resolve(translateByHandler(translationId)); - } - return deferred.promise; - }; - var resolveForFallbackLanguageInstant = function (fallbackLanguageIndex, translationId, interpolateParams, Interpolator) { - var result; - if (fallbackLanguageIndex < $fallbackLanguage.length) { - var langKey = $fallbackLanguage[fallbackLanguageIndex]; - result = getFallbackTranslationInstant(langKey, translationId, interpolateParams, Interpolator); - if (!result) { - result = resolveForFallbackLanguageInstant(fallbackLanguageIndex + 1, translationId, interpolateParams, Interpolator); + if ($languageKeyAliases) { + var alias; + for (var langKeyAlias in $languageKeyAliases) { + var hasWildcardKey = false; + var hasExactKey = Object.prototype.hasOwnProperty.call($languageKeyAliases, langKeyAlias) && angular.lowercase(langKeyAlias) === angular.lowercase(preferred); + if (langKeyAlias.slice(-1) === '*') { + hasWildcardKey = langKeyAlias.slice(0, -1) === preferred.slice(0, langKeyAlias.length - 1); + } + if (hasExactKey || hasWildcardKey) { + alias = $languageKeyAliases[langKeyAlias]; + if (indexOf(avail, angular.lowercase(alias)) > -1) { + return alias; + } + } + } } - } - return result; - }; - var fallbackTranslation = function (translationId, interpolateParams, Interpolator) { - return resolveForFallbackLanguage(startFallbackIteration > 0 ? startFallbackIteration : fallbackIndex, translationId, interpolateParams, Interpolator); - }; - var fallbackTranslationInstant = function (translationId, interpolateParams, Interpolator) { - return resolveForFallbackLanguageInstant(startFallbackIteration > 0 ? startFallbackIteration : fallbackIndex, translationId, interpolateParams, Interpolator); - }; - var determineTranslation = function (translationId, interpolateParams, interpolationId) { - var deferred = $q.defer(); - var table = $uses ? $translationTable[$uses] : $translationTable, Interpolator = interpolationId ? interpolatorHashMap[interpolationId] : defaultInterpolator; - if (table && Object.prototype.hasOwnProperty.call(table, translationId)) { - var translation = table[translationId]; - if (translation.substr(0, 2) === '@:') { - $translate(translation.substr(2), interpolateParams, interpolationId).then(deferred.resolve, deferred.reject); - } else { - deferred.resolve(Interpolator.interpolate(translation, interpolateParams)); + var parts = preferred.split('_'); + if (parts.length > 1 && indexOf(avail, angular.lowercase(parts[0])) > -1) { + return parts[0]; } - } else { - var missingTranslationHandlerTranslation; - if ($missingTranslationHandlerFactory && !pendingLoader) { - missingTranslationHandlerTranslation = translateByHandler(translationId); + return preferred; + }; + var translations = function (langKey, translationTable) { + if (!langKey && !translationTable) { + return $translationTable; } - if ($uses && $fallbackLanguage && $fallbackLanguage.length) { - fallbackTranslation(translationId, interpolateParams, Interpolator).then(function (translation) { - deferred.resolve(translation); - }, function (_translationId) { - deferred.reject(applyNotFoundIndicators(_translationId)); - }); - } else if ($missingTranslationHandlerFactory && !pendingLoader && missingTranslationHandlerTranslation) { - deferred.resolve(missingTranslationHandlerTranslation); + if (langKey && !translationTable) { + if (angular.isString(langKey)) { + return $translationTable[langKey]; + } } else { - deferred.reject(applyNotFoundIndicators(translationId)); + if (!angular.isObject($translationTable[langKey])) { + $translationTable[langKey] = {}; + } + angular.extend($translationTable[langKey], flatObject(translationTable)); } - } - return deferred.promise; - }; - var determineTranslationInstant = function (translationId, interpolateParams, interpolationId) { - var result, table = $uses ? $translationTable[$uses] : $translationTable, Interpolator = interpolationId ? interpolatorHashMap[interpolationId] : defaultInterpolator; - if (table && Object.prototype.hasOwnProperty.call(table, translationId)) { - var translation = table[translationId]; - if (translation.substr(0, 2) === '@:') { - result = determineTranslationInstant(translation.substr(2), interpolateParams, interpolationId); - } else { - result = Interpolator.interpolate(translation, interpolateParams); + return this; + }; + this.translations = translations; + this.cloakClassName = function (name) { + if (!name) { + return $cloakClassName; + } + $cloakClassName = name; + return this; + }; + var flatObject = function (data, path, result, prevKey) { + var key, keyWithPath, keyWithShortPath, val; + if (!path) { + path = []; } - } else { - var missingTranslationHandlerTranslation; - if ($missingTranslationHandlerFactory && !pendingLoader) { - missingTranslationHandlerTranslation = translateByHandler(translationId); + if (!result) { + result = {}; } - if ($uses && $fallbackLanguage && $fallbackLanguage.length) { - fallbackIndex = 0; - result = fallbackTranslationInstant(translationId, interpolateParams, Interpolator); - } else if ($missingTranslationHandlerFactory && !pendingLoader && missingTranslationHandlerTranslation) { - result = missingTranslationHandlerTranslation; - } else { - result = applyNotFoundIndicators(translationId); + for (key in data) { + if (!Object.prototype.hasOwnProperty.call(data, key)) { + continue; + } + val = data[key]; + if (angular.isObject(val)) { + flatObject(val, path.concat(key), result, key); + } else { + keyWithPath = path.length ? '' + path.join(NESTED_OBJECT_DELIMITER) + NESTED_OBJECT_DELIMITER + key : key; + if (path.length && key === prevKey) { + keyWithShortPath = '' + path.join(NESTED_OBJECT_DELIMITER); + result[keyWithShortPath] = '@:' + keyWithPath; + } + result[keyWithPath] = val; + } } - } - return result; + return result; + }; + this.addInterpolation = function (factory) { + $interpolatorFactories.push(factory); + return this; + }; + this.useMessageFormatInterpolation = function () { + return this.useInterpolation('$translateMessageFormatInterpolation'); + }; + this.useInterpolation = function (factory) { + $interpolationFactory = factory; + return this; }; - $translate.preferredLanguage = function (langKey) { - if (langKey) { + this.useSanitizeValueStrategy = function (value) { + $interpolationSanitizationStrategy = value; + return this; + }; + this.preferredLanguage = function (langKey) { setupPreferredLanguage(langKey); - } - return $preferredLanguage; + return this; + }; + var setupPreferredLanguage = function (langKey) { + if (langKey) { + $preferredLanguage = langKey; + } + return $preferredLanguage; + }; + this.translationNotFoundIndicator = function (indicator) { + this.translationNotFoundIndicatorLeft(indicator); + this.translationNotFoundIndicatorRight(indicator); + return this; }; - $translate.cloakClassName = function () { - return $cloakClassName; + this.translationNotFoundIndicatorLeft = function (indicator) { + if (!indicator) { + return $notFoundIndicatorLeft; + } + $notFoundIndicatorLeft = indicator; + return this; + }; + this.translationNotFoundIndicatorRight = function (indicator) { + if (!indicator) { + return $notFoundIndicatorRight; + } + $notFoundIndicatorRight = indicator; + return this; }; - $translate.fallbackLanguage = function (langKey) { - if (langKey !== undefined && langKey !== null) { + this.fallbackLanguage = function (langKey) { fallbackStack(langKey); - if ($loaderFactory) { - if ($fallbackLanguage && $fallbackLanguage.length) { - for (var i = 0, len = $fallbackLanguage.length; i < len; i++) { - if (!langPromises[$fallbackLanguage[i]]) { - langPromises[$fallbackLanguage[i]] = loadAsync($fallbackLanguage[i]); - } + return this; + }; + var fallbackStack = function (langKey) { + if (langKey) { + if (angular.isString(langKey)) { + $fallbackWasString = true; + $fallbackLanguage = [langKey]; + } else if (angular.isArray(langKey)) { + $fallbackWasString = false; + $fallbackLanguage = langKey; } - } - } - $translate.use($translate.use()); - } - if ($fallbackWasString) { - return $fallbackLanguage[0]; - } else { - return $fallbackLanguage; - } - }; - $translate.useFallbackLanguage = function (langKey) { - if (langKey !== undefined && langKey !== null) { - if (!langKey) { - startFallbackIteration = 0; + if (angular.isString($preferredLanguage) && indexOf($fallbackLanguage, $preferredLanguage) < 0) { + $fallbackLanguage.push($preferredLanguage); + } + return this; } else { - var langKeyPosition = indexOf($fallbackLanguage, langKey); - if (langKeyPosition > -1) { - startFallbackIteration = langKeyPosition; - } + if ($fallbackWasString) { + return $fallbackLanguage[0]; + } else { + return $fallbackLanguage; + } } - } }; - $translate.proposedLanguage = function () { - return $nextLang; + this.use = function (langKey) { + if (langKey) { + if (!$translationTable[langKey] && !$loaderFactory) { + throw new Error('$translateProvider couldn\'t find translationTable for langKey: \'' + langKey + '\''); + } + $uses = langKey; + return this; + } + return $uses; + }; + var storageKey = function (key) { + if (!key) { + if ($storagePrefix) { + return $storagePrefix + $storageKey; + } + return $storageKey; + } + $storageKey = key; }; - $translate.storage = function () { - return Storage; + this.storageKey = storageKey; + this.useUrlLoader = function (url, options) { + return this.useLoader('$translateUrlLoader', angular.extend({url: url}, options)); }; - $translate.use = function (key) { - if (!key) { - return $uses; - } - var deferred = $q.defer(); - $rootScope.$emit('$translateChangeStart', { language: key }); - var aliasedKey = negotiateLocale(key); - if (aliasedKey) { - key = aliasedKey; - } - if (!$translationTable[key] && $loaderFactory && !langPromises[key]) { - $nextLang = key; - langPromises[key] = loadAsync(key).then(function (translation) { - translations(translation.key, translation.table); - deferred.resolve(translation.key); - useLanguage(translation.key); - if ($nextLang === key) { - $nextLang = undefined; - } - }, function (key) { - if ($nextLang === key) { - $nextLang = undefined; - } - $rootScope.$emit('$translateChangeError', { language: key }); - deferred.reject(key); - $rootScope.$emit('$translateChangeEnd', { language: key }); - }); - } else { - deferred.resolve(key); - useLanguage(key); - } - return deferred.promise; - }; - $translate.storageKey = function () { - return storageKey(); - }; - $translate.isPostCompilingEnabled = function () { - return $postCompilingEnabled; - }; - $translate.refresh = function (langKey) { - if (!$loaderFactory) { - throw new Error('Couldn\'t refresh translation table, no loader registered!'); - } - var deferred = $q.defer(); - function resolve() { - deferred.resolve(); - $rootScope.$emit('$translateRefreshEnd', { language: langKey }); - } - function reject() { - deferred.reject(); - $rootScope.$emit('$translateRefreshEnd', { language: langKey }); - } - $rootScope.$emit('$translateRefreshStart', { language: langKey }); - if (!langKey) { - var tables = [], loadingKeys = {}; - if ($fallbackLanguage && $fallbackLanguage.length) { - for (var i = 0, len = $fallbackLanguage.length; i < len; i++) { - tables.push(loadAsync($fallbackLanguage[i])); - loadingKeys[$fallbackLanguage[i]] = true; - } + this.useStaticFilesLoader = function (options) { + return this.useLoader('$translateStaticFilesLoader', options); + }; + this.useLoader = function (loaderFactory, options) { + $loaderFactory = loaderFactory; + $loaderOptions = options || {}; + return this; + }; + this.useLocalStorage = function () { + return this.useStorage('$translateLocalStorage'); + }; + this.useCookieStorage = function () { + return this.useStorage('$translateCookieStorage'); + }; + this.useStorage = function (storageFactory) { + $storageFactory = storageFactory; + return this; + }; + this.storagePrefix = function (prefix) { + if (!prefix) { + return prefix; } - if ($uses && !loadingKeys[$uses]) { - tables.push(loadAsync($uses)); + $storagePrefix = prefix; + return this; + }; + this.useMissingTranslationHandlerLog = function () { + return this.useMissingTranslationHandler('$translateMissingTranslationHandlerLog'); + }; + this.useMissingTranslationHandler = function (factory) { + $missingTranslationHandlerFactory = factory; + return this; + }; + this.usePostCompiling = function (value) { + $postCompilingEnabled = !!value; + return this; + }; + this.determinePreferredLanguage = function (fn) { + var locale = fn && angular.isFunction(fn) ? fn() : getLocale(); + if (!$availableLanguageKeys.length) { + $preferredLanguage = locale; + } else { + $preferredLanguage = negotiateLocale(locale); } - $q.all(tables).then(function (tableData) { - angular.forEach(tableData, function (data) { - if ($translationTable[data.key]) { - delete $translationTable[data.key]; + return this; + }; + this.registerAvailableLanguageKeys = function (languageKeys, aliases) { + if (languageKeys) { + $availableLanguageKeys = languageKeys; + if (aliases) { + $languageKeyAliases = aliases; } - translations(data.key, data.table); - }); - if ($uses) { - useLanguage($uses); - } - resolve(); - }); - } else if ($translationTable[langKey]) { - loadAsync(langKey).then(function (data) { - translations(data.key, data.table); - if (langKey === $uses) { - useLanguage($uses); - } - resolve(); - }, reject); - } else { - reject(); - } - return deferred.promise; - }; - $translate.instant = function (translationId, interpolateParams, interpolationId) { - if (translationId === null || angular.isUndefined(translationId)) { - return translationId; - } - if (angular.isArray(translationId)) { - var results = {}; - for (var i = 0, c = translationId.length; i < c; i++) { - results[translationId[i]] = $translate.instant(translationId[i], interpolateParams, interpolationId); - } - return results; - } - if (angular.isString(translationId) && translationId.length < 1) { - return translationId; - } - if (translationId) { - translationId = trim.apply(translationId); - } - var result, possibleLangKeys = []; - if ($preferredLanguage) { - possibleLangKeys.push($preferredLanguage); - } - if ($uses) { - possibleLangKeys.push($uses); - } - if ($fallbackLanguage && $fallbackLanguage.length) { - possibleLangKeys = possibleLangKeys.concat($fallbackLanguage); - } - for (var j = 0, d = possibleLangKeys.length; j < d; j++) { - var possibleLangKey = possibleLangKeys[j]; - if ($translationTable[possibleLangKey]) { - if (typeof $translationTable[possibleLangKey][translationId] !== 'undefined') { - result = determineTranslationInstant(translationId, interpolateParams, interpolationId); - } + return this; } - if (typeof result !== 'undefined') { - break; - } - } - if (!result && result !== '') { - result = defaultInterpolator.interpolate(translationId, interpolateParams); - if ($missingTranslationHandlerFactory && !pendingLoader) { - result = translateByHandler(translationId); + return $availableLanguageKeys; + }; + this.useLoaderCache = function (cache) { + if (cache === false) { + loaderCache = undefined; + } else if (cache === true) { + loaderCache = true; + } else if (typeof cache === 'undefined') { + loaderCache = '$translationCache'; + } else if (cache) { + loaderCache = cache; } - } - return result; - }; - $translate.versionInfo = function () { - return version; - }; - $translate.loaderCache = function () { - return loaderCache; - }; - if ($loaderFactory) { - if (angular.equals($translationTable, {})) { - $translate.use($translate.use()); - } - if ($fallbackLanguage && $fallbackLanguage.length) { - var processAsyncResult = function (translation) { - translations(translation.key, translation.table); - $rootScope.$emit('$translateChangeEnd', { language: translation.key }); - }; - for (var i = 0, len = $fallbackLanguage.length; i < len; i++) { - langPromises[$fallbackLanguage[i]] = loadAsync($fallbackLanguage[i]).then(processAsyncResult); + return this; + }; + this.$get = [ + '$log', + '$injector', + '$rootScope', + '$q', + function ($log, $injector, $rootScope, $q) { + var Storage, + defaultInterpolator = $injector.get($interpolationFactory || '$translateDefaultInterpolation'), + pendingLoader = false, interpolatorHashMap = {}, langPromises = {}, fallbackIndex, + startFallbackIteration; + var $translate = function (translationId, interpolateParams, interpolationId) { + if (angular.isArray(translationId)) { + var translateAll = function (translationIds) { + var results = {}; + var promises = []; + var translate = function (translationId) { + var deferred = $q.defer(); + var regardless = function (value) { + results[translationId] = value; + deferred.resolve([ + translationId, + value + ]); + }; + $translate(translationId, interpolateParams, interpolationId).then(regardless, regardless); + return deferred.promise; + }; + for (var i = 0, c = translationIds.length; i < c; i++) { + promises.push(translate(translationIds[i])); + } + return $q.all(promises).then(function () { + return results; + }); + }; + return translateAll(translationId); + } + var deferred = $q.defer(); + if (translationId) { + translationId = trim.apply(translationId); + } + var promiseToWaitFor = function () { + var promise = $preferredLanguage ? langPromises[$preferredLanguage] : langPromises[$uses]; + fallbackIndex = 0; + if ($storageFactory && !promise) { + var langKey = Storage.get($storageKey); + promise = langPromises[langKey]; + if ($fallbackLanguage && $fallbackLanguage.length) { + var index = indexOf($fallbackLanguage, langKey); + fallbackIndex = index === 0 ? 1 : 0; + if (indexOf($fallbackLanguage, $preferredLanguage) < 0) { + $fallbackLanguage.push($preferredLanguage); + } + } + } + return promise; + }(); + if (!promiseToWaitFor) { + determineTranslation(translationId, interpolateParams, interpolationId).then(deferred.resolve, deferred.reject); + } else { + promiseToWaitFor.then(function () { + determineTranslation(translationId, interpolateParams, interpolationId).then(deferred.resolve, deferred.reject); + }, deferred.reject); + } + return deferred.promise; + }; + var applyNotFoundIndicators = function (translationId) { + if ($notFoundIndicatorLeft) { + translationId = [ + $notFoundIndicatorLeft, + translationId + ].join(' '); + } + if ($notFoundIndicatorRight) { + translationId = [ + translationId, + $notFoundIndicatorRight + ].join(' '); + } + return translationId; + }; + var useLanguage = function (key) { + $uses = key; + $rootScope.$emit('$translateChangeSuccess', {language: key}); + if ($storageFactory) { + Storage.set($translate.storageKey(), $uses); + } + defaultInterpolator.setLocale($uses); + angular.forEach(interpolatorHashMap, function (interpolator, id) { + interpolatorHashMap[id].setLocale($uses); + }); + $rootScope.$emit('$translateChangeEnd', {language: key}); + }; + var loadAsync = function (key) { + if (!key) { + throw 'No language key specified for loading.'; + } + var deferred = $q.defer(); + $rootScope.$emit('$translateLoadingStart', {language: key}); + pendingLoader = true; + var cache = loaderCache; + if (typeof cache === 'string') { + cache = $injector.get(cache); + } + var loaderOptions = angular.extend({}, $loaderOptions, { + key: key, + $http: angular.extend({}, {cache: cache}, $loaderOptions.$http) + }); + $injector.get($loaderFactory)(loaderOptions).then(function (data) { + var translationTable = {}; + $rootScope.$emit('$translateLoadingSuccess', {language: key}); + if (angular.isArray(data)) { + angular.forEach(data, function (table) { + angular.extend(translationTable, flatObject(table)); + }); + } else { + angular.extend(translationTable, flatObject(data)); + } + pendingLoader = false; + deferred.resolve({ + key: key, + table: translationTable + }); + $rootScope.$emit('$translateLoadingEnd', {language: key}); + }, function (key) { + $rootScope.$emit('$translateLoadingError', {language: key}); + deferred.reject(key); + $rootScope.$emit('$translateLoadingEnd', {language: key}); + }); + return deferred.promise; + }; + if ($storageFactory) { + Storage = $injector.get($storageFactory); + if (!Storage.get || !Storage.set) { + throw new Error('Couldn\'t use storage \'' + $storageFactory + '\', missing get() or set() method!'); + } + } + if (angular.isFunction(defaultInterpolator.useSanitizeValueStrategy)) { + defaultInterpolator.useSanitizeValueStrategy($interpolationSanitizationStrategy); + } + if ($interpolatorFactories.length) { + angular.forEach($interpolatorFactories, function (interpolatorFactory) { + var interpolator = $injector.get(interpolatorFactory); + interpolator.setLocale($preferredLanguage || $uses); + if (angular.isFunction(interpolator.useSanitizeValueStrategy)) { + interpolator.useSanitizeValueStrategy($interpolationSanitizationStrategy); + } + interpolatorHashMap[interpolator.getInterpolationIdentifier()] = interpolator; + }); + } + var getTranslationTable = function (langKey) { + var deferred = $q.defer(); + if (Object.prototype.hasOwnProperty.call($translationTable, langKey)) { + deferred.resolve($translationTable[langKey]); + } else if (langPromises[langKey]) { + langPromises[langKey].then(function (data) { + translations(data.key, data.table); + deferred.resolve(data.table); + }, deferred.reject); + } else { + deferred.reject(); + } + return deferred.promise; + }; + var getFallbackTranslation = function (langKey, translationId, interpolateParams, Interpolator) { + var deferred = $q.defer(); + getTranslationTable(langKey).then(function (translationTable) { + if (Object.prototype.hasOwnProperty.call(translationTable, translationId)) { + Interpolator.setLocale(langKey); + deferred.resolve(Interpolator.interpolate(translationTable[translationId], interpolateParams)); + Interpolator.setLocale($uses); + } else { + deferred.reject(); + } + }, deferred.reject); + return deferred.promise; + }; + var getFallbackTranslationInstant = function (langKey, translationId, interpolateParams, Interpolator) { + var result, translationTable = $translationTable[langKey]; + if (Object.prototype.hasOwnProperty.call(translationTable, translationId)) { + Interpolator.setLocale(langKey); + result = Interpolator.interpolate(translationTable[translationId], interpolateParams); + Interpolator.setLocale($uses); + } + return result; + }; + var translateByHandler = function (translationId) { + if ($missingTranslationHandlerFactory) { + var resultString = $injector.get($missingTranslationHandlerFactory)(translationId, $uses); + if (resultString !== undefined) { + return resultString; + } else { + return translationId; + } + } else { + return translationId; + } + }; + var resolveForFallbackLanguage = function (fallbackLanguageIndex, translationId, interpolateParams, Interpolator) { + var deferred = $q.defer(); + if (fallbackLanguageIndex < $fallbackLanguage.length) { + var langKey = $fallbackLanguage[fallbackLanguageIndex]; + getFallbackTranslation(langKey, translationId, interpolateParams, Interpolator).then(deferred.resolve, function () { + resolveForFallbackLanguage(fallbackLanguageIndex + 1, translationId, interpolateParams, Interpolator).then(deferred.resolve); + }); + } else { + deferred.resolve(translateByHandler(translationId)); + } + return deferred.promise; + }; + var resolveForFallbackLanguageInstant = function (fallbackLanguageIndex, translationId, interpolateParams, Interpolator) { + var result; + if (fallbackLanguageIndex < $fallbackLanguage.length) { + var langKey = $fallbackLanguage[fallbackLanguageIndex]; + result = getFallbackTranslationInstant(langKey, translationId, interpolateParams, Interpolator); + if (!result) { + result = resolveForFallbackLanguageInstant(fallbackLanguageIndex + 1, translationId, interpolateParams, Interpolator); + } + } + return result; + }; + var fallbackTranslation = function (translationId, interpolateParams, Interpolator) { + return resolveForFallbackLanguage(startFallbackIteration > 0 ? startFallbackIteration : fallbackIndex, translationId, interpolateParams, Interpolator); + }; + var fallbackTranslationInstant = function (translationId, interpolateParams, Interpolator) { + return resolveForFallbackLanguageInstant(startFallbackIteration > 0 ? startFallbackIteration : fallbackIndex, translationId, interpolateParams, Interpolator); + }; + var determineTranslation = function (translationId, interpolateParams, interpolationId) { + var deferred = $q.defer(); + var table = $uses ? $translationTable[$uses] : $translationTable, + Interpolator = interpolationId ? interpolatorHashMap[interpolationId] : defaultInterpolator; + if (table && Object.prototype.hasOwnProperty.call(table, translationId)) { + var translation = table[translationId]; + if (translation.substr(0, 2) === '@:') { + $translate(translation.substr(2), interpolateParams, interpolationId).then(deferred.resolve, deferred.reject); + } else { + deferred.resolve(Interpolator.interpolate(translation, interpolateParams)); + } + } else { + var missingTranslationHandlerTranslation; + if ($missingTranslationHandlerFactory && !pendingLoader) { + missingTranslationHandlerTranslation = translateByHandler(translationId); + } + if ($uses && $fallbackLanguage && $fallbackLanguage.length) { + fallbackTranslation(translationId, interpolateParams, Interpolator).then(function (translation) { + deferred.resolve(translation); + }, function (_translationId) { + deferred.reject(applyNotFoundIndicators(_translationId)); + }); + } else if ($missingTranslationHandlerFactory && !pendingLoader && missingTranslationHandlerTranslation) { + deferred.resolve(missingTranslationHandlerTranslation); + } else { + deferred.reject(applyNotFoundIndicators(translationId)); + } + } + return deferred.promise; + }; + var determineTranslationInstant = function (translationId, interpolateParams, interpolationId) { + var result, table = $uses ? $translationTable[$uses] : $translationTable, + Interpolator = interpolationId ? interpolatorHashMap[interpolationId] : defaultInterpolator; + if (table && Object.prototype.hasOwnProperty.call(table, translationId)) { + var translation = table[translationId]; + if (translation.substr(0, 2) === '@:') { + result = determineTranslationInstant(translation.substr(2), interpolateParams, interpolationId); + } else { + result = Interpolator.interpolate(translation, interpolateParams); + } + } else { + var missingTranslationHandlerTranslation; + if ($missingTranslationHandlerFactory && !pendingLoader) { + missingTranslationHandlerTranslation = translateByHandler(translationId); + } + if ($uses && $fallbackLanguage && $fallbackLanguage.length) { + fallbackIndex = 0; + result = fallbackTranslationInstant(translationId, interpolateParams, Interpolator); + } else if ($missingTranslationHandlerFactory && !pendingLoader && missingTranslationHandlerTranslation) { + result = missingTranslationHandlerTranslation; + } else { + result = applyNotFoundIndicators(translationId); + } + } + return result; + }; + $translate.preferredLanguage = function (langKey) { + if (langKey) { + setupPreferredLanguage(langKey); + } + return $preferredLanguage; + }; + $translate.cloakClassName = function () { + return $cloakClassName; + }; + $translate.fallbackLanguage = function (langKey) { + if (langKey !== undefined && langKey !== null) { + fallbackStack(langKey); + if ($loaderFactory) { + if ($fallbackLanguage && $fallbackLanguage.length) { + for (var i = 0, len = $fallbackLanguage.length; i < len; i++) { + if (!langPromises[$fallbackLanguage[i]]) { + langPromises[$fallbackLanguage[i]] = loadAsync($fallbackLanguage[i]); + } + } + } + } + $translate.use($translate.use()); + } + if ($fallbackWasString) { + return $fallbackLanguage[0]; + } else { + return $fallbackLanguage; + } + }; + $translate.useFallbackLanguage = function (langKey) { + if (langKey !== undefined && langKey !== null) { + if (!langKey) { + startFallbackIteration = 0; + } else { + var langKeyPosition = indexOf($fallbackLanguage, langKey); + if (langKeyPosition > -1) { + startFallbackIteration = langKeyPosition; + } + } + } + }; + $translate.proposedLanguage = function () { + return $nextLang; + }; + $translate.storage = function () { + return Storage; + }; + $translate.use = function (key) { + if (!key) { + return $uses; + } + var deferred = $q.defer(); + $rootScope.$emit('$translateChangeStart', {language: key}); + var aliasedKey = negotiateLocale(key); + if (aliasedKey) { + key = aliasedKey; + } + if (!$translationTable[key] && $loaderFactory && !langPromises[key]) { + $nextLang = key; + langPromises[key] = loadAsync(key).then(function (translation) { + translations(translation.key, translation.table); + deferred.resolve(translation.key); + useLanguage(translation.key); + if ($nextLang === key) { + $nextLang = undefined; + } + }, function (key) { + if ($nextLang === key) { + $nextLang = undefined; + } + $rootScope.$emit('$translateChangeError', {language: key}); + deferred.reject(key); + $rootScope.$emit('$translateChangeEnd', {language: key}); + }); + } else { + deferred.resolve(key); + useLanguage(key); + } + return deferred.promise; + }; + $translate.storageKey = function () { + return storageKey(); + }; + $translate.isPostCompilingEnabled = function () { + return $postCompilingEnabled; + }; + $translate.refresh = function (langKey) { + if (!$loaderFactory) { + throw new Error('Couldn\'t refresh translation table, no loader registered!'); + } + var deferred = $q.defer(); + + function resolve() { + deferred.resolve(); + $rootScope.$emit('$translateRefreshEnd', {language: langKey}); + } + + function reject() { + deferred.reject(); + $rootScope.$emit('$translateRefreshEnd', {language: langKey}); + } + + $rootScope.$emit('$translateRefreshStart', {language: langKey}); + if (!langKey) { + var tables = [], loadingKeys = {}; + if ($fallbackLanguage && $fallbackLanguage.length) { + for (var i = 0, len = $fallbackLanguage.length; i < len; i++) { + tables.push(loadAsync($fallbackLanguage[i])); + loadingKeys[$fallbackLanguage[i]] = true; + } + } + if ($uses && !loadingKeys[$uses]) { + tables.push(loadAsync($uses)); + } + $q.all(tables).then(function (tableData) { + angular.forEach(tableData, function (data) { + if ($translationTable[data.key]) { + delete $translationTable[data.key]; + } + translations(data.key, data.table); + }); + if ($uses) { + useLanguage($uses); + } + resolve(); + }); + } else if ($translationTable[langKey]) { + loadAsync(langKey).then(function (data) { + translations(data.key, data.table); + if (langKey === $uses) { + useLanguage($uses); + } + resolve(); + }, reject); + } else { + reject(); + } + return deferred.promise; + }; + $translate.instant = function (translationId, interpolateParams, interpolationId) { + if (translationId === null || angular.isUndefined(translationId)) { + return translationId; + } + if (angular.isArray(translationId)) { + var results = {}; + for (var i = 0, c = translationId.length; i < c; i++) { + results[translationId[i]] = $translate.instant(translationId[i], interpolateParams, interpolationId); + } + return results; + } + if (angular.isString(translationId) && translationId.length < 1) { + return translationId; + } + if (translationId) { + translationId = trim.apply(translationId); + } + var result, possibleLangKeys = []; + if ($preferredLanguage) { + possibleLangKeys.push($preferredLanguage); + } + if ($uses) { + possibleLangKeys.push($uses); + } + if ($fallbackLanguage && $fallbackLanguage.length) { + possibleLangKeys = possibleLangKeys.concat($fallbackLanguage); + } + for (var j = 0, d = possibleLangKeys.length; j < d; j++) { + var possibleLangKey = possibleLangKeys[j]; + if ($translationTable[possibleLangKey]) { + if (typeof $translationTable[possibleLangKey][translationId] !== 'undefined') { + result = determineTranslationInstant(translationId, interpolateParams, interpolationId); + } + } + if (typeof result !== 'undefined') { + break; + } + } + if (!result && result !== '') { + result = defaultInterpolator.interpolate(translationId, interpolateParams); + if ($missingTranslationHandlerFactory && !pendingLoader) { + result = translateByHandler(translationId); + } + } + return result; + }; + $translate.versionInfo = function () { + return version; + }; + $translate.loaderCache = function () { + return loaderCache; + }; + if ($loaderFactory) { + if (angular.equals($translationTable, {})) { + $translate.use($translate.use()); + } + if ($fallbackLanguage && $fallbackLanguage.length) { + var processAsyncResult = function (translation) { + translations(translation.key, translation.table); + $rootScope.$emit('$translateChangeEnd', {language: translation.key}); + }; + for (var i = 0, len = $fallbackLanguage.length; i < len; i++) { + langPromises[$fallbackLanguage[i]] = loadAsync($fallbackLanguage[i]).then(processAsyncResult); + } + } + } + return $translate; } - } - } - return $translate; - } - ]; - } + ]; + } ]); angular.module('pascalprecht.translate').factory('$translateDefaultInterpolation', [ - '$interpolate', - function ($interpolate) { - var $translateInterpolator = {}, $locale, $identifier = 'default', $sanitizeValueStrategy = null, sanitizeValueStrategies = { - escaped: function (params) { - var result = {}; - for (var key in params) { - if (Object.prototype.hasOwnProperty.call(params, key)) { - result[key] = angular.element('
').text(params[key]).html(); + '$interpolate', + function ($interpolate) { + var $translateInterpolator = {}, $locale, $identifier = 'default', $sanitizeValueStrategy = null, + sanitizeValueStrategies = { + escaped: function (params) { + var result = {}; + for (var key in params) { + if (Object.prototype.hasOwnProperty.call(params, key)) { + result[key] = angular.element('
').text(params[key]).html(); + } + } + return result; + } + }; + var sanitizeParams = function (params) { + var result; + if (angular.isFunction(sanitizeValueStrategies[$sanitizeValueStrategy])) { + result = sanitizeValueStrategies[$sanitizeValueStrategy](params); + } else { + result = params; } - } - return result; - } - }; - var sanitizeParams = function (params) { - var result; - if (angular.isFunction(sanitizeValueStrategies[$sanitizeValueStrategy])) { - result = sanitizeValueStrategies[$sanitizeValueStrategy](params); - } else { - result = params; - } - return result; - }; - $translateInterpolator.setLocale = function (locale) { - $locale = locale; - }; - $translateInterpolator.getInterpolationIdentifier = function () { - return $identifier; - }; - $translateInterpolator.useSanitizeValueStrategy = function (value) { - $sanitizeValueStrategy = value; - return this; - }; - $translateInterpolator.interpolate = function (string, interpolateParams) { - if ($sanitizeValueStrategy) { - interpolateParams = sanitizeParams(interpolateParams); - } - return $interpolate(string)(interpolateParams || {}); - }; - return $translateInterpolator; - } + return result; + }; + $translateInterpolator.setLocale = function (locale) { + $locale = locale; + }; + $translateInterpolator.getInterpolationIdentifier = function () { + return $identifier; + }; + $translateInterpolator.useSanitizeValueStrategy = function (value) { + $sanitizeValueStrategy = value; + return this; + }; + $translateInterpolator.interpolate = function (string, interpolateParams) { + if ($sanitizeValueStrategy) { + interpolateParams = sanitizeParams(interpolateParams); + } + return $interpolate(string)(interpolateParams || {}); + }; + return $translateInterpolator; + } ]); angular.module('pascalprecht.translate').constant('$STORAGE_KEY', 'NG_TRANSLATE_LANG_KEY'); angular.module('pascalprecht.translate').directive('translate', [ - '$translate', - '$q', - '$interpolate', - '$compile', - '$parse', - '$rootScope', - function ($translate, $q, $interpolate, $compile, $parse, $rootScope) { - return { - restrict: 'AE', - scope: true, - compile: function (tElement, tAttr) { - var translateValuesExist = tAttr.translateValues ? tAttr.translateValues : undefined; - var translateInterpolation = tAttr.translateInterpolation ? tAttr.translateInterpolation : undefined; - var translateValueExist = tElement[0].outerHTML.match(/translate-value-+/i); - var interpolateRegExp = '^(.*)(' + $interpolate.startSymbol() + '.*' + $interpolate.endSymbol() + ')(.*)'; - return function linkFn(scope, iElement, iAttr) { - scope.interpolateParams = {}; - scope.preText = ''; - scope.postText = ''; - iAttr.$observe('translate', function (translationId) { - if (angular.equals(translationId, '') || !angular.isDefined(translationId)) { - var interpolateMatches = iElement.text().match(interpolateRegExp); - if (angular.isArray(interpolateMatches)) { - scope.preText = interpolateMatches[1]; - scope.postText = interpolateMatches[3]; - scope.translationId = $interpolate(interpolateMatches[2])(scope.$parent); - } else { - scope.translationId = iElement.text().replace(/^\s+|\s+$/g, ''); - } - } else { - scope.translationId = translationId; - } - }); - iAttr.$observe('translateDefault', function (value) { - scope.defaultText = value; - }); - if (translateValuesExist) { - iAttr.$observe('translateValues', function (interpolateParams) { - if (interpolateParams) { - scope.$parent.$watch(function () { - angular.extend(scope.interpolateParams, $parse(interpolateParams)(scope.$parent)); - }); - } - }); - } - if (translateValueExist) { - var fn = function (attrName) { - iAttr.$observe(attrName, function (value) { - scope.interpolateParams[angular.lowercase(attrName.substr(14, 1)) + attrName.substr(15)] = value; - }); - }; - for (var attr in iAttr) { - if (Object.prototype.hasOwnProperty.call(iAttr, attr) && attr.substr(0, 14) === 'translateValue' && attr !== 'translateValues') { - fn(attr); - } - } - } - var applyElementContent = function (value, scope, successful) { - if (!successful && typeof scope.defaultText !== 'undefined') { - value = scope.defaultText; - } - iElement.html(scope.preText + value + scope.postText); - var globallyEnabled = $translate.isPostCompilingEnabled(); - var locallyDefined = typeof tAttr.translateCompile !== 'undefined'; - var locallyEnabled = locallyDefined && tAttr.translateCompile !== 'false'; - if (globallyEnabled && !locallyDefined || locallyEnabled) { - $compile(iElement.contents())(scope); - } - }; - var updateTranslationFn = function () { - if (!translateValuesExist && !translateValueExist) { - return function () { - var unwatch = scope.$watch('translationId', function (value) { - if (scope.translationId && value) { - $translate(value, {}, translateInterpolation).then(function (translation) { - applyElementContent(translation, scope, true); - unwatch(); - }, function (translationId) { - applyElementContent(translationId, scope, false); - unwatch(); + '$translate', + '$q', + '$interpolate', + '$compile', + '$parse', + '$rootScope', + function ($translate, $q, $interpolate, $compile, $parse, $rootScope) { + return { + restrict: 'AE', + scope: true, + compile: function (tElement, tAttr) { + var translateValuesExist = tAttr.translateValues ? tAttr.translateValues : undefined; + var translateInterpolation = tAttr.translateInterpolation ? tAttr.translateInterpolation : undefined; + var translateValueExist = tElement[0].outerHTML.match(/translate-value-+/i); + var interpolateRegExp = '^(.*)(' + $interpolate.startSymbol() + '.*' + $interpolate.endSymbol() + ')(.*)'; + return function linkFn(scope, iElement, iAttr) { + scope.interpolateParams = {}; + scope.preText = ''; + scope.postText = ''; + iAttr.$observe('translate', function (translationId) { + if (angular.equals(translationId, '') || !angular.isDefined(translationId)) { + var interpolateMatches = iElement.text().match(interpolateRegExp); + if (angular.isArray(interpolateMatches)) { + scope.preText = interpolateMatches[1]; + scope.postText = interpolateMatches[3]; + scope.translationId = $interpolate(interpolateMatches[2])(scope.$parent); + } else { + scope.translationId = iElement.text().replace(/^\s+|\s+$/g, ''); + } + } else { + scope.translationId = translationId; + } + }); + iAttr.$observe('translateDefault', function (value) { + scope.defaultText = value; + }); + if (translateValuesExist) { + iAttr.$observe('translateValues', function (interpolateParams) { + if (interpolateParams) { + scope.$parent.$watch(function () { + angular.extend(scope.interpolateParams, $parse(interpolateParams)(scope.$parent)); + }); + } }); - } - }, true); - }; - } else { - return function () { - var updateTranslations = function () { - if (scope.translationId && scope.interpolateParams) { - $translate(scope.translationId, scope.interpolateParams, translateInterpolation).then(function (translation) { - applyElementContent(translation, scope, true); - }, function (translationId) { - applyElementContent(translationId, scope, false); - }); - } - }; - scope.$watch('interpolateParams', updateTranslations, true); - scope.$watch('translationId', updateTranslations); + } + if (translateValueExist) { + var fn = function (attrName) { + iAttr.$observe(attrName, function (value) { + scope.interpolateParams[angular.lowercase(attrName.substr(14, 1)) + attrName.substr(15)] = value; + }); + }; + for (var attr in iAttr) { + if (Object.prototype.hasOwnProperty.call(iAttr, attr) && attr.substr(0, 14) === 'translateValue' && attr !== 'translateValues') { + fn(attr); + } + } + } + var applyElementContent = function (value, scope, successful) { + if (!successful && typeof scope.defaultText !== 'undefined') { + value = scope.defaultText; + } + iElement.html(scope.preText + value + scope.postText); + var globallyEnabled = $translate.isPostCompilingEnabled(); + var locallyDefined = typeof tAttr.translateCompile !== 'undefined'; + var locallyEnabled = locallyDefined && tAttr.translateCompile !== 'false'; + if (globallyEnabled && !locallyDefined || locallyEnabled) { + $compile(iElement.contents())(scope); + } + }; + var updateTranslationFn = function () { + if (!translateValuesExist && !translateValueExist) { + return function () { + var unwatch = scope.$watch('translationId', function (value) { + if (scope.translationId && value) { + $translate(value, {}, translateInterpolation).then(function (translation) { + applyElementContent(translation, scope, true); + unwatch(); + }, function (translationId) { + applyElementContent(translationId, scope, false); + unwatch(); + }); + } + }, true); + }; + } else { + return function () { + var updateTranslations = function () { + if (scope.translationId && scope.interpolateParams) { + $translate(scope.translationId, scope.interpolateParams, translateInterpolation).then(function (translation) { + applyElementContent(translation, scope, true); + }, function (translationId) { + applyElementContent(translationId, scope, false); + }); + } + }; + scope.$watch('interpolateParams', updateTranslations, true); + scope.$watch('translationId', updateTranslations); + }; + } + }(); + var unbind = $rootScope.$on('$translateChangeSuccess', updateTranslationFn); + updateTranslationFn(); + scope.$on('$destroy', unbind); }; - } - }(); - var unbind = $rootScope.$on('$translateChangeSuccess', updateTranslationFn); - updateTranslationFn(); - scope.$on('$destroy', unbind); - }; - } - }; - } + } + }; + } ]); angular.module('pascalprecht.translate').directive('translateCloak', [ - '$rootScope', - '$translate', - function ($rootScope, $translate) { - return { - compile: function (tElement) { - var applyCloak = function () { - tElement.addClass($translate.cloakClassName()); - }, removeCloak = function () { - tElement.removeClass($translate.cloakClassName()); - }, removeListener = $rootScope.$on('$translateChangeEnd', function () { - removeCloak(); - removeListener(); - removeListener = null; - }); - applyCloak(); - return function linkFn(scope, iElement, iAttr) { - if (iAttr.translateCloak && iAttr.translateCloak.length) { - iAttr.$observe('translateCloak', function (translationId) { - $translate(translationId).then(removeCloak, applyCloak); - }); - } - }; - } - }; - } + '$rootScope', + '$translate', + function ($rootScope, $translate) { + return { + compile: function (tElement) { + var applyCloak = function () { + tElement.addClass($translate.cloakClassName()); + }, removeCloak = function () { + tElement.removeClass($translate.cloakClassName()); + }, removeListener = $rootScope.$on('$translateChangeEnd', function () { + removeCloak(); + removeListener(); + removeListener = null; + }); + applyCloak(); + return function linkFn(scope, iElement, iAttr) { + if (iAttr.translateCloak && iAttr.translateCloak.length) { + iAttr.$observe('translateCloak', function (translationId) { + $translate(translationId).then(removeCloak, applyCloak); + }); + } + }; + } + }; + } ]); angular.module('pascalprecht.translate').filter('translate', [ - '$parse', - '$translate', - function ($parse, $translate) { - var translateFilter = function (translationId, interpolateParams, interpolation) { - if (!angular.isObject(interpolateParams)) { - interpolateParams = $parse(interpolateParams)(this); - } - return $translate.instant(translationId, interpolateParams, interpolation); - }; - translateFilter.$stateful = true; - return translateFilter; - } -]); \ No newline at end of file + '$parse', + '$translate', + function ($parse, $translate) { + var translateFilter = function (translationId, interpolateParams, interpolation) { + if (!angular.isObject(interpolateParams)) { + interpolateParams = $parse(interpolateParams)(this); + } + return $translate.instant(translationId, interpolateParams, interpolation); + }; + translateFilter.$stateful = true; + return translateFilter; + } +]); diff --git a/pear-modules/pear-process/src/main/resources/static/editor-app/libs/bootstrap-daterangepicker_1.3.7/daterangepicker-bs3.css b/pear-modules/pear-process/src/main/resources/static/editor-app/libs/bootstrap-daterangepicker_1.3.7/daterangepicker-bs3.css index abcaa4681cb1e2c24280252bab5d9d770811e6e5..7dea099d4aad617acdbb0674b334723725d07316 100644 --- a/pear-modules/pear-process/src/main/resources/static/editor-app/libs/bootstrap-daterangepicker_1.3.7/daterangepicker-bs3.css +++ b/pear-modules/pear-process/src/main/resources/static/editor-app/libs/bootstrap-daterangepicker_1.3.7/daterangepicker-bs3.css @@ -28,11 +28,11 @@ text-align: left; } -.daterangepicker .ranges .range_inputs>div { +.daterangepicker .ranges .range_inputs > div { float: left; } -.daterangepicker .ranges .range_inputs>div:nth-child(2) { +.daterangepicker .ranges .range_inputs > div:nth-child(2) { padding-left: 11px; } @@ -264,4 +264,4 @@ .daterangepicker th.month { width: auto; -} \ No newline at end of file +} diff --git a/pear-modules/pear-process/src/main/resources/static/editor-app/libs/bootstrap-daterangepicker_1.3.7/daterangepicker.js b/pear-modules/pear-process/src/main/resources/static/editor-app/libs/bootstrap-daterangepicker_1.3.7/daterangepicker.js index 579e875675e7749303bec663cb9cc13aa66709ab..aa3344ba40fabf15c0da565dd59c00430db5c576 100644 --- a/pear-modules/pear-process/src/main/resources/static/editor-app/libs/bootstrap-daterangepicker_1.3.7/daterangepicker.js +++ b/pear-modules/pear-process/src/main/resources/static/editor-app/libs/bootstrap-daterangepicker_1.3.7/daterangepicker.js @@ -1,6 +1,6 @@ /** * @version: 1.3.7 - * @author: Dan Grossman http://www.dangrossman.info/ + * @@author Dan Grossman http://www.dangrossman.info/ * @date: 2014-04-29 * @copyright: Copyright (c) 2012-2014 Dan Grossman. All rights reserved. * @license: Licensed under Apache License v2.0. See http://www.apache.org/licenses/LICENSE-2.0 @@ -95,7 +95,7 @@ constructor: DateRangePicker, - setOptions: function(options, callback) { + setOptions: function (options, callback) { this.startDate = moment().startOf('day'); this.endDate = moment().endOf('day'); @@ -134,7 +134,8 @@ firstDay: 0 }; - this.cb = function () { }; + this.cb = function () { + }; if (typeof options.format === 'string') this.format = options.format; @@ -368,7 +369,7 @@ }, - setStartDate: function(startDate) { + setStartDate: function (startDate) { if (typeof startDate === 'string') this.startDate = moment(startDate, this.format); @@ -384,7 +385,7 @@ this.updateCalendars(); }, - setEndDate: function(endDate) { + setEndDate: function (endDate) { if (typeof endDate === 'string') this.endDate = moment(endDate, this.format); @@ -425,7 +426,7 @@ start = null, end = null; - if(dateString.length === 2) { + if (dateString.length === 2) { start = moment(dateString[0], this.format); end = moment(dateString[1], this.format); } @@ -455,7 +456,7 @@ }, move: function () { - var parentOffset = { top: 0, left: 0 }; + var parentOffset = {top: 0, left: 0}; if (!this.parentEl.is('body')) { parentOffset = { top: this.parentEl.offset().top - this.parentEl.scrollTop(), @@ -504,7 +505,9 @@ this.move(); // Create a click proxy that is private to this instance of datepicker, for unbinding - this._outsideClickProxy = $.proxy(function (e) { this.outsideClick(e); }, this); + this._outsideClickProxy = $.proxy(function (e) { + this.outsideClick(e); + }, this); // Bind global datepicker mousedown for hiding and $(document) .on('mousedown.daterangepicker', this._outsideClickProxy) @@ -524,7 +527,7 @@ target.closest(this.element).length || target.closest(this.container).length || target.closest('.calendar-date').length - ) return; + ) return; this.hide(); }, @@ -558,16 +561,16 @@ } }, - showCalendars: function() { + showCalendars: function () { this.container.addClass('show-calendar'); this.move(); }, - hideCalendars: function() { + hideCalendars: function () { this.container.removeClass('show-calendar'); }, - updateInputText: function() { + updateInputText: function () { if (this.element.is('input') && !this.singleDatePicker) { this.element.val(this.startDate.format(this.format) + this.separator + this.endDate.format(this.format)); } else if (this.element.is('input')) { @@ -716,17 +719,17 @@ updateMonthYear: function (e) { var isLeft = $(e.target).closest('.calendar').hasClass('left'), leftOrRight = isLeft ? 'left' : 'right', - cal = this.container.find('.calendar.'+leftOrRight); + cal = this.container.find('.calendar.' + leftOrRight); // Month must be Number for new moment versions var month = parseInt(cal.find('.monthselect').val(), 10); var year = cal.find('.yearselect').val(); - this[leftOrRight+'Calendar'].month.month(month).year(year); + this[leftOrRight + 'Calendar'].month.month(month).year(year); this.updateCalendars(); }, - updateTime: function(e) { + updateTime: function (e) { var cal = $(e.target).closest('.calendar'), isLeft = cal.hasClass('left'); @@ -929,8 +932,12 @@ } } else if (calendar[row][col] >= this.startDate && calendar[row][col] <= this.endDate) { cname += ' in-range '; - if (calendar[row][col].isSame(this.startDate)) { cname += ' start-date '; } - if (calendar[row][col].isSame(this.endDate)) { cname += ' end-date '; } + if (calendar[row][col].isSame(this.startDate)) { + cname += ' start-date '; + } + if (calendar[row][col].isSame(this.endDate)) { + cname += ' end-date '; + } } var title = 'r' + row + 'c' + col; @@ -1003,7 +1010,7 @@ }, - remove: function() { + remove: function () { this.container.remove(); this.element.off('.daterangepicker'); @@ -1023,4 +1030,4 @@ return this; }; -}(window.jQuery, window.moment); \ No newline at end of file +}(window.jQuery, window.moment); diff --git a/pear-modules/pear-process/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/css/bootstrap-theme.css b/pear-modules/pear-process/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/css/bootstrap-theme.css index a4069929bceb661eacbd4b1eb21306cfa5a1c8f9..b53ebfd0a9385e36e79297ee65ed8b36934c79b6 100644 --- a/pear-modules/pear-process/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/css/bootstrap-theme.css +++ b/pear-modules/pear-process/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/css/bootstrap-theme.css @@ -10,10 +10,11 @@ .btn-info, .btn-warning, .btn-danger { - text-shadow: 0 -1px 0 rgba(0, 0, 0, .2); - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); + text-shadow: 0 -1px 0 rgba(0, 0, 0, .2); + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 1px rgba(0, 0, 0, .075); } + .btn-default:active, .btn-primary:active, .btn-success:active, @@ -26,322 +27,373 @@ .btn-info.active, .btn-warning.active, .btn-danger.active { - -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); - box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); } + .btn:active, .btn.active { - background-image: none; + background-image: none; } + .btn-default { - text-shadow: 0 1px 0 #fff; - background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%); - background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - background-repeat: repeat-x; - border-color: #dbdbdb; - border-color: #ccc; + text-shadow: 0 1px 0 #fff; + background-image: -webkit-linear-gradient(top, #fff 0%, #e0e0e0 100%); + background-image: linear-gradient(to bottom, #fff 0%, #e0e0e0 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + background-repeat: repeat-x; + border-color: #dbdbdb; + border-color: #ccc; } + .btn-default:hover, .btn-default:focus { - background-color: #e0e0e0; - background-position: 0 -15px; + background-color: #e0e0e0; + background-position: 0 -15px; } + .btn-default:active, .btn-default.active { - background-color: #e0e0e0; - border-color: #dbdbdb; + background-color: #e0e0e0; + border-color: #dbdbdb; } + .btn-primary { - background-image: -webkit-linear-gradient(top, #428bca 0%, #2d6ca2 100%); - background-image: linear-gradient(to bottom, #428bca 0%, #2d6ca2 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - background-repeat: repeat-x; - border-color: #2b669a; + background-image: -webkit-linear-gradient(top, #428bca 0%, #2d6ca2 100%); + background-image: linear-gradient(to bottom, #428bca 0%, #2d6ca2 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + background-repeat: repeat-x; + border-color: #2b669a; } + .btn-primary:hover, .btn-primary:focus { - background-color: #2d6ca2; - background-position: 0 -15px; + background-color: #2d6ca2; + background-position: 0 -15px; } + .btn-primary:active, .btn-primary.active { - background-color: #2d6ca2; - border-color: #2b669a; + background-color: #2d6ca2; + border-color: #2b669a; } + .btn-success { - background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%); - background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - background-repeat: repeat-x; - border-color: #3e8f3e; + background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%); + background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + background-repeat: repeat-x; + border-color: #3e8f3e; } + .btn-success:hover, .btn-success:focus { - background-color: #419641; - background-position: 0 -15px; + background-color: #419641; + background-position: 0 -15px; } + .btn-success:active, .btn-success.active { - background-color: #419641; - border-color: #3e8f3e; + background-color: #419641; + border-color: #3e8f3e; } + .btn-info { - background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); - background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - background-repeat: repeat-x; - border-color: #28a4c9; + background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%); + background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + background-repeat: repeat-x; + border-color: #28a4c9; } + .btn-info:hover, .btn-info:focus { - background-color: #2aabd2; - background-position: 0 -15px; + background-color: #2aabd2; + background-position: 0 -15px; } + .btn-info:active, .btn-info.active { - background-color: #2aabd2; - border-color: #28a4c9; + background-color: #2aabd2; + border-color: #28a4c9; } + .btn-warning { - background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); - background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - background-repeat: repeat-x; - border-color: #e38d13; + background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%); + background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + background-repeat: repeat-x; + border-color: #e38d13; } + .btn-warning:hover, .btn-warning:focus { - background-color: #eb9316; - background-position: 0 -15px; + background-color: #eb9316; + background-position: 0 -15px; } + .btn-warning:active, .btn-warning.active { - background-color: #eb9316; - border-color: #e38d13; + background-color: #eb9316; + border-color: #e38d13; } + .btn-danger { - background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%); - background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - background-repeat: repeat-x; - border-color: #b92c28; + background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%); + background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + background-repeat: repeat-x; + border-color: #b92c28; } + .btn-danger:hover, .btn-danger:focus { - background-color: #c12e2a; - background-position: 0 -15px; + background-color: #c12e2a; + background-position: 0 -15px; } + .btn-danger:active, .btn-danger.active { - background-color: #c12e2a; - border-color: #b92c28; + background-color: #c12e2a; + border-color: #b92c28; } + .thumbnail, .img-thumbnail { - -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); - box-shadow: 0 1px 2px rgba(0, 0, 0, .075); + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); + box-shadow: 0 1px 2px rgba(0, 0, 0, .075); } + .dropdown-menu > li > a:hover, .dropdown-menu > li > a:focus { - background-color: #e8e8e8; - background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); - background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); - background-repeat: repeat-x; + background-color: #e8e8e8; + background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); + background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); + background-repeat: repeat-x; } + .dropdown-menu > .active > a, .dropdown-menu > .active > a:hover, .dropdown-menu > .active > a:focus { - background-color: #357ebd; - background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%); - background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); - background-repeat: repeat-x; + background-color: #357ebd; + background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%); + background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); + background-repeat: repeat-x; } + .navbar-default { - background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%); - background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - background-repeat: repeat-x; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); + background-image: -webkit-linear-gradient(top, #fff 0%, #f8f8f8 100%); + background-image: linear-gradient(to bottom, #fff 0%, #f8f8f8 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + background-repeat: repeat-x; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .15), 0 1px 5px rgba(0, 0, 0, .075); } + .navbar-default .navbar-nav > .active > a { - background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f3f3f3 100%); - background-image: linear-gradient(to bottom, #ebebeb 0%, #f3f3f3 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0); - background-repeat: repeat-x; - -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); - box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); + background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f3f3f3 100%); + background-image: linear-gradient(to bottom, #ebebeb 0%, #f3f3f3 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0); + background-repeat: repeat-x; + -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); + box-shadow: inset 0 3px 9px rgba(0, 0, 0, .075); } + .navbar-brand, .navbar-nav > li > a { - text-shadow: 0 1px 0 rgba(255, 255, 255, .25); + text-shadow: 0 1px 0 rgba(255, 255, 255, .25); } + .navbar-inverse { - background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%); - background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0); - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); - background-repeat: repeat-x; + background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222 100%); + background-image: linear-gradient(to bottom, #3c3c3c 0%, #222 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0); + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); + background-repeat: repeat-x; } + .navbar-inverse .navbar-nav > .active > a { - background-image: -webkit-linear-gradient(top, #222 0%, #282828 100%); - background-image: linear-gradient(to bottom, #222 0%, #282828 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0); - background-repeat: repeat-x; - -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); - box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); + background-image: -webkit-linear-gradient(top, #222 0%, #282828 100%); + background-image: linear-gradient(to bottom, #222 0%, #282828 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0); + background-repeat: repeat-x; + -webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); + box-shadow: inset 0 3px 9px rgba(0, 0, 0, .25); } + .navbar-inverse .navbar-brand, .navbar-inverse .navbar-nav > li > a { - text-shadow: 0 -1px 0 rgba(0, 0, 0, .25); + text-shadow: 0 -1px 0 rgba(0, 0, 0, .25); } + .navbar-static-top, .navbar-fixed-top, .navbar-fixed-bottom { - border-radius: 0; + border-radius: 0; } + .alert { - text-shadow: 0 1px 0 rgba(255, 255, 255, .2); - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); + text-shadow: 0 1px 0 rgba(255, 255, 255, .2); + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .25), 0 1px 2px rgba(0, 0, 0, .05); } + .alert-success { - background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); - background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0); - background-repeat: repeat-x; - border-color: #b2dba1; + background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%); + background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0); + background-repeat: repeat-x; + border-color: #b2dba1; } + .alert-info { - background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%); - background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0); - background-repeat: repeat-x; - border-color: #9acfea; + background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%); + background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0); + background-repeat: repeat-x; + border-color: #9acfea; } + .alert-warning { - background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); - background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0); - background-repeat: repeat-x; - border-color: #f5e79e; + background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%); + background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0); + background-repeat: repeat-x; + border-color: #f5e79e; } + .alert-danger { - background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); - background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0); - background-repeat: repeat-x; - border-color: #dca7a7; + background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%); + background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0); + background-repeat: repeat-x; + border-color: #dca7a7; } + .progress { - background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); - background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0); - background-repeat: repeat-x; + background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%); + background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0); + background-repeat: repeat-x; } + .progress-bar { - background-image: -webkit-linear-gradient(top, #428bca 0%, #3071a9 100%); - background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0); - background-repeat: repeat-x; + background-image: -webkit-linear-gradient(top, #428bca 0%, #3071a9 100%); + background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0); + background-repeat: repeat-x; } + .progress-bar-success { - background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%); - background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); - background-repeat: repeat-x; + background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%); + background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0); + background-repeat: repeat-x; } + .progress-bar-info { - background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); - background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); - background-repeat: repeat-x; + background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%); + background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0); + background-repeat: repeat-x; } + .progress-bar-warning { - background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); - background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); - background-repeat: repeat-x; + background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%); + background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0); + background-repeat: repeat-x; } + .progress-bar-danger { - background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%); - background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); - background-repeat: repeat-x; + background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%); + background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0); + background-repeat: repeat-x; } + .list-group { - border-radius: 4px; - -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); - box-shadow: 0 1px 2px rgba(0, 0, 0, .075); + border-radius: 4px; + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .075); + box-shadow: 0 1px 2px rgba(0, 0, 0, .075); } + .list-group-item.active, .list-group-item.active:hover, .list-group-item.active:focus { - text-shadow: 0 -1px 0 #3071a9; - background-image: -webkit-linear-gradient(top, #428bca 0%, #3278b3 100%); - background-image: linear-gradient(to bottom, #428bca 0%, #3278b3 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0); - background-repeat: repeat-x; - border-color: #3278b3; + text-shadow: 0 -1px 0 #3071a9; + background-image: -webkit-linear-gradient(top, #428bca 0%, #3278b3 100%); + background-image: linear-gradient(to bottom, #428bca 0%, #3278b3 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0); + background-repeat: repeat-x; + border-color: #3278b3; } + .panel { - -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05); - box-shadow: 0 1px 2px rgba(0, 0, 0, .05); + -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, .05); + box-shadow: 0 1px 2px rgba(0, 0, 0, .05); } + .panel-default > .panel-heading { - background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); - background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); - background-repeat: repeat-x; + background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%); + background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0); + background-repeat: repeat-x; } + .panel-primary > .panel-heading { - background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%); - background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); - background-repeat: repeat-x; + background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%); + background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0); + background-repeat: repeat-x; } + .panel-success > .panel-heading { - background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); - background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0); - background-repeat: repeat-x; + background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%); + background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0); + background-repeat: repeat-x; } + .panel-info > .panel-heading { - background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); - background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0); - background-repeat: repeat-x; + background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%); + background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0); + background-repeat: repeat-x; } + .panel-warning > .panel-heading { - background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); - background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0); - background-repeat: repeat-x; + background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%); + background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0); + background-repeat: repeat-x; } + .panel-danger > .panel-heading { - background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%); - background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0); - background-repeat: repeat-x; + background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%); + background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0); + background-repeat: repeat-x; } + .well { - background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); - background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0); - background-repeat: repeat-x; - border-color: #dcdcdc; - -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); - box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); + background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%); + background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0); + background-repeat: repeat-x; + border-color: #dcdcdc; + -webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); + box-shadow: inset 0 1px 3px rgba(0, 0, 0, .05), 0 1px 0 rgba(255, 255, 255, .1); } + /*# sourceMappingURL=bootstrap-theme.css.map */ diff --git a/pear-modules/pear-process/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/css/bootstrap-theme.css.map b/pear-modules/pear-process/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/css/bootstrap-theme.css.map index b36fc9a4970e41d7a3bfdb67780e93ab18a68faf..284a3e61fb465686abc546631f020f877543521d 100644 --- a/pear-modules/pear-process/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/css/bootstrap-theme.css.map +++ b/pear-modules/pear-process/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/css/bootstrap-theme.css.map @@ -1 +1,13 @@ -{"version":3,"sources":["less/theme.less","less/mixins.less"],"names":[],"mappings":"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","sourcesContent":["\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, 12%));\n .reset-filter(); // Disable gradients for IE9 because filter bleeds through rounded corners\n background-repeat: repeat-x;\n border-color: darken(@btn-color, 14%);\n\n &:hover,\n &:focus {\n background-color: darken(@btn-color, 12%);\n background-position: 0 -15px;\n }\n\n &:active,\n &.active {\n background-color: darken(@btn-color, 12%);\n border-color: darken(@btn-color, 14%);\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-info { .btn-styles(@btn-info-bg); }\n.btn-warning { .btn-styles(@btn-warning-bg); }\n.btn-danger { .btn-styles(@btn-danger-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 #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.dropdown-menu > .active > a,\n.dropdown-menu > .active > a:hover,\n.dropdown-menu > .active > a:focus {\n #gradient > .vertical(@start-color: @dropdown-link-active-bg; @end-color: darken(@dropdown-link-active-bg, 5%));\n background-color: darken(@dropdown-link-active-bg, 5%);\n}\n\n\n\n//\n// Navbar\n// --------------------------------------------------\n\n// Default navbar\n.navbar-default {\n #gradient > .vertical(@start-color: lighten(@navbar-default-bg, 10%); @end-color: @navbar-default-bg);\n .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\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 #gradient > .vertical(@start-color: darken(@navbar-default-bg, 5%); @end-color: darken(@navbar-default-bg, 2%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.075));\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 .reset-filter(); // Remove gradient in IE<10 to fix bug where dropdowns don't get triggered\n\n .navbar-nav > .active > a {\n #gradient > .vertical(@start-color: @navbar-inverse-bg; @end-color: lighten(@navbar-inverse-bg, 2.5%));\n .box-shadow(inset 0 3px 9px rgba(0,0,0,.25));\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","//\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;\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\n opacity: 1; } // See https://github.com/twbs/bootstrap/pull/11526\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//\n// Heads up! v3 launched with with only `.hide-text()`, but per our pattern for\n// mixins being reused as classes with the same name, this doesn't hold up. As\n// of v3.0.1 we have added `.text-hide()` and deprecated `.hide-text()`. Note\n// that we cannot chain the mixins together in Less, so they are repeated.\n//\n// Source: https://github.com/h5bp/html5-boilerplate/commit/aa0396eae757\n\n// Deprecated as of v3.0.1 (will be removed in v4)\n.hide-text() {\n font: ~\"0/0\" a;\n color: transparent;\n text-shadow: none;\n background-color: transparent;\n border: 0;\n}\n// New mixin to use as of v3.0.1\n.text-hide() {\n .hide-text();\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//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support the\n// standard `box-shadow` property.\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-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\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 only\n transform: rotate(@degrees);\n}\n.scale(@ratio; @ratio-y...) {\n -webkit-transform: scale(@ratio, @ratio-y);\n -ms-transform: scale(@ratio, @ratio-y); // IE9 only\n transform: scale(@ratio, @ratio-y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\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.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\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.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 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-linear-gradient(left, color-stop(@start-color @start-percent), color-stop(@end-color @end-percent)); // Safari 5.1-6, Chrome 10+\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\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-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\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-6, Chrome 10+\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-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-linear-gradient(@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-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: rgba(255,255,255,.15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 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\n & > .panel-heading {\n color: @heading-text-color;\n background-color: @heading-bg-color;\n border-color: @heading-border;\n\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\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) {\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 }\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 &.@{state}:hover > th {\n background-color: darken(@background, 5%);\n }\n }\n}\n\n// List Groups\n// -------------------------\n.list-group-item-variant(@state; @background; @color) {\n .list-group-item-@{state} {\n color: @color;\n background-color: @background;\n\n a& {\n color: @color;\n\n .list-group-item-heading { color: inherit; }\n\n &:hover,\n &:focus {\n color: @color;\n background-color: darken(@background, 5%);\n }\n &.active,\n &.active:hover,\n &.active:focus {\n color: #fff;\n background-color: @color;\n border-color: @color;\n }\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 .badge {\n color: @background;\n background-color: @color;\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// Contextual backgrounds\n// -------------------------\n.bg-variant(@color) {\n background-color: @color;\n a&:hover {\n background-color: darken(@color, 10%);\n }\n}\n\n// Typography\n// -------------------------\n.text-emphasis-variant(@color) {\n color: @color;\n a&:hover {\n color: darken(@color, 10%);\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();\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 table& { display: table; }\n tr& { display: table-row !important; }\n th&,\n td& { display: table-cell !important; }\n}\n\n.responsive-invisibility() {\n display: none !important;\n}\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 &:extend(.clearfix all);\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 &:extend(.clearfix all);\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 min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n}\n.make-xs-column-offset(@columns) {\n @media (min-width: @screen-xs-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-xs-column-push(@columns) {\n @media (min-width: @screen-xs-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-xs-column-pull(@columns) {\n @media (min-width: @screen-xs-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n\n// Generate the small columns\n.make-sm-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-sm-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-offset(@columns) {\n @media (min-width: @screen-sm-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-push(@columns) {\n @media (min-width: @screen-sm-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-pull(@columns) {\n @media (min-width: @screen-sm-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n\n// Generate the medium columns\n.make-md-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-md-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-offset(@columns) {\n @media (min-width: @screen-md-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-push(@columns) {\n @media (min-width: @screen-md-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-pull(@columns) {\n @media (min-width: @screen-md-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n\n// Generate the large columns\n.make-lg-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-lg-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-offset(@columns) {\n @media (min-width: @screen-lg-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-push(@columns) {\n @media (min-width: @screen-lg-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-pull(@columns) {\n @media (min-width: @screen-lg-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n\n// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `@grid-columns`.\n\n.make-grid-columns() {\n // Common styles for all sizes of grid columns, widths 1-12\n .col(@index) when (@index = 1) { // initial\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general; \"=<\" isn't a typo\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\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 .col(1); // kickstart it\n}\n\n.float-grid-columns(@class) {\n .col(@index) when (@index = 1) { // initial\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n float: left;\n }\n }\n .col(1); // kickstart it\n}\n\n.calc-grid-column(@index, @class, @type) when (@type = width) and (@index > 0) {\n .col-@{class}-@{index} {\n width: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) {\n .col-@{class}-push-@{index} {\n left: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) {\n .col-@{class}-pull-@{index} {\n right: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = offset) {\n .col-@{class}-offset-@{index} {\n margin-left: percentage((@index / @grid-columns));\n }\n}\n\n// Basic looping in LESS\n.loop-grid-columns(@index, @class, @type) when (@index >= 0) {\n .calc-grid-column(@index, @class, @type);\n // next iteration\n .loop-grid-columns((@index - 1), @class, @type);\n}\n\n// Create grid for specific class\n.make-grid(@class) {\n .float-grid-columns(@class);\n .loop-grid-columns(@grid-columns, @class, width);\n .loop-grid-columns(@grid-columns, @class, pull);\n .loop-grid-columns(@grid-columns, @class, push);\n .loop-grid-columns(@grid-columns, @class, offset);\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 .radio,\n .checkbox,\n .radio-inline,\n .checkbox-inline {\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 // Optional feedback icon\n .form-control-feedback {\n color: @text-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. ``\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 select[multiple]& {\n height: auto;\n }\n}\n" + ] +} diff --git a/pear-modules/pear-process/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/css/bootstrap.css b/pear-modules/pear-process/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/css/bootstrap.css index 7f36651961ed5bc42a712042c6db5493b4ce99e9..0c7675d765d59ac2c073ee75215fec4395fd5b02 100644 --- a/pear-modules/pear-process/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/css/bootstrap.css +++ b/pear-modules/pear-process/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/css/bootstrap.css @@ -6,13 +6,15 @@ /*! normalize.css v3.0.0 | MIT License | git.io/normalize */ html { - font-family: sans-serif; - -webkit-text-size-adjust: 100%; - -ms-text-size-adjust: 100%; + font-family: sans-serif; + -webkit-text-size-adjust: 100%; + -ms-text-size-adjust: 100%; } + body { - margin: 0; + margin: 0; } + article, aside, details, @@ -25,331 +27,403 @@ main, nav, section, summary { - display: block; + display: block; } + audio, canvas, progress, video { - display: inline-block; - vertical-align: baseline; + display: inline-block; + vertical-align: baseline; } + audio:not([controls]) { - display: none; - height: 0; + display: none; + height: 0; } + [hidden], template { - display: none; + display: none; } + a { - background: transparent; + background: transparent; } + a:active, a:hover { - outline: 0; + outline: 0; } + abbr[title] { - border-bottom: 1px dotted; + border-bottom: 1px dotted; } + b, strong { - font-weight: bold; + font-weight: bold; } + dfn { - font-style: italic; + font-style: italic; } + h1 { - margin: .67em 0; - font-size: 2em; + margin: .67em 0; + font-size: 2em; } + mark { - color: #000; - background: #ff0; + color: #000; + background: #ff0; } + small { - font-size: 80%; + font-size: 80%; } + sub, sup { - position: relative; - font-size: 75%; - line-height: 0; - vertical-align: baseline; + position: relative; + font-size: 75%; + line-height: 0; + vertical-align: baseline; } + sup { - top: -.5em; + top: -.5em; } + sub { - bottom: -.25em; + bottom: -.25em; } + img { - border: 0; + border: 0; } + svg:not(:root) { - overflow: hidden; + overflow: hidden; } + figure { - margin: 1em 40px; + margin: 1em 40px; } + hr { - height: 0; - -moz-box-sizing: content-box; - box-sizing: content-box; + height: 0; + -moz-box-sizing: content-box; + box-sizing: content-box; } + pre { - overflow: auto; + overflow: auto; } + code, kbd, pre, samp { - font-family: monospace, monospace; - font-size: 1em; + font-family: monospace, monospace; + font-size: 1em; } + button, input, optgroup, select, textarea { - margin: 0; - font: inherit; - color: inherit; + margin: 0; + font: inherit; + color: inherit; } + button { - overflow: visible; + overflow: visible; } + button, select { - text-transform: none; + text-transform: none; } + button, html input[type="button"], input[type="reset"], input[type="submit"] { - -webkit-appearance: button; - cursor: pointer; + -webkit-appearance: button; + cursor: pointer; } + button[disabled], html input[disabled] { - cursor: default; + cursor: default; } + button::-moz-focus-inner, input::-moz-focus-inner { - padding: 0; - border: 0; + padding: 0; + border: 0; } + input { - line-height: normal; + line-height: normal; } + input[type="checkbox"], input[type="radio"] { - box-sizing: border-box; - padding: 0; + box-sizing: border-box; + padding: 0; } + input[type="number"]::-webkit-inner-spin-button, input[type="number"]::-webkit-outer-spin-button { - height: auto; + height: auto; } + input[type="search"] { - -webkit-box-sizing: content-box; - -moz-box-sizing: content-box; - box-sizing: content-box; - -webkit-appearance: textfield; + -webkit-box-sizing: content-box; + -moz-box-sizing: content-box; + box-sizing: content-box; + -webkit-appearance: textfield; } + input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration { - -webkit-appearance: none; + -webkit-appearance: none; } + fieldset { - padding: .35em .625em .75em; - margin: 0 2px; - border: 1px solid #c0c0c0; + padding: .35em .625em .75em; + margin: 0 2px; + border: 1px solid #c0c0c0; } + legend { - padding: 0; - border: 0; + padding: 0; + border: 0; } + textarea { - overflow: auto; + overflow: auto; } + optgroup { - font-weight: bold; + font-weight: bold; } + table { - border-spacing: 0; - border-collapse: collapse; + border-spacing: 0; + border-collapse: collapse; } + td, th { - padding: 0; + padding: 0; } + @media print { - * { - color: #000 !important; - text-shadow: none !important; - background: transparent !important; - box-shadow: none !important; - } - a, - a:visited { - text-decoration: underline; - } - a[href]:after { - content: " (" attr(href) ")"; - } - abbr[title]:after { - content: " (" attr(title) ")"; - } - a[href^="javascript:"]:after, - a[href^="#"]:after { - content: ""; - } - pre, - blockquote { - border: 1px solid #999; + * { + color: #000 !important; + text-shadow: none !important; + background: transparent !important; + box-shadow: none !important; + } - page-break-inside: avoid; - } - thead { - display: table-header-group; - } - tr, - img { - page-break-inside: avoid; - } - img { - max-width: 100% !important; - } - p, - h2, - h3 { - orphans: 3; - widows: 3; - } - h2, - h3 { - page-break-after: avoid; - } - select { - background: #fff !important; - } - .navbar { - display: none; - } - .table td, - .table th { - background-color: #fff !important; - } - .btn > .caret, - .dropup > .btn > .caret { - border-top-color: #000 !important; - } - .label { - border: 1px solid #000; - } - .table { - border-collapse: collapse !important; - } - .table-bordered th, - .table-bordered td { - border: 1px solid #ddd !important; - } + a, + a:visited { + text-decoration: underline; + } + + a[href]:after { + content: " (" attr(href) ")"; + } + + abbr[title]:after { + content: " (" attr(title) ")"; + } + + a[href^="javascript:"]:after, + a[href^="#"]:after { + content: ""; + } + + pre, + blockquote { + border: 1px solid #999; + + page-break-inside: avoid; + } + + thead { + display: table-header-group; + } + + tr, + img { + page-break-inside: avoid; + } + + img { + max-width: 100% !important; + } + + p, + h2, + h3 { + orphans: 3; + widows: 3; + } + + h2, + h3 { + page-break-after: avoid; + } + + select { + background: #fff !important; + } + + .navbar { + display: none; + } + + .table td, + .table th { + background-color: #fff !important; + } + + .btn > .caret, + .dropup > .btn > .caret { + border-top-color: #000 !important; + } + + .label { + border: 1px solid #000; + } + + .table { + border-collapse: collapse !important; + } + + .table-bordered th, + .table-bordered td { + border: 1px solid #ddd !important; + } } + * { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; } + *:before, *:after { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; } + html { - font-size: 62.5%; + font-size: 62.5%; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } + body { - font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; - font-size: 14px; - line-height: 1.42857143; - color: #333; - background-color: #fff; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; + font-size: 14px; + line-height: 1.42857143; + color: #333; + background-color: #fff; } + input, button, select, textarea { - font-family: inherit; - font-size: inherit; - line-height: inherit; + font-family: inherit; + font-size: inherit; + line-height: inherit; } + a { - color: #428bca; - text-decoration: none; + color: #428bca; + text-decoration: none; } + a:hover, a:focus { - color: #2a6496; - text-decoration: underline; + color: #2a6496; + text-decoration: underline; } + a:focus { - outline: thin dotted; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; } + figure { - margin: 0; + margin: 0; } + img { - vertical-align: middle; + vertical-align: middle; } + .img-responsive, .thumbnail > img, .thumbnail a > img, .carousel-inner > .item > img, .carousel-inner > .item > a > img { - display: block; - max-width: 100%; - height: auto; + display: block; + max-width: 100%; + height: auto; } + .img-rounded { - border-radius: 6px; + border-radius: 6px; } + .img-thumbnail { - display: inline-block; - max-width: 100%; - height: auto; - padding: 4px; - line-height: 1.42857143; - background-color: #fff; - border: 1px solid #ddd; - border-radius: 4px; - -webkit-transition: all .2s ease-in-out; - transition: all .2s ease-in-out; + display: inline-block; + max-width: 100%; + height: auto; + padding: 4px; + line-height: 1.42857143; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 4px; + -webkit-transition: all .2s ease-in-out; + transition: all .2s ease-in-out; } + .img-circle { - border-radius: 50%; + border-radius: 50%; } + hr { - margin-top: 20px; - margin-bottom: 20px; - border: 0; - border-top: 1px solid #eee; + margin-top: 20px; + margin-bottom: 20px; + border: 0; + border-top: 1px solid #eee; } + .sr-only { - position: absolute; - width: 1px; - height: 1px; - padding: 0; - margin: -1px; - overflow: hidden; - clip: rect(0, 0, 0, 0); - border: 0; + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + border: 0; } + h1, h2, h3, @@ -362,11 +436,12 @@ h6, .h4, .h5, .h6 { - font-family: inherit; - font-weight: 500; - line-height: 1.1; - color: inherit; + font-family: inherit; + font-weight: 500; + line-height: 1.1; + color: inherit; } + h1 small, h2 small, h3 small, @@ -391,19 +466,21 @@ h6 .small, .h4 .small, .h5 .small, .h6 .small { - font-weight: normal; - line-height: 1; - color: #999; + font-weight: normal; + line-height: 1; + color: #999; } + h1, .h1, h2, .h2, h3, .h3 { - margin-top: 20px; - margin-bottom: 10px; + margin-top: 20px; + margin-bottom: 10px; } + h1 small, .h1 small, h2 small, @@ -416,17 +493,19 @@ h2 .small, .h2 .small, h3 .small, .h3 .small { - font-size: 65%; + font-size: 65%; } + h4, .h4, h5, .h5, h6, .h6 { - margin-top: 10px; - margin-bottom: 10px; + margin-top: 10px; + margin-bottom: 10px; } + h4 small, .h4 small, h5 small, @@ -439,1049 +518,1346 @@ h5 .small, .h5 .small, h6 .small, .h6 .small { - font-size: 75%; + font-size: 75%; } + h1, .h1 { - font-size: 36px; + font-size: 36px; } + h2, .h2 { - font-size: 30px; + font-size: 30px; } + h3, .h3 { - font-size: 24px; + font-size: 24px; } + h4, .h4 { - font-size: 18px; + font-size: 18px; } + h5, .h5 { - font-size: 14px; + font-size: 14px; } + h6, .h6 { - font-size: 12px; + font-size: 12px; } + p { - margin: 0 0 10px; + margin: 0 0 10px; } + .lead { - margin-bottom: 20px; - font-size: 16px; - font-weight: 200; - line-height: 1.4; + margin-bottom: 20px; + font-size: 16px; + font-weight: 200; + line-height: 1.4; } + @media (min-width: 768px) { - .lead { - font-size: 21px; - } + .lead { + font-size: 21px; + } } + small, .small { - font-size: 85%; + font-size: 85%; } + cite { - font-style: normal; + font-style: normal; } + .text-left { - text-align: left; + text-align: left; } + .text-right { - text-align: right; + text-align: right; } + .text-center { - text-align: center; + text-align: center; } + .text-justify { - text-align: justify; + text-align: justify; } + .text-muted { - color: #999; + color: #999; } + .text-primary { - color: #428bca; + color: #428bca; } + a.text-primary:hover { - color: #3071a9; + color: #3071a9; } + .text-success { - color: #3c763d; + color: #3c763d; } + a.text-success:hover { - color: #2b542c; + color: #2b542c; } + .text-info { - color: #31708f; + color: #31708f; } + a.text-info:hover { - color: #245269; + color: #245269; } + .text-warning { - color: #8a6d3b; + color: #8a6d3b; } + a.text-warning:hover { - color: #66512c; + color: #66512c; } + .text-danger { - color: #a94442; + color: #a94442; } + a.text-danger:hover { - color: #843534; + color: #843534; } + .bg-primary { - color: #fff; - background-color: #428bca; + color: #fff; + background-color: #428bca; } + a.bg-primary:hover { - background-color: #3071a9; + background-color: #3071a9; } + .bg-success { - background-color: #dff0d8; + background-color: #dff0d8; } + a.bg-success:hover { - background-color: #c1e2b3; + background-color: #c1e2b3; } + .bg-info { - background-color: #d9edf7; + background-color: #d9edf7; } + a.bg-info:hover { - background-color: #afd9ee; + background-color: #afd9ee; } + .bg-warning { - background-color: #fcf8e3; + background-color: #fcf8e3; } + a.bg-warning:hover { - background-color: #f7ecb5; + background-color: #f7ecb5; } + .bg-danger { - background-color: #f2dede; + background-color: #f2dede; } + a.bg-danger:hover { - background-color: #e4b9b9; + background-color: #e4b9b9; } + .page-header { - padding-bottom: 9px; - margin: 40px 0 20px; - border-bottom: 1px solid #eee; + padding-bottom: 9px; + margin: 40px 0 20px; + border-bottom: 1px solid #eee; } + ul, ol { - margin-top: 0; - margin-bottom: 10px; + margin-top: 0; + margin-bottom: 10px; } + ul ul, ol ul, ul ol, ol ol { - margin-bottom: 0; + margin-bottom: 0; } + .list-unstyled { - padding-left: 0; - list-style: none; + padding-left: 0; + list-style: none; } + .list-inline { - padding-left: 0; - margin-left: -5px; - list-style: none; + padding-left: 0; + margin-left: -5px; + list-style: none; } + .list-inline > li { - display: inline-block; - padding-right: 5px; - padding-left: 5px; + display: inline-block; + padding-right: 5px; + padding-left: 5px; } + dl { - margin-top: 0; - margin-bottom: 20px; + margin-top: 0; + margin-bottom: 20px; } + dt, dd { - line-height: 1.42857143; + line-height: 1.42857143; } + dt { - font-weight: bold; + font-weight: bold; } + dd { - margin-left: 0; + margin-left: 0; } + @media (min-width: 768px) { - .dl-horizontal dt { - float: left; - width: 160px; - overflow: hidden; - clear: left; - text-align: right; - text-overflow: ellipsis; - white-space: nowrap; - } - .dl-horizontal dd { - margin-left: 180px; - } + .dl-horizontal dt { + float: left; + width: 160px; + overflow: hidden; + clear: left; + text-align: right; + text-overflow: ellipsis; + white-space: nowrap; + } + + .dl-horizontal dd { + margin-left: 180px; + } } + abbr[title], abbr[data-original-title] { - cursor: help; - border-bottom: 1px dotted #999; + cursor: help; + border-bottom: 1px dotted #999; } + .initialism { - font-size: 90%; - text-transform: uppercase; + font-size: 90%; + text-transform: uppercase; } + blockquote { - padding: 10px 20px; - margin: 0 0 20px; - font-size: 17.5px; - border-left: 5px solid #eee; + padding: 10px 20px; + margin: 0 0 20px; + font-size: 17.5px; + border-left: 5px solid #eee; } + blockquote p:last-child, blockquote ul:last-child, blockquote ol:last-child { - margin-bottom: 0; + margin-bottom: 0; } + blockquote footer, blockquote small, blockquote .small { - display: block; - font-size: 80%; - line-height: 1.42857143; - color: #999; + display: block; + font-size: 80%; + line-height: 1.42857143; + color: #999; } + blockquote footer:before, blockquote small:before, blockquote .small:before { - content: '\2014 \00A0'; + content: '\2014 \00A0'; } + .blockquote-reverse, blockquote.pull-right { - padding-right: 15px; - padding-left: 0; - text-align: right; - border-right: 5px solid #eee; - border-left: 0; + padding-right: 15px; + padding-left: 0; + text-align: right; + border-right: 5px solid #eee; + border-left: 0; } + .blockquote-reverse footer:before, blockquote.pull-right footer:before, .blockquote-reverse small:before, blockquote.pull-right small:before, .blockquote-reverse .small:before, blockquote.pull-right .small:before { - content: ''; + content: ''; } + .blockquote-reverse footer:after, blockquote.pull-right footer:after, .blockquote-reverse small:after, blockquote.pull-right small:after, .blockquote-reverse .small:after, blockquote.pull-right .small:after { - content: '\00A0 \2014'; + content: '\00A0 \2014'; } + blockquote:before, blockquote:after { - content: ""; + content: ""; } + address { - margin-bottom: 20px; - font-style: normal; - line-height: 1.42857143; + margin-bottom: 20px; + font-style: normal; + line-height: 1.42857143; } + code, kbd, pre, samp { - font-family: Menlo, Monaco, Consolas, "Courier New", monospace; + font-family: Menlo, Monaco, Consolas, "Courier New", monospace; } + code { - padding: 2px 4px; - font-size: 90%; - color: #c7254e; - white-space: nowrap; - background-color: #f9f2f4; - border-radius: 4px; + padding: 2px 4px; + font-size: 90%; + color: #c7254e; + white-space: nowrap; + background-color: #f9f2f4; + border-radius: 4px; } + kbd { - padding: 2px 4px; - font-size: 90%; - color: #fff; - background-color: #333; - border-radius: 3px; - box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); + padding: 2px 4px; + font-size: 90%; + color: #fff; + background-color: #333; + border-radius: 3px; + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .25); } + pre { - display: block; - padding: 9.5px; - margin: 0 0 10px; - font-size: 13px; - line-height: 1.42857143; - color: #333; - word-break: break-all; - word-wrap: break-word; - background-color: #f5f5f5; - border: 1px solid #ccc; - border-radius: 4px; + display: block; + padding: 9.5px; + margin: 0 0 10px; + font-size: 13px; + line-height: 1.42857143; + color: #333; + word-break: break-all; + word-wrap: break-word; + background-color: #f5f5f5; + border: 1px solid #ccc; + border-radius: 4px; } + pre code { - padding: 0; - font-size: inherit; - color: inherit; - white-space: pre-wrap; - background-color: transparent; - border-radius: 0; + padding: 0; + font-size: inherit; + color: inherit; + white-space: pre-wrap; + background-color: transparent; + border-radius: 0; } + .pre-scrollable { - max-height: 340px; - overflow-y: scroll; + max-height: 340px; + overflow-y: scroll; } + .container { - padding-right: 15px; - padding-left: 15px; - margin-right: auto; - margin-left: auto; + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; } + @media (min-width: 768px) { - .container { - width: 750px; - } + .container { + width: 750px; + } } + @media (min-width: 992px) { - .container { - width: 970px; - } + .container { + width: 970px; + } } + @media (min-width: 1200px) { - .container { - width: 1170px; - } + .container { + width: 1170px; + } } + .container-fluid { - padding-right: 15px; - padding-left: 15px; - margin-right: auto; - margin-left: auto; + padding-right: 15px; + padding-left: 15px; + margin-right: auto; + margin-left: auto; } + .row { - margin-right: -15px; - margin-left: -15px; + margin-right: -15px; + margin-left: -15px; } + .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 { - position: relative; - min-height: 1px; - padding-right: 15px; - padding-left: 15px; + position: relative; + min-height: 1px; + padding-right: 15px; + padding-left: 15px; } + .col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 { - float: left; + float: left; } + .col-xs-12 { - width: 100%; + width: 100%; } + .col-xs-11 { - width: 91.66666667%; + width: 91.66666667%; } + .col-xs-10 { - width: 83.33333333%; + width: 83.33333333%; } + .col-xs-9 { - width: 75%; + width: 75%; } + .col-xs-8 { - width: 66.66666667%; + width: 66.66666667%; } + .col-xs-7 { - width: 58.33333333%; + width: 58.33333333%; } + .col-xs-6 { - width: 50%; + width: 50%; } + .col-xs-5 { - width: 41.66666667%; + width: 41.66666667%; } + .col-xs-4 { - width: 33.33333333%; + width: 33.33333333%; } + .col-xs-3 { - width: 25%; + width: 25%; } + .col-xs-2 { - width: 16.66666667%; + width: 16.66666667%; } + .col-xs-1 { - width: 8.33333333%; + width: 8.33333333%; } + .col-xs-pull-12 { - right: 100%; + right: 100%; } + .col-xs-pull-11 { - right: 91.66666667%; + right: 91.66666667%; } + .col-xs-pull-10 { - right: 83.33333333%; + right: 83.33333333%; } + .col-xs-pull-9 { - right: 75%; + right: 75%; } + .col-xs-pull-8 { - right: 66.66666667%; + right: 66.66666667%; } + .col-xs-pull-7 { - right: 58.33333333%; + right: 58.33333333%; } + .col-xs-pull-6 { - right: 50%; + right: 50%; } + .col-xs-pull-5 { - right: 41.66666667%; + right: 41.66666667%; } + .col-xs-pull-4 { - right: 33.33333333%; + right: 33.33333333%; } + .col-xs-pull-3 { - right: 25%; + right: 25%; } + .col-xs-pull-2 { - right: 16.66666667%; + right: 16.66666667%; } + .col-xs-pull-1 { - right: 8.33333333%; + right: 8.33333333%; } + .col-xs-pull-0 { - right: 0; + right: 0; } + .col-xs-push-12 { - left: 100%; + left: 100%; } + .col-xs-push-11 { - left: 91.66666667%; + left: 91.66666667%; } + .col-xs-push-10 { - left: 83.33333333%; + left: 83.33333333%; } + .col-xs-push-9 { - left: 75%; + left: 75%; } + .col-xs-push-8 { - left: 66.66666667%; + left: 66.66666667%; } + .col-xs-push-7 { - left: 58.33333333%; + left: 58.33333333%; } + .col-xs-push-6 { - left: 50%; + left: 50%; } + .col-xs-push-5 { - left: 41.66666667%; + left: 41.66666667%; } + .col-xs-push-4 { - left: 33.33333333%; + left: 33.33333333%; } + .col-xs-push-3 { - left: 25%; + left: 25%; } + .col-xs-push-2 { - left: 16.66666667%; + left: 16.66666667%; } + .col-xs-push-1 { - left: 8.33333333%; + left: 8.33333333%; } + .col-xs-push-0 { - left: 0; + left: 0; } + .col-xs-offset-12 { - margin-left: 100%; + margin-left: 100%; } + .col-xs-offset-11 { - margin-left: 91.66666667%; + margin-left: 91.66666667%; } + .col-xs-offset-10 { - margin-left: 83.33333333%; + margin-left: 83.33333333%; } + .col-xs-offset-9 { - margin-left: 75%; + margin-left: 75%; } + .col-xs-offset-8 { - margin-left: 66.66666667%; + margin-left: 66.66666667%; } + .col-xs-offset-7 { - margin-left: 58.33333333%; + margin-left: 58.33333333%; } + .col-xs-offset-6 { - margin-left: 50%; + margin-left: 50%; } + .col-xs-offset-5 { - margin-left: 41.66666667%; + margin-left: 41.66666667%; } + .col-xs-offset-4 { - margin-left: 33.33333333%; + margin-left: 33.33333333%; } + .col-xs-offset-3 { - margin-left: 25%; + margin-left: 25%; } + .col-xs-offset-2 { - margin-left: 16.66666667%; + margin-left: 16.66666667%; } + .col-xs-offset-1 { - margin-left: 8.33333333%; + margin-left: 8.33333333%; } + .col-xs-offset-0 { - margin-left: 0; + margin-left: 0; } + @media (min-width: 768px) { - .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 { - float: left; - } - .col-sm-12 { - width: 100%; - } - .col-sm-11 { - width: 91.66666667%; - } - .col-sm-10 { - width: 83.33333333%; - } - .col-sm-9 { - width: 75%; - } - .col-sm-8 { - width: 66.66666667%; - } - .col-sm-7 { - width: 58.33333333%; - } - .col-sm-6 { - width: 50%; - } - .col-sm-5 { - width: 41.66666667%; - } - .col-sm-4 { - width: 33.33333333%; - } - .col-sm-3 { - width: 25%; - } - .col-sm-2 { - width: 16.66666667%; - } - .col-sm-1 { - width: 8.33333333%; - } - .col-sm-pull-12 { - right: 100%; - } - .col-sm-pull-11 { - right: 91.66666667%; - } - .col-sm-pull-10 { - right: 83.33333333%; - } - .col-sm-pull-9 { - right: 75%; - } - .col-sm-pull-8 { - right: 66.66666667%; - } - .col-sm-pull-7 { - right: 58.33333333%; - } - .col-sm-pull-6 { - right: 50%; - } - .col-sm-pull-5 { - right: 41.66666667%; - } - .col-sm-pull-4 { - right: 33.33333333%; - } - .col-sm-pull-3 { - right: 25%; - } - .col-sm-pull-2 { - right: 16.66666667%; - } - .col-sm-pull-1 { - right: 8.33333333%; - } - .col-sm-pull-0 { - right: 0; - } - .col-sm-push-12 { - left: 100%; - } - .col-sm-push-11 { - left: 91.66666667%; - } - .col-sm-push-10 { - left: 83.33333333%; - } - .col-sm-push-9 { - left: 75%; - } - .col-sm-push-8 { - left: 66.66666667%; - } - .col-sm-push-7 { - left: 58.33333333%; - } - .col-sm-push-6 { - left: 50%; - } - .col-sm-push-5 { - left: 41.66666667%; - } - .col-sm-push-4 { - left: 33.33333333%; - } - .col-sm-push-3 { - left: 25%; - } - .col-sm-push-2 { - left: 16.66666667%; - } - .col-sm-push-1 { - left: 8.33333333%; - } - .col-sm-push-0 { - left: 0; - } - .col-sm-offset-12 { - margin-left: 100%; - } - .col-sm-offset-11 { - margin-left: 91.66666667%; - } - .col-sm-offset-10 { - margin-left: 83.33333333%; - } - .col-sm-offset-9 { - margin-left: 75%; - } - .col-sm-offset-8 { - margin-left: 66.66666667%; - } - .col-sm-offset-7 { - margin-left: 58.33333333%; - } - .col-sm-offset-6 { - margin-left: 50%; - } - .col-sm-offset-5 { - margin-left: 41.66666667%; - } - .col-sm-offset-4 { - margin-left: 33.33333333%; - } - .col-sm-offset-3 { - margin-left: 25%; - } - .col-sm-offset-2 { - margin-left: 16.66666667%; - } - .col-sm-offset-1 { - margin-left: 8.33333333%; - } - .col-sm-offset-0 { - margin-left: 0; - } + .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 { + float: left; + } + + .col-sm-12 { + width: 100%; + } + + .col-sm-11 { + width: 91.66666667%; + } + + .col-sm-10 { + width: 83.33333333%; + } + + .col-sm-9 { + width: 75%; + } + + .col-sm-8 { + width: 66.66666667%; + } + + .col-sm-7 { + width: 58.33333333%; + } + + .col-sm-6 { + width: 50%; + } + + .col-sm-5 { + width: 41.66666667%; + } + + .col-sm-4 { + width: 33.33333333%; + } + + .col-sm-3 { + width: 25%; + } + + .col-sm-2 { + width: 16.66666667%; + } + + .col-sm-1 { + width: 8.33333333%; + } + + .col-sm-pull-12 { + right: 100%; + } + + .col-sm-pull-11 { + right: 91.66666667%; + } + + .col-sm-pull-10 { + right: 83.33333333%; + } + + .col-sm-pull-9 { + right: 75%; + } + + .col-sm-pull-8 { + right: 66.66666667%; + } + + .col-sm-pull-7 { + right: 58.33333333%; + } + + .col-sm-pull-6 { + right: 50%; + } + + .col-sm-pull-5 { + right: 41.66666667%; + } + + .col-sm-pull-4 { + right: 33.33333333%; + } + + .col-sm-pull-3 { + right: 25%; + } + + .col-sm-pull-2 { + right: 16.66666667%; + } + + .col-sm-pull-1 { + right: 8.33333333%; + } + + .col-sm-pull-0 { + right: 0; + } + + .col-sm-push-12 { + left: 100%; + } + + .col-sm-push-11 { + left: 91.66666667%; + } + + .col-sm-push-10 { + left: 83.33333333%; + } + + .col-sm-push-9 { + left: 75%; + } + + .col-sm-push-8 { + left: 66.66666667%; + } + + .col-sm-push-7 { + left: 58.33333333%; + } + + .col-sm-push-6 { + left: 50%; + } + + .col-sm-push-5 { + left: 41.66666667%; + } + + .col-sm-push-4 { + left: 33.33333333%; + } + + .col-sm-push-3 { + left: 25%; + } + + .col-sm-push-2 { + left: 16.66666667%; + } + + .col-sm-push-1 { + left: 8.33333333%; + } + + .col-sm-push-0 { + left: 0; + } + + .col-sm-offset-12 { + margin-left: 100%; + } + + .col-sm-offset-11 { + margin-left: 91.66666667%; + } + + .col-sm-offset-10 { + margin-left: 83.33333333%; + } + + .col-sm-offset-9 { + margin-left: 75%; + } + + .col-sm-offset-8 { + margin-left: 66.66666667%; + } + + .col-sm-offset-7 { + margin-left: 58.33333333%; + } + + .col-sm-offset-6 { + margin-left: 50%; + } + + .col-sm-offset-5 { + margin-left: 41.66666667%; + } + + .col-sm-offset-4 { + margin-left: 33.33333333%; + } + + .col-sm-offset-3 { + margin-left: 25%; + } + + .col-sm-offset-2 { + margin-left: 16.66666667%; + } + + .col-sm-offset-1 { + margin-left: 8.33333333%; + } + + .col-sm-offset-0 { + margin-left: 0; + } } + @media (min-width: 992px) { - .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 { - float: left; - } - .col-md-12 { - width: 100%; - } - .col-md-11 { - width: 91.66666667%; - } - .col-md-10 { - width: 83.33333333%; - } - .col-md-9 { - width: 75%; - } - .col-md-8 { - width: 66.66666667%; - } - .col-md-7 { - width: 58.33333333%; - } - .col-md-6 { - width: 50%; - } - .col-md-5 { - width: 41.66666667%; - } - .col-md-4 { - width: 33.33333333%; - } - .col-md-3 { - width: 25%; - } - .col-md-2 { - width: 16.66666667%; - } - .col-md-1 { - width: 8.33333333%; - } - .col-md-pull-12 { - right: 100%; - } - .col-md-pull-11 { - right: 91.66666667%; - } - .col-md-pull-10 { - right: 83.33333333%; - } - .col-md-pull-9 { - right: 75%; - } - .col-md-pull-8 { - right: 66.66666667%; - } - .col-md-pull-7 { - right: 58.33333333%; - } - .col-md-pull-6 { - right: 50%; - } - .col-md-pull-5 { - right: 41.66666667%; - } - .col-md-pull-4 { - right: 33.33333333%; - } - .col-md-pull-3 { - right: 25%; - } - .col-md-pull-2 { - right: 16.66666667%; - } - .col-md-pull-1 { - right: 8.33333333%; - } - .col-md-pull-0 { - right: 0; - } - .col-md-push-12 { - left: 100%; - } - .col-md-push-11 { - left: 91.66666667%; - } - .col-md-push-10 { - left: 83.33333333%; - } - .col-md-push-9 { - left: 75%; - } - .col-md-push-8 { - left: 66.66666667%; - } - .col-md-push-7 { - left: 58.33333333%; - } - .col-md-push-6 { - left: 50%; - } - .col-md-push-5 { - left: 41.66666667%; - } - .col-md-push-4 { - left: 33.33333333%; - } - .col-md-push-3 { - left: 25%; - } - .col-md-push-2 { - left: 16.66666667%; - } - .col-md-push-1 { - left: 8.33333333%; - } - .col-md-push-0 { - left: 0; - } - .col-md-offset-12 { - margin-left: 100%; - } - .col-md-offset-11 { - margin-left: 91.66666667%; - } - .col-md-offset-10 { - margin-left: 83.33333333%; - } - .col-md-offset-9 { - margin-left: 75%; - } - .col-md-offset-8 { - margin-left: 66.66666667%; - } - .col-md-offset-7 { - margin-left: 58.33333333%; - } - .col-md-offset-6 { - margin-left: 50%; - } - .col-md-offset-5 { - margin-left: 41.66666667%; - } - .col-md-offset-4 { - margin-left: 33.33333333%; - } - .col-md-offset-3 { - margin-left: 25%; - } - .col-md-offset-2 { - margin-left: 16.66666667%; - } - .col-md-offset-1 { - margin-left: 8.33333333%; - } - .col-md-offset-0 { - margin-left: 0; - } + .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 { + float: left; + } + + .col-md-12 { + width: 100%; + } + + .col-md-11 { + width: 91.66666667%; + } + + .col-md-10 { + width: 83.33333333%; + } + + .col-md-9 { + width: 75%; + } + + .col-md-8 { + width: 66.66666667%; + } + + .col-md-7 { + width: 58.33333333%; + } + + .col-md-6 { + width: 50%; + } + + .col-md-5 { + width: 41.66666667%; + } + + .col-md-4 { + width: 33.33333333%; + } + + .col-md-3 { + width: 25%; + } + + .col-md-2 { + width: 16.66666667%; + } + + .col-md-1 { + width: 8.33333333%; + } + + .col-md-pull-12 { + right: 100%; + } + + .col-md-pull-11 { + right: 91.66666667%; + } + + .col-md-pull-10 { + right: 83.33333333%; + } + + .col-md-pull-9 { + right: 75%; + } + + .col-md-pull-8 { + right: 66.66666667%; + } + + .col-md-pull-7 { + right: 58.33333333%; + } + + .col-md-pull-6 { + right: 50%; + } + + .col-md-pull-5 { + right: 41.66666667%; + } + + .col-md-pull-4 { + right: 33.33333333%; + } + + .col-md-pull-3 { + right: 25%; + } + + .col-md-pull-2 { + right: 16.66666667%; + } + + .col-md-pull-1 { + right: 8.33333333%; + } + + .col-md-pull-0 { + right: 0; + } + + .col-md-push-12 { + left: 100%; + } + + .col-md-push-11 { + left: 91.66666667%; + } + + .col-md-push-10 { + left: 83.33333333%; + } + + .col-md-push-9 { + left: 75%; + } + + .col-md-push-8 { + left: 66.66666667%; + } + + .col-md-push-7 { + left: 58.33333333%; + } + + .col-md-push-6 { + left: 50%; + } + + .col-md-push-5 { + left: 41.66666667%; + } + + .col-md-push-4 { + left: 33.33333333%; + } + + .col-md-push-3 { + left: 25%; + } + + .col-md-push-2 { + left: 16.66666667%; + } + + .col-md-push-1 { + left: 8.33333333%; + } + + .col-md-push-0 { + left: 0; + } + + .col-md-offset-12 { + margin-left: 100%; + } + + .col-md-offset-11 { + margin-left: 91.66666667%; + } + + .col-md-offset-10 { + margin-left: 83.33333333%; + } + + .col-md-offset-9 { + margin-left: 75%; + } + + .col-md-offset-8 { + margin-left: 66.66666667%; + } + + .col-md-offset-7 { + margin-left: 58.33333333%; + } + + .col-md-offset-6 { + margin-left: 50%; + } + + .col-md-offset-5 { + margin-left: 41.66666667%; + } + + .col-md-offset-4 { + margin-left: 33.33333333%; + } + + .col-md-offset-3 { + margin-left: 25%; + } + + .col-md-offset-2 { + margin-left: 16.66666667%; + } + + .col-md-offset-1 { + margin-left: 8.33333333%; + } + + .col-md-offset-0 { + margin-left: 0; + } } + @media (min-width: 1200px) { - .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 { - float: left; - } - .col-lg-12 { - width: 100%; - } - .col-lg-11 { - width: 91.66666667%; - } - .col-lg-10 { - width: 83.33333333%; - } - .col-lg-9 { - width: 75%; - } - .col-lg-8 { - width: 66.66666667%; - } - .col-lg-7 { - width: 58.33333333%; - } - .col-lg-6 { - width: 50%; - } - .col-lg-5 { - width: 41.66666667%; - } - .col-lg-4 { - width: 33.33333333%; - } - .col-lg-3 { - width: 25%; - } - .col-lg-2 { - width: 16.66666667%; - } - .col-lg-1 { - width: 8.33333333%; - } - .col-lg-pull-12 { - right: 100%; - } - .col-lg-pull-11 { - right: 91.66666667%; - } - .col-lg-pull-10 { - right: 83.33333333%; - } - .col-lg-pull-9 { - right: 75%; - } - .col-lg-pull-8 { - right: 66.66666667%; - } - .col-lg-pull-7 { - right: 58.33333333%; - } - .col-lg-pull-6 { - right: 50%; - } - .col-lg-pull-5 { - right: 41.66666667%; - } - .col-lg-pull-4 { - right: 33.33333333%; - } - .col-lg-pull-3 { - right: 25%; - } - .col-lg-pull-2 { - right: 16.66666667%; - } - .col-lg-pull-1 { - right: 8.33333333%; - } - .col-lg-pull-0 { - right: 0; - } - .col-lg-push-12 { - left: 100%; - } - .col-lg-push-11 { - left: 91.66666667%; - } - .col-lg-push-10 { - left: 83.33333333%; - } - .col-lg-push-9 { - left: 75%; - } - .col-lg-push-8 { - left: 66.66666667%; - } - .col-lg-push-7 { - left: 58.33333333%; - } - .col-lg-push-6 { - left: 50%; - } - .col-lg-push-5 { - left: 41.66666667%; - } - .col-lg-push-4 { - left: 33.33333333%; - } - .col-lg-push-3 { - left: 25%; - } - .col-lg-push-2 { - left: 16.66666667%; - } - .col-lg-push-1 { - left: 8.33333333%; - } - .col-lg-push-0 { - left: 0; - } - .col-lg-offset-12 { - margin-left: 100%; - } - .col-lg-offset-11 { - margin-left: 91.66666667%; - } - .col-lg-offset-10 { - margin-left: 83.33333333%; - } - .col-lg-offset-9 { - margin-left: 75%; - } - .col-lg-offset-8 { - margin-left: 66.66666667%; - } - .col-lg-offset-7 { - margin-left: 58.33333333%; - } - .col-lg-offset-6 { - margin-left: 50%; - } - .col-lg-offset-5 { - margin-left: 41.66666667%; - } - .col-lg-offset-4 { - margin-left: 33.33333333%; - } - .col-lg-offset-3 { - margin-left: 25%; - } - .col-lg-offset-2 { - margin-left: 16.66666667%; - } - .col-lg-offset-1 { - margin-left: 8.33333333%; - } - .col-lg-offset-0 { - margin-left: 0; - } + .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 { + float: left; + } + + .col-lg-12 { + width: 100%; + } + + .col-lg-11 { + width: 91.66666667%; + } + + .col-lg-10 { + width: 83.33333333%; + } + + .col-lg-9 { + width: 75%; + } + + .col-lg-8 { + width: 66.66666667%; + } + + .col-lg-7 { + width: 58.33333333%; + } + + .col-lg-6 { + width: 50%; + } + + .col-lg-5 { + width: 41.66666667%; + } + + .col-lg-4 { + width: 33.33333333%; + } + + .col-lg-3 { + width: 25%; + } + + .col-lg-2 { + width: 16.66666667%; + } + + .col-lg-1 { + width: 8.33333333%; + } + + .col-lg-pull-12 { + right: 100%; + } + + .col-lg-pull-11 { + right: 91.66666667%; + } + + .col-lg-pull-10 { + right: 83.33333333%; + } + + .col-lg-pull-9 { + right: 75%; + } + + .col-lg-pull-8 { + right: 66.66666667%; + } + + .col-lg-pull-7 { + right: 58.33333333%; + } + + .col-lg-pull-6 { + right: 50%; + } + + .col-lg-pull-5 { + right: 41.66666667%; + } + + .col-lg-pull-4 { + right: 33.33333333%; + } + + .col-lg-pull-3 { + right: 25%; + } + + .col-lg-pull-2 { + right: 16.66666667%; + } + + .col-lg-pull-1 { + right: 8.33333333%; + } + + .col-lg-pull-0 { + right: 0; + } + + .col-lg-push-12 { + left: 100%; + } + + .col-lg-push-11 { + left: 91.66666667%; + } + + .col-lg-push-10 { + left: 83.33333333%; + } + + .col-lg-push-9 { + left: 75%; + } + + .col-lg-push-8 { + left: 66.66666667%; + } + + .col-lg-push-7 { + left: 58.33333333%; + } + + .col-lg-push-6 { + left: 50%; + } + + .col-lg-push-5 { + left: 41.66666667%; + } + + .col-lg-push-4 { + left: 33.33333333%; + } + + .col-lg-push-3 { + left: 25%; + } + + .col-lg-push-2 { + left: 16.66666667%; + } + + .col-lg-push-1 { + left: 8.33333333%; + } + + .col-lg-push-0 { + left: 0; + } + + .col-lg-offset-12 { + margin-left: 100%; + } + + .col-lg-offset-11 { + margin-left: 91.66666667%; + } + + .col-lg-offset-10 { + margin-left: 83.33333333%; + } + + .col-lg-offset-9 { + margin-left: 75%; + } + + .col-lg-offset-8 { + margin-left: 66.66666667%; + } + + .col-lg-offset-7 { + margin-left: 58.33333333%; + } + + .col-lg-offset-6 { + margin-left: 50%; + } + + .col-lg-offset-5 { + margin-left: 41.66666667%; + } + + .col-lg-offset-4 { + margin-left: 33.33333333%; + } + + .col-lg-offset-3 { + margin-left: 25%; + } + + .col-lg-offset-2 { + margin-left: 16.66666667%; + } + + .col-lg-offset-1 { + margin-left: 8.33333333%; + } + + .col-lg-offset-0 { + margin-left: 0; + } } + table { - max-width: 100%; - background-color: transparent; + max-width: 100%; + background-color: transparent; } + th { - text-align: left; + text-align: left; } + .table { - width: 100%; - margin-bottom: 20px; + width: 100%; + margin-bottom: 20px; } + .table > thead > tr > th, .table > tbody > tr > th, .table > tfoot > tr > th, .table > thead > tr > td, .table > tbody > tr > td, .table > tfoot > tr > td { - padding: 8px; - line-height: 1.42857143; - vertical-align: top; - border-top: 1px solid #ddd; + padding: 8px; + line-height: 1.42857143; + vertical-align: top; + border-top: 1px solid #ddd; } + .table > thead > tr > th { - vertical-align: bottom; - border-bottom: 2px solid #ddd; + vertical-align: bottom; + border-bottom: 2px solid #ddd; } + .table > caption + thead > tr:first-child > th, .table > colgroup + thead > tr:first-child > th, .table > thead:first-child > tr:first-child > th, .table > caption + thead > tr:first-child > td, .table > colgroup + thead > tr:first-child > td, .table > thead:first-child > tr:first-child > td { - border-top: 0; + border-top: 0; } + .table > tbody + tbody { - border-top: 2px solid #ddd; + border-top: 2px solid #ddd; } + .table .table { - background-color: #fff; + background-color: #fff; } + .table-condensed > thead > tr > th, .table-condensed > tbody > tr > th, .table-condensed > tfoot > tr > th, .table-condensed > thead > tr > td, .table-condensed > tbody > tr > td, .table-condensed > tfoot > tr > td { - padding: 5px; + padding: 5px; } + .table-bordered { - border: 1px solid #ddd; + border: 1px solid #ddd; } + .table-bordered > thead > tr > th, .table-bordered > tbody > tr > th, .table-bordered > tfoot > tr > th, .table-bordered > thead > tr > td, .table-bordered > tbody > tr > td, .table-bordered > tfoot > tr > td { - border: 1px solid #ddd; + border: 1px solid #ddd; } + .table-bordered > thead > tr > th, .table-bordered > thead > tr > td { - border-bottom-width: 2px; + border-bottom-width: 2px; } + .table-striped > tbody > tr:nth-child(odd) > td, .table-striped > tbody > tr:nth-child(odd) > th { - background-color: #f9f9f9; + background-color: #f9f9f9; } + .table-hover > tbody > tr:hover > td, .table-hover > tbody > tr:hover > th { - background-color: #f5f5f5; + background-color: #f5f5f5; } + table col[class*="col-"] { - position: static; - display: table-column; - float: none; + position: static; + display: table-column; + float: none; } + table td[class*="col-"], table th[class*="col-"] { - position: static; - display: table-cell; - float: none; + position: static; + display: table-cell; + float: none; } + .table > thead > tr > td.active, .table > tbody > tr > td.active, .table > tfoot > tr > td.active, @@ -1494,14 +1870,16 @@ table th[class*="col-"] { .table > thead > tr.active > th, .table > tbody > tr.active > th, .table > tfoot > tr.active > th { - background-color: #f5f5f5; + background-color: #f5f5f5; } + .table-hover > tbody > tr > td.active:hover, .table-hover > tbody > tr > th.active:hover, .table-hover > tbody > tr.active:hover > td, .table-hover > tbody > tr.active:hover > th { - background-color: #e8e8e8; + background-color: #e8e8e8; } + .table > thead > tr > td.success, .table > tbody > tr > td.success, .table > tfoot > tr > td.success, @@ -1514,14 +1892,16 @@ table th[class*="col-"] { .table > thead > tr.success > th, .table > tbody > tr.success > th, .table > tfoot > tr.success > th { - background-color: #dff0d8; + background-color: #dff0d8; } + .table-hover > tbody > tr > td.success:hover, .table-hover > tbody > tr > th.success:hover, .table-hover > tbody > tr.success:hover > td, .table-hover > tbody > tr.success:hover > th { - background-color: #d0e9c6; + background-color: #d0e9c6; } + .table > thead > tr > td.info, .table > tbody > tr > td.info, .table > tfoot > tr > td.info, @@ -1534,14 +1914,16 @@ table th[class*="col-"] { .table > thead > tr.info > th, .table > tbody > tr.info > th, .table > tfoot > tr.info > th { - background-color: #d9edf7; + background-color: #d9edf7; } + .table-hover > tbody > tr > td.info:hover, .table-hover > tbody > tr > th.info:hover, .table-hover > tbody > tr.info:hover > td, .table-hover > tbody > tr.info:hover > th { - background-color: #c4e3f3; + background-color: #c4e3f3; } + .table > thead > tr > td.warning, .table > tbody > tr > td.warning, .table > tfoot > tr > td.warning, @@ -1554,14 +1936,16 @@ table th[class*="col-"] { .table > thead > tr.warning > th, .table > tbody > tr.warning > th, .table > tfoot > tr.warning > th { - background-color: #fcf8e3; + background-color: #fcf8e3; } + .table-hover > tbody > tr > td.warning:hover, .table-hover > tbody > tr > th.warning:hover, .table-hover > tbody > tr.warning:hover > td, .table-hover > tbody > tr.warning:hover > th { - background-color: #faf2cc; + background-color: #faf2cc; } + .table > thead > tr > td.danger, .table > tbody > tr > td.danger, .table > tfoot > tr > td.danger, @@ -1574,211 +1958,246 @@ table th[class*="col-"] { .table > thead > tr.danger > th, .table > tbody > tr.danger > th, .table > tfoot > tr.danger > th { - background-color: #f2dede; + background-color: #f2dede; } + .table-hover > tbody > tr > td.danger:hover, .table-hover > tbody > tr > th.danger:hover, .table-hover > tbody > tr.danger:hover > td, .table-hover > tbody > tr.danger:hover > th { - background-color: #ebcccc; + background-color: #ebcccc; } + @media (max-width: 767px) { - .table-responsive { - width: 100%; - margin-bottom: 15px; - overflow-x: scroll; - overflow-y: hidden; - -webkit-overflow-scrolling: touch; - -ms-overflow-style: -ms-autohiding-scrollbar; - border: 1px solid #ddd; - } - .table-responsive > .table { - margin-bottom: 0; - } - .table-responsive > .table > thead > tr > th, - .table-responsive > .table > tbody > tr > th, - .table-responsive > .table > tfoot > tr > th, - .table-responsive > .table > thead > tr > td, - .table-responsive > .table > tbody > tr > td, - .table-responsive > .table > tfoot > tr > td { - white-space: nowrap; - } - .table-responsive > .table-bordered { - border: 0; - } - .table-responsive > .table-bordered > thead > tr > th:first-child, - .table-responsive > .table-bordered > tbody > tr > th:first-child, - .table-responsive > .table-bordered > tfoot > tr > th:first-child, - .table-responsive > .table-bordered > thead > tr > td:first-child, - .table-responsive > .table-bordered > tbody > tr > td:first-child, - .table-responsive > .table-bordered > tfoot > tr > td:first-child { - border-left: 0; - } - .table-responsive > .table-bordered > thead > tr > th:last-child, - .table-responsive > .table-bordered > tbody > tr > th:last-child, - .table-responsive > .table-bordered > tfoot > tr > th:last-child, - .table-responsive > .table-bordered > thead > tr > td:last-child, - .table-responsive > .table-bordered > tbody > tr > td:last-child, - .table-responsive > .table-bordered > tfoot > tr > td:last-child { - border-right: 0; - } - .table-responsive > .table-bordered > tbody > tr:last-child > th, - .table-responsive > .table-bordered > tfoot > tr:last-child > th, - .table-responsive > .table-bordered > tbody > tr:last-child > td, - .table-responsive > .table-bordered > tfoot > tr:last-child > td { - border-bottom: 0; - } + .table-responsive { + width: 100%; + margin-bottom: 15px; + overflow-x: scroll; + overflow-y: hidden; + -webkit-overflow-scrolling: touch; + -ms-overflow-style: -ms-autohiding-scrollbar; + border: 1px solid #ddd; + } + + .table-responsive > .table { + margin-bottom: 0; + } + + .table-responsive > .table > thead > tr > th, + .table-responsive > .table > tbody > tr > th, + .table-responsive > .table > tfoot > tr > th, + .table-responsive > .table > thead > tr > td, + .table-responsive > .table > tbody > tr > td, + .table-responsive > .table > tfoot > tr > td { + white-space: nowrap; + } + + .table-responsive > .table-bordered { + border: 0; + } + + .table-responsive > .table-bordered > thead > tr > th:first-child, + .table-responsive > .table-bordered > tbody > tr > th:first-child, + .table-responsive > .table-bordered > tfoot > tr > th:first-child, + .table-responsive > .table-bordered > thead > tr > td:first-child, + .table-responsive > .table-bordered > tbody > tr > td:first-child, + .table-responsive > .table-bordered > tfoot > tr > td:first-child { + border-left: 0; + } + + .table-responsive > .table-bordered > thead > tr > th:last-child, + .table-responsive > .table-bordered > tbody > tr > th:last-child, + .table-responsive > .table-bordered > tfoot > tr > th:last-child, + .table-responsive > .table-bordered > thead > tr > td:last-child, + .table-responsive > .table-bordered > tbody > tr > td:last-child, + .table-responsive > .table-bordered > tfoot > tr > td:last-child { + border-right: 0; + } + + .table-responsive > .table-bordered > tbody > tr:last-child > th, + .table-responsive > .table-bordered > tfoot > tr:last-child > th, + .table-responsive > .table-bordered > tbody > tr:last-child > td, + .table-responsive > .table-bordered > tfoot > tr:last-child > td { + border-bottom: 0; + } } + fieldset { - min-width: 0; - padding: 0; - margin: 0; - border: 0; + min-width: 0; + padding: 0; + margin: 0; + border: 0; } + legend { - display: block; - width: 100%; - padding: 0; - margin-bottom: 20px; - font-size: 21px; - line-height: inherit; - color: #333; - border: 0; - border-bottom: 1px solid #e5e5e5; + display: block; + width: 100%; + padding: 0; + margin-bottom: 20px; + font-size: 21px; + line-height: inherit; + color: #333; + border: 0; + border-bottom: 1px solid #e5e5e5; } + label { - display: inline-block; - margin-bottom: 5px; - font-weight: bold; + display: inline-block; + margin-bottom: 5px; + font-weight: bold; } + input[type="search"] { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; } + input[type="radio"], input[type="checkbox"] { - margin: 4px 0 0; - margin-top: 1px \9; - /* IE8-9 */ - line-height: normal; + margin: 4px 0 0; + margin-top: 1px \9; + /* IE8-9 */ + line-height: normal; } + input[type="file"] { - display: block; + display: block; } + input[type="range"] { - display: block; - width: 100%; + display: block; + width: 100%; } + select[multiple], select[size] { - height: auto; + height: auto; } + input[type="file"]:focus, input[type="radio"]:focus, input[type="checkbox"]:focus { - outline: thin dotted; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; } + output { - display: block; - padding-top: 7px; - font-size: 14px; - line-height: 1.42857143; - color: #555; + display: block; + padding-top: 7px; + font-size: 14px; + line-height: 1.42857143; + color: #555; } + .form-control { - display: block; - width: 100%; - height: 34px; - padding: 6px 12px; - font-size: 14px; - line-height: 1.42857143; - color: #555; - background-color: #fff; - background-image: none; - border: 1px solid #ccc; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; - transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + display: block; + width: 100%; + height: 34px; + padding: 6px 12px; + font-size: 14px; + line-height: 1.42857143; + color: #555; + background-color: #fff; + background-image: none; + border: 1px solid #ccc; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + -webkit-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; + transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s; } + .form-control:focus { - border-color: #66afe9; - outline: 0; - -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); - box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, .6); + border-color: #66afe9; + outline: 0; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, .6); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 8px rgba(102, 175, 233, .6); } + .form-control::-moz-placeholder { - color: #999; - opacity: 1; + color: #999; + opacity: 1; } + .form-control:-ms-input-placeholder { - color: #999; + color: #999; } + .form-control::-webkit-input-placeholder { - color: #999; + color: #999; } + .form-control[disabled], .form-control[readonly], fieldset[disabled] .form-control { - cursor: not-allowed; - background-color: #eee; - opacity: 1; + cursor: not-allowed; + background-color: #eee; + opacity: 1; } + textarea.form-control { - height: auto; + height: auto; } + input[type="search"] { - -webkit-appearance: none; + -webkit-appearance: none; } + input[type="date"] { - line-height: 34px; + line-height: 34px; } + .form-group { - margin-bottom: 15px; + margin-bottom: 15px; } + .radio, .checkbox { - display: block; - min-height: 20px; - padding-left: 20px; - margin-top: 10px; - margin-bottom: 10px; + display: block; + min-height: 20px; + padding-left: 20px; + margin-top: 10px; + margin-bottom: 10px; } + .radio label, .checkbox label { - display: inline; - font-weight: normal; - cursor: pointer; + display: inline; + font-weight: normal; + cursor: pointer; } + .radio input[type="radio"], .radio-inline input[type="radio"], .checkbox input[type="checkbox"], .checkbox-inline input[type="checkbox"] { - float: left; - margin-left: -20px; + float: left; + margin-left: -20px; } + .radio + .radio, .checkbox + .checkbox { - margin-top: -5px; + margin-top: -5px; } + .radio-inline, .checkbox-inline { - display: inline-block; - padding-left: 20px; - margin-bottom: 0; - font-weight: normal; - vertical-align: middle; - cursor: pointer; + display: inline-block; + padding-left: 20px; + margin-bottom: 0; + font-weight: normal; + vertical-align: middle; + cursor: pointer; } + .radio-inline + .radio-inline, .checkbox-inline + .checkbox-inline { - margin-top: 0; - margin-left: 10px; + margin-top: 0; + margin-left: 10px; } + input[type="radio"][disabled], input[type="checkbox"][disabled], .radio[disabled], @@ -1791,272 +2210,320 @@ fieldset[disabled] .radio, fieldset[disabled] .radio-inline, fieldset[disabled] .checkbox, fieldset[disabled] .checkbox-inline { - cursor: not-allowed; + cursor: not-allowed; } + .input-sm { - height: 30px; - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; } + select.input-sm { - height: 30px; - line-height: 30px; + height: 30px; + line-height: 30px; } + textarea.input-sm, select[multiple].input-sm { - height: auto; + height: auto; } + .input-lg { - height: 46px; - padding: 10px 16px; - font-size: 18px; - line-height: 1.33; - border-radius: 6px; + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; } + select.input-lg { - height: 46px; - line-height: 46px; + height: 46px; + line-height: 46px; } + textarea.input-lg, select[multiple].input-lg { - height: auto; + height: auto; } + .has-feedback { - position: relative; + position: relative; } + .has-feedback .form-control { - padding-right: 42.5px; + padding-right: 42.5px; } + .has-feedback .form-control-feedback { - position: absolute; - top: 25px; - right: 0; - display: block; - width: 34px; - height: 34px; - line-height: 34px; - text-align: center; + position: absolute; + top: 25px; + right: 0; + display: block; + width: 34px; + height: 34px; + line-height: 34px; + text-align: center; } + .has-success .help-block, .has-success .control-label, .has-success .radio, .has-success .checkbox, .has-success .radio-inline, .has-success .checkbox-inline { - color: #3c763d; + color: #3c763d; } + .has-success .form-control { - border-color: #3c763d; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + border-color: #3c763d; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); } + .has-success .form-control:focus { - border-color: #2b542c; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; + border-color: #2b542c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #67b168; } + .has-success .input-group-addon { - color: #3c763d; - background-color: #dff0d8; - border-color: #3c763d; + color: #3c763d; + background-color: #dff0d8; + border-color: #3c763d; } + .has-success .form-control-feedback { - color: #3c763d; + color: #3c763d; } + .has-warning .help-block, .has-warning .control-label, .has-warning .radio, .has-warning .checkbox, .has-warning .radio-inline, .has-warning .checkbox-inline { - color: #8a6d3b; + color: #8a6d3b; } + .has-warning .form-control { - border-color: #8a6d3b; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + border-color: #8a6d3b; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); } + .has-warning .form-control:focus { - border-color: #66512c; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; + border-color: #66512c; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #c0a16b; } + .has-warning .input-group-addon { - color: #8a6d3b; - background-color: #fcf8e3; - border-color: #8a6d3b; + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #8a6d3b; } + .has-warning .form-control-feedback { - color: #8a6d3b; + color: #8a6d3b; } + .has-error .help-block, .has-error .control-label, .has-error .radio, .has-error .checkbox, .has-error .radio-inline, .has-error .checkbox-inline { - color: #a94442; + color: #a94442; } + .has-error .form-control { - border-color: #a94442; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + border-color: #a94442; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); } + .has-error .form-control:focus { - border-color: #843534; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; + border-color: #843534; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075), 0 0 6px #ce8483; } + .has-error .input-group-addon { - color: #a94442; - background-color: #f2dede; - border-color: #a94442; + color: #a94442; + background-color: #f2dede; + border-color: #a94442; } + .has-error .form-control-feedback { - color: #a94442; + color: #a94442; } + .form-control-static { - margin-bottom: 0; + margin-bottom: 0; } + .help-block { - display: block; - margin-top: 5px; - margin-bottom: 10px; - color: #737373; + display: block; + margin-top: 5px; + margin-bottom: 10px; + color: #737373; } + @media (min-width: 768px) { - .form-inline .form-group { - display: inline-block; - margin-bottom: 0; - vertical-align: middle; - } - .form-inline .form-control { - display: inline-block; - width: auto; - vertical-align: middle; - } - .form-inline .input-group > .form-control { - width: 100%; - } - .form-inline .control-label { - margin-bottom: 0; - vertical-align: middle; - } - .form-inline .radio, - .form-inline .checkbox { - display: inline-block; - padding-left: 0; - margin-top: 0; - margin-bottom: 0; - vertical-align: middle; - } - .form-inline .radio input[type="radio"], - .form-inline .checkbox input[type="checkbox"] { - float: none; - margin-left: 0; - } - .form-inline .has-feedback .form-control-feedback { - top: 0; - } + .form-inline .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + + .form-inline .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + + .form-inline .input-group > .form-control { + width: 100%; + } + + .form-inline .control-label { + margin-bottom: 0; + vertical-align: middle; + } + + .form-inline .radio, + .form-inline .checkbox { + display: inline-block; + padding-left: 0; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + + .form-inline .radio input[type="radio"], + .form-inline .checkbox input[type="checkbox"] { + float: none; + margin-left: 0; + } + + .form-inline .has-feedback .form-control-feedback { + top: 0; + } } + .form-horizontal .control-label, .form-horizontal .radio, .form-horizontal .checkbox, .form-horizontal .radio-inline, .form-horizontal .checkbox-inline { - padding-top: 7px; - margin-top: 0; - margin-bottom: 0; + padding-top: 7px; + margin-top: 0; + margin-bottom: 0; } + .form-horizontal .radio, .form-horizontal .checkbox { - min-height: 27px; + min-height: 27px; } + .form-horizontal .form-group { - margin-right: -15px; - margin-left: -15px; + margin-right: -15px; + margin-left: -15px; } + .form-horizontal .form-control-static { - padding-top: 7px; + padding-top: 7px; } + @media (min-width: 768px) { - .form-horizontal .control-label { - text-align: right; - } + .form-horizontal .control-label { + text-align: right; + } } + .form-horizontal .has-feedback .form-control-feedback { - top: 0; - right: 15px; + top: 0; + right: 15px; } + .btn { - display: inline-block; - padding: 6px 12px; - margin-bottom: 0; - font-size: 14px; - font-weight: normal; - line-height: 1.42857143; - text-align: center; - white-space: nowrap; - vertical-align: middle; - cursor: pointer; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - background-image: none; - border: 1px solid transparent; - border-radius: 4px; + display: inline-block; + padding: 6px 12px; + margin-bottom: 0; + font-size: 14px; + font-weight: normal; + line-height: 1.42857143; + text-align: center; + white-space: nowrap; + vertical-align: middle; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; } + .btn:focus, .btn:active:focus, .btn.active:focus { - outline: thin dotted; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; + outline: thin dotted; + outline: 5px auto -webkit-focus-ring-color; + outline-offset: -2px; } + .btn:hover, .btn:focus { - color: #333; - text-decoration: none; + color: #333; + text-decoration: none; } + .btn:active, .btn.active { - background-image: none; - outline: 0; - -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); - box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + background-image: none; + outline: 0; + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); } + .btn.disabled, .btn[disabled], fieldset[disabled] .btn { - pointer-events: none; - cursor: not-allowed; - filter: alpha(opacity=65); - -webkit-box-shadow: none; - box-shadow: none; - opacity: .65; + pointer-events: none; + cursor: not-allowed; + filter: alpha(opacity=65); + -webkit-box-shadow: none; + box-shadow: none; + opacity: .65; } + .btn-default { - color: #333; - background-color: #fff; - border-color: #ccc; + color: #333; + background-color: #fff; + border-color: #ccc; } + .btn-default:hover, .btn-default:focus, .btn-default:active, .btn-default.active, .open .dropdown-toggle.btn-default { - color: #333; - background-color: #ebebeb; - border-color: #adadad; + color: #333; + background-color: #ebebeb; + border-color: #adadad; } + .btn-default:active, .btn-default.active, .open .dropdown-toggle.btn-default { - background-image: none; + background-image: none; } + .btn-default.disabled, .btn-default[disabled], fieldset[disabled] .btn-default, @@ -2072,32 +2539,37 @@ fieldset[disabled] .btn-default:active, .btn-default.disabled.active, .btn-default[disabled].active, fieldset[disabled] .btn-default.active { - background-color: #fff; - border-color: #ccc; + background-color: #fff; + border-color: #ccc; } + .btn-default .badge { - color: #fff; - background-color: #333; + color: #fff; + background-color: #333; } + .btn-primary { - color: #fff; - background-color: #428bca; - border-color: #357ebd; + color: #fff; + background-color: #428bca; + border-color: #357ebd; } + .btn-primary:hover, .btn-primary:focus, .btn-primary:active, .btn-primary.active, .open .dropdown-toggle.btn-primary { - color: #fff; - background-color: #3276b1; - border-color: #285e8e; + color: #fff; + background-color: #3276b1; + border-color: #285e8e; } + .btn-primary:active, .btn-primary.active, .open .dropdown-toggle.btn-primary { - background-image: none; + background-image: none; } + .btn-primary.disabled, .btn-primary[disabled], fieldset[disabled] .btn-primary, @@ -2113,32 +2585,37 @@ fieldset[disabled] .btn-primary:active, .btn-primary.disabled.active, .btn-primary[disabled].active, fieldset[disabled] .btn-primary.active { - background-color: #428bca; - border-color: #357ebd; + background-color: #428bca; + border-color: #357ebd; } + .btn-primary .badge { - color: #428bca; - background-color: #fff; + color: #428bca; + background-color: #fff; } + .btn-success { - color: #fff; - background-color: #5cb85c; - border-color: #4cae4c; + color: #fff; + background-color: #5cb85c; + border-color: #4cae4c; } + .btn-success:hover, .btn-success:focus, .btn-success:active, .btn-success.active, .open .dropdown-toggle.btn-success { - color: #fff; - background-color: #47a447; - border-color: #398439; + color: #fff; + background-color: #47a447; + border-color: #398439; } + .btn-success:active, .btn-success.active, .open .dropdown-toggle.btn-success { - background-image: none; + background-image: none; } + .btn-success.disabled, .btn-success[disabled], fieldset[disabled] .btn-success, @@ -2154,32 +2631,37 @@ fieldset[disabled] .btn-success:active, .btn-success.disabled.active, .btn-success[disabled].active, fieldset[disabled] .btn-success.active { - background-color: #5cb85c; - border-color: #4cae4c; + background-color: #5cb85c; + border-color: #4cae4c; } + .btn-success .badge { - color: #5cb85c; - background-color: #fff; + color: #5cb85c; + background-color: #fff; } + .btn-info { - color: #fff; - background-color: #5bc0de; - border-color: #46b8da; + color: #fff; + background-color: #5bc0de; + border-color: #46b8da; } + .btn-info:hover, .btn-info:focus, .btn-info:active, .btn-info.active, .open .dropdown-toggle.btn-info { - color: #fff; - background-color: #39b3d7; - border-color: #269abc; + color: #fff; + background-color: #39b3d7; + border-color: #269abc; } + .btn-info:active, .btn-info.active, .open .dropdown-toggle.btn-info { - background-image: none; + background-image: none; } + .btn-info.disabled, .btn-info[disabled], fieldset[disabled] .btn-info, @@ -2195,32 +2677,37 @@ fieldset[disabled] .btn-info:active, .btn-info.disabled.active, .btn-info[disabled].active, fieldset[disabled] .btn-info.active { - background-color: #5bc0de; - border-color: #46b8da; + background-color: #5bc0de; + border-color: #46b8da; } + .btn-info .badge { - color: #5bc0de; - background-color: #fff; + color: #5bc0de; + background-color: #fff; } + .btn-warning { - color: #fff; - background-color: #f0ad4e; - border-color: #eea236; + color: #fff; + background-color: #f0ad4e; + border-color: #eea236; } + .btn-warning:hover, .btn-warning:focus, .btn-warning:active, .btn-warning.active, .open .dropdown-toggle.btn-warning { - color: #fff; - background-color: #ed9c28; - border-color: #d58512; + color: #fff; + background-color: #ed9c28; + border-color: #d58512; } + .btn-warning:active, .btn-warning.active, .open .dropdown-toggle.btn-warning { - background-image: none; + background-image: none; } + .btn-warning.disabled, .btn-warning[disabled], fieldset[disabled] .btn-warning, @@ -2236,32 +2723,37 @@ fieldset[disabled] .btn-warning:active, .btn-warning.disabled.active, .btn-warning[disabled].active, fieldset[disabled] .btn-warning.active { - background-color: #f0ad4e; - border-color: #eea236; + background-color: #f0ad4e; + border-color: #eea236; } + .btn-warning .badge { - color: #f0ad4e; - background-color: #fff; + color: #f0ad4e; + background-color: #fff; } + .btn-danger { - color: #fff; - background-color: #d9534f; - border-color: #d43f3a; + color: #fff; + background-color: #d9534f; + border-color: #d43f3a; } + .btn-danger:hover, .btn-danger:focus, .btn-danger:active, .btn-danger.active, .open .dropdown-toggle.btn-danger { - color: #fff; - background-color: #d2322d; - border-color: #ac2925; + color: #fff; + background-color: #d2322d; + border-color: #ac2925; } + .btn-danger:active, .btn-danger.active, .open .dropdown-toggle.btn-danger { - background-image: none; + background-image: none; } + .btn-danger.disabled, .btn-danger[disabled], fieldset[disabled] .btn-danger, @@ -2277,868 +2769,1112 @@ fieldset[disabled] .btn-danger:active, .btn-danger.disabled.active, .btn-danger[disabled].active, fieldset[disabled] .btn-danger.active { - background-color: #d9534f; - border-color: #d43f3a; + background-color: #d9534f; + border-color: #d43f3a; } + .btn-danger .badge { - color: #d9534f; - background-color: #fff; + color: #d9534f; + background-color: #fff; } + .btn-link { - font-weight: normal; - color: #428bca; - cursor: pointer; - border-radius: 0; + font-weight: normal; + color: #428bca; + cursor: pointer; + border-radius: 0; } + .btn-link, .btn-link:active, .btn-link[disabled], fieldset[disabled] .btn-link { - background-color: transparent; - -webkit-box-shadow: none; - box-shadow: none; + background-color: transparent; + -webkit-box-shadow: none; + box-shadow: none; } + .btn-link, .btn-link:hover, .btn-link:focus, .btn-link:active { - border-color: transparent; + border-color: transparent; } + .btn-link:hover, .btn-link:focus { - color: #2a6496; - text-decoration: underline; - background-color: transparent; + color: #2a6496; + text-decoration: underline; + background-color: transparent; } + .btn-link[disabled]:hover, fieldset[disabled] .btn-link:hover, .btn-link[disabled]:focus, fieldset[disabled] .btn-link:focus { - color: #999; - text-decoration: none; + color: #999; + text-decoration: none; } + .btn-lg, .btn-group-lg > .btn { - padding: 10px 16px; - font-size: 18px; - line-height: 1.33; - border-radius: 6px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; } + .btn-sm, .btn-group-sm > .btn { - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; } + .btn-xs, .btn-group-xs > .btn { - padding: 1px 5px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; + padding: 1px 5px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; } + .btn-block { - display: block; - width: 100%; - padding-right: 0; - padding-left: 0; + display: block; + width: 100%; + padding-right: 0; + padding-left: 0; } + .btn-block + .btn-block { - margin-top: 5px; + margin-top: 5px; } + input[type="submit"].btn-block, input[type="reset"].btn-block, input[type="button"].btn-block { - width: 100%; + width: 100%; } + .fade { - opacity: 0; - -webkit-transition: opacity .15s linear; - transition: opacity .15s linear; + opacity: 0; + -webkit-transition: opacity .15s linear; + transition: opacity .15s linear; } + .fade.in { - opacity: 1; + opacity: 1; } + .collapse { - display: none; + display: none; } + .collapse.in { - display: block; + display: block; } + .collapsing { - position: relative; - height: 0; - overflow: hidden; - -webkit-transition: height .35s ease; - transition: height .35s ease; + position: relative; + height: 0; + overflow: hidden; + -webkit-transition: height .35s ease; + transition: height .35s ease; } + @font-face { - font-family: 'Glyphicons Halflings'; + font-family: 'Glyphicons Halflings'; - src: url('../fonts/glyphicons-halflings-regular.eot'); - 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'); + src: url('../fonts/glyphicons-halflings-regular.eot'); + 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'); } + .glyphicon { - position: relative; - top: 1px; - display: inline-block; - font-family: 'Glyphicons Halflings'; - font-style: normal; - font-weight: normal; - line-height: 1; + position: relative; + top: 1px; + display: inline-block; + font-family: 'Glyphicons Halflings'; + font-style: normal; + font-weight: normal; + line-height: 1; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; } + .glyphicon-asterisk:before { - content: "\2a"; + content: "\2a"; } + .glyphicon-plus:before { - content: "\2b"; + content: "\2b"; } + .glyphicon-euro:before { - content: "\20ac"; + content: "\20ac"; } + .glyphicon-minus:before { - content: "\2212"; + content: "\2212"; } + .glyphicon-cloud:before { - content: "\2601"; + content: "\2601"; } + .glyphicon-envelope:before { - content: "\2709"; + content: "\2709"; } + .glyphicon-pencil:before { - content: "\270f"; + content: "\270f"; } + .glyphicon-glass:before { - content: "\e001"; + content: "\e001"; } + .glyphicon-music:before { - content: "\e002"; + content: "\e002"; } + .glyphicon-search:before { - content: "\e003"; + content: "\e003"; } + .glyphicon-heart:before { - content: "\e005"; + content: "\e005"; } + .glyphicon-star:before { - content: "\e006"; + content: "\e006"; } + .glyphicon-star-empty:before { - content: "\e007"; + content: "\e007"; } + .glyphicon-user:before { - content: "\e008"; + content: "\e008"; } + .glyphicon-film:before { - content: "\e009"; + content: "\e009"; } + .glyphicon-th-large:before { - content: "\e010"; + content: "\e010"; } + .glyphicon-th:before { - content: "\e011"; + content: "\e011"; } + .glyphicon-th-list:before { - content: "\e012"; + content: "\e012"; } + .glyphicon-ok:before { - content: "\e013"; + content: "\e013"; } + .glyphicon-remove:before { - content: "\e014"; + content: "\e014"; } + .glyphicon-zoom-in:before { - content: "\e015"; + content: "\e015"; } + .glyphicon-zoom-out:before { - content: "\e016"; + content: "\e016"; } + .glyphicon-off:before { - content: "\e017"; + content: "\e017"; } + .glyphicon-signal:before { - content: "\e018"; + content: "\e018"; } + .glyphicon-cog:before { - content: "\e019"; + content: "\e019"; } + .glyphicon-trash:before { - content: "\e020"; + content: "\e020"; } + .glyphicon-home:before { - content: "\e021"; + content: "\e021"; } + .glyphicon-file:before { - content: "\e022"; + content: "\e022"; } + .glyphicon-time:before { - content: "\e023"; + content: "\e023"; } + .glyphicon-road:before { - content: "\e024"; + content: "\e024"; } + .glyphicon-download-alt:before { - content: "\e025"; + content: "\e025"; } + .glyphicon-download:before { - content: "\e026"; + content: "\e026"; } + .glyphicon-upload:before { - content: "\e027"; + content: "\e027"; } + .glyphicon-inbox:before { - content: "\e028"; + content: "\e028"; } + .glyphicon-play-circle:before { - content: "\e029"; + content: "\e029"; } + .glyphicon-repeat:before { - content: "\e030"; + content: "\e030"; } + .glyphicon-refresh:before { - content: "\e031"; + content: "\e031"; } + .glyphicon-list-alt:before { - content: "\e032"; + content: "\e032"; } + .glyphicon-lock:before { - content: "\e033"; + content: "\e033"; } + .glyphicon-flag:before { - content: "\e034"; + content: "\e034"; } + .glyphicon-headphones:before { - content: "\e035"; + content: "\e035"; } + .glyphicon-volume-off:before { - content: "\e036"; + content: "\e036"; } + .glyphicon-volume-down:before { - content: "\e037"; + content: "\e037"; } + .glyphicon-volume-up:before { - content: "\e038"; + content: "\e038"; } + .glyphicon-qrcode:before { - content: "\e039"; + content: "\e039"; } + .glyphicon-barcode:before { - content: "\e040"; + content: "\e040"; } + .glyphicon-tag:before { - content: "\e041"; + content: "\e041"; } + .glyphicon-tags:before { - content: "\e042"; + content: "\e042"; } + .glyphicon-book:before { - content: "\e043"; + content: "\e043"; } + .glyphicon-bookmark:before { - content: "\e044"; + content: "\e044"; } + .glyphicon-print:before { - content: "\e045"; + content: "\e045"; } + .glyphicon-camera:before { - content: "\e046"; + content: "\e046"; } + .glyphicon-font:before { - content: "\e047"; + content: "\e047"; } + .glyphicon-bold:before { - content: "\e048"; + content: "\e048"; } + .glyphicon-italic:before { - content: "\e049"; + content: "\e049"; } + .glyphicon-text-height:before { - content: "\e050"; + content: "\e050"; } + .glyphicon-text-width:before { - content: "\e051"; + content: "\e051"; } + .glyphicon-align-left:before { - content: "\e052"; + content: "\e052"; } + .glyphicon-align-center:before { - content: "\e053"; + content: "\e053"; } + .glyphicon-align-right:before { - content: "\e054"; + content: "\e054"; } + .glyphicon-align-justify:before { - content: "\e055"; + content: "\e055"; } + .glyphicon-list:before { - content: "\e056"; + content: "\e056"; } + .glyphicon-indent-left:before { - content: "\e057"; + content: "\e057"; } + .glyphicon-indent-right:before { - content: "\e058"; + content: "\e058"; } + .glyphicon-facetime-video:before { - content: "\e059"; + content: "\e059"; } + .glyphicon-picture:before { - content: "\e060"; + content: "\e060"; } + .glyphicon-map-marker:before { - content: "\e062"; + content: "\e062"; } + .glyphicon-adjust:before { - content: "\e063"; + content: "\e063"; } + .glyphicon-tint:before { - content: "\e064"; + content: "\e064"; } + .glyphicon-edit:before { - content: "\e065"; + content: "\e065"; } + .glyphicon-share:before { - content: "\e066"; + content: "\e066"; } + .glyphicon-check:before { - content: "\e067"; + content: "\e067"; } + .glyphicon-move:before { - content: "\e068"; + content: "\e068"; } + .glyphicon-step-backward:before { - content: "\e069"; + content: "\e069"; } + .glyphicon-fast-backward:before { - content: "\e070"; + content: "\e070"; } + .glyphicon-backward:before { - content: "\e071"; + content: "\e071"; } + .glyphicon-play:before { - content: "\e072"; + content: "\e072"; } + .glyphicon-pause:before { - content: "\e073"; + content: "\e073"; } + .glyphicon-stop:before { - content: "\e074"; + content: "\e074"; } + .glyphicon-forward:before { - content: "\e075"; + content: "\e075"; } + .glyphicon-fast-forward:before { - content: "\e076"; + content: "\e076"; } + .glyphicon-step-forward:before { - content: "\e077"; + content: "\e077"; } + .glyphicon-eject:before { - content: "\e078"; + content: "\e078"; } + .glyphicon-chevron-left:before { - content: "\e079"; + content: "\e079"; } + .glyphicon-chevron-right:before { - content: "\e080"; + content: "\e080"; } + .glyphicon-plus-sign:before { - content: "\e081"; + content: "\e081"; } + .glyphicon-minus-sign:before { - content: "\e082"; + content: "\e082"; } + .glyphicon-remove-sign:before { - content: "\e083"; + content: "\e083"; } + .glyphicon-ok-sign:before { - content: "\e084"; + content: "\e084"; } + .glyphicon-question-sign:before { - content: "\e085"; + content: "\e085"; } + .glyphicon-info-sign:before { - content: "\e086"; + content: "\e086"; } + .glyphicon-screenshot:before { - content: "\e087"; + content: "\e087"; } + .glyphicon-remove-circle:before { - content: "\e088"; + content: "\e088"; } + .glyphicon-ok-circle:before { - content: "\e089"; + content: "\e089"; } + .glyphicon-ban-circle:before { - content: "\e090"; + content: "\e090"; } + .glyphicon-arrow-left:before { - content: "\e091"; + content: "\e091"; } + .glyphicon-arrow-right:before { - content: "\e092"; + content: "\e092"; } + .glyphicon-arrow-up:before { - content: "\e093"; + content: "\e093"; } + .glyphicon-arrow-down:before { - content: "\e094"; + content: "\e094"; } + .glyphicon-share-alt:before { - content: "\e095"; + content: "\e095"; } + .glyphicon-resize-full:before { - content: "\e096"; + content: "\e096"; } + .glyphicon-resize-small:before { - content: "\e097"; + content: "\e097"; } + .glyphicon-exclamation-sign:before { - content: "\e101"; + content: "\e101"; } + .glyphicon-gift:before { - content: "\e102"; + content: "\e102"; } + .glyphicon-leaf:before { - content: "\e103"; + content: "\e103"; } + .glyphicon-fire:before { - content: "\e104"; + content: "\e104"; } + .glyphicon-eye-open:before { - content: "\e105"; + content: "\e105"; } + .glyphicon-eye-close:before { - content: "\e106"; + content: "\e106"; } + .glyphicon-warning-sign:before { - content: "\e107"; + content: "\e107"; } + .glyphicon-plane:before { - content: "\e108"; + content: "\e108"; } + .glyphicon-calendar:before { - content: "\e109"; + content: "\e109"; } + .glyphicon-random:before { - content: "\e110"; + content: "\e110"; } + .glyphicon-comment:before { - content: "\e111"; + content: "\e111"; } + .glyphicon-magnet:before { - content: "\e112"; + content: "\e112"; } + .glyphicon-chevron-up:before { - content: "\e113"; + content: "\e113"; } + .glyphicon-chevron-down:before { - content: "\e114"; + content: "\e114"; } + .glyphicon-retweet:before { - content: "\e115"; + content: "\e115"; } + .glyphicon-shopping-cart:before { - content: "\e116"; + content: "\e116"; } + .glyphicon-folder-close:before { - content: "\e117"; + content: "\e117"; } + .glyphicon-folder-open:before { - content: "\e118"; + content: "\e118"; } + .glyphicon-resize-vertical:before { - content: "\e119"; + content: "\e119"; } + .glyphicon-resize-horizontal:before { - content: "\e120"; + content: "\e120"; } + .glyphicon-hdd:before { - content: "\e121"; + content: "\e121"; } + .glyphicon-bullhorn:before { - content: "\e122"; + content: "\e122"; } + .glyphicon-bell:before { - content: "\e123"; + content: "\e123"; } + .glyphicon-certificate:before { - content: "\e124"; + content: "\e124"; } + .glyphicon-thumbs-up:before { - content: "\e125"; + content: "\e125"; } + .glyphicon-thumbs-down:before { - content: "\e126"; + content: "\e126"; } + .glyphicon-hand-right:before { - content: "\e127"; + content: "\e127"; } + .glyphicon-hand-left:before { - content: "\e128"; + content: "\e128"; } + .glyphicon-hand-up:before { - content: "\e129"; + content: "\e129"; } + .glyphicon-hand-down:before { - content: "\e130"; + content: "\e130"; } + .glyphicon-circle-arrow-right:before { - content: "\e131"; + content: "\e131"; } + .glyphicon-circle-arrow-left:before { - content: "\e132"; + content: "\e132"; } + .glyphicon-circle-arrow-up:before { - content: "\e133"; + content: "\e133"; } + .glyphicon-circle-arrow-down:before { - content: "\e134"; + content: "\e134"; } + .glyphicon-globe:before { - content: "\e135"; + content: "\e135"; } + .glyphicon-wrench:before { - content: "\e136"; + content: "\e136"; } + .glyphicon-tasks:before { - content: "\e137"; + content: "\e137"; } + .glyphicon-filter:before { - content: "\e138"; + content: "\e138"; } + .glyphicon-briefcase:before { - content: "\e139"; + content: "\e139"; } + .glyphicon-fullscreen:before { - content: "\e140"; + content: "\e140"; } + .glyphicon-dashboard:before { - content: "\e141"; + content: "\e141"; } + .glyphicon-paperclip:before { - content: "\e142"; + content: "\e142"; } + .glyphicon-heart-empty:before { - content: "\e143"; + content: "\e143"; } + .glyphicon-link:before { - content: "\e144"; + content: "\e144"; } + .glyphicon-phone:before { - content: "\e145"; + content: "\e145"; } + .glyphicon-pushpin:before { - content: "\e146"; + content: "\e146"; } + .glyphicon-usd:before { - content: "\e148"; + content: "\e148"; } + .glyphicon-gbp:before { - content: "\e149"; + content: "\e149"; } + .glyphicon-sort:before { - content: "\e150"; + content: "\e150"; } + .glyphicon-sort-by-alphabet:before { - content: "\e151"; + content: "\e151"; } + .glyphicon-sort-by-alphabet-alt:before { - content: "\e152"; + content: "\e152"; } + .glyphicon-sort-by-order:before { - content: "\e153"; + content: "\e153"; } + .glyphicon-sort-by-order-alt:before { - content: "\e154"; + content: "\e154"; } + .glyphicon-sort-by-attributes:before { - content: "\e155"; + content: "\e155"; } + .glyphicon-sort-by-attributes-alt:before { - content: "\e156"; + content: "\e156"; } + .glyphicon-unchecked:before { - content: "\e157"; + content: "\e157"; } + .glyphicon-expand:before { - content: "\e158"; + content: "\e158"; } + .glyphicon-collapse-down:before { - content: "\e159"; + content: "\e159"; } + .glyphicon-collapse-up:before { - content: "\e160"; + content: "\e160"; } + .glyphicon-log-in:before { - content: "\e161"; + content: "\e161"; } + .glyphicon-flash:before { - content: "\e162"; + content: "\e162"; } + .glyphicon-log-out:before { - content: "\e163"; + content: "\e163"; } + .glyphicon-new-window:before { - content: "\e164"; + content: "\e164"; } + .glyphicon-record:before { - content: "\e165"; + content: "\e165"; } + .glyphicon-save:before { - content: "\e166"; + content: "\e166"; } + .glyphicon-open:before { - content: "\e167"; + content: "\e167"; } + .glyphicon-saved:before { - content: "\e168"; + content: "\e168"; } + .glyphicon-import:before { - content: "\e169"; + content: "\e169"; } + .glyphicon-export:before { - content: "\e170"; + content: "\e170"; } + .glyphicon-send:before { - content: "\e171"; + content: "\e171"; } + .glyphicon-floppy-disk:before { - content: "\e172"; + content: "\e172"; } + .glyphicon-floppy-saved:before { - content: "\e173"; + content: "\e173"; } + .glyphicon-floppy-remove:before { - content: "\e174"; + content: "\e174"; } + .glyphicon-floppy-save:before { - content: "\e175"; + content: "\e175"; } + .glyphicon-floppy-open:before { - content: "\e176"; + content: "\e176"; } + .glyphicon-credit-card:before { - content: "\e177"; + content: "\e177"; } + .glyphicon-transfer:before { - content: "\e178"; + content: "\e178"; } + .glyphicon-cutlery:before { - content: "\e179"; + content: "\e179"; } + .glyphicon-header:before { - content: "\e180"; + content: "\e180"; } + .glyphicon-compressed:before { - content: "\e181"; + content: "\e181"; } + .glyphicon-earphone:before { - content: "\e182"; + content: "\e182"; } + .glyphicon-phone-alt:before { - content: "\e183"; + content: "\e183"; } + .glyphicon-tower:before { - content: "\e184"; + content: "\e184"; } + .glyphicon-stats:before { - content: "\e185"; + content: "\e185"; } + .glyphicon-sd-video:before { - content: "\e186"; + content: "\e186"; } + .glyphicon-hd-video:before { - content: "\e187"; + content: "\e187"; } + .glyphicon-subtitles:before { - content: "\e188"; + content: "\e188"; } + .glyphicon-sound-stereo:before { - content: "\e189"; + content: "\e189"; } + .glyphicon-sound-dolby:before { - content: "\e190"; + content: "\e190"; } + .glyphicon-sound-5-1:before { - content: "\e191"; + content: "\e191"; } + .glyphicon-sound-6-1:before { - content: "\e192"; + content: "\e192"; } + .glyphicon-sound-7-1:before { - content: "\e193"; + content: "\e193"; } + .glyphicon-copyright-mark:before { - content: "\e194"; + content: "\e194"; } + .glyphicon-registration-mark:before { - content: "\e195"; + content: "\e195"; } + .glyphicon-cloud-download:before { - content: "\e197"; + content: "\e197"; } + .glyphicon-cloud-upload:before { - content: "\e198"; + content: "\e198"; } + .glyphicon-tree-conifer:before { - content: "\e199"; + content: "\e199"; } + .glyphicon-tree-deciduous:before { - content: "\e200"; + content: "\e200"; } + .caret { - display: inline-block; - width: 0; - height: 0; - margin-left: 2px; - vertical-align: middle; - border-top: 4px solid; - border-right: 4px solid transparent; - border-left: 4px solid transparent; + display: inline-block; + width: 0; + height: 0; + margin-left: 2px; + vertical-align: middle; + border-top: 4px solid; + border-right: 4px solid transparent; + border-left: 4px solid transparent; } + .dropdown { - position: relative; + position: relative; } + .dropdown-toggle:focus { - outline: 0; + outline: 0; } + .dropdown-menu { - position: absolute; - top: 100%; - left: 0; - z-index: 1000; - display: none; - float: left; - min-width: 160px; - padding: 5px 0; - margin: 2px 0 0; - font-size: 14px; - list-style: none; - background-color: #fff; - background-clip: padding-box; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, .15); - border-radius: 4px; - -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175); - box-shadow: 0 6px 12px rgba(0, 0, 0, .175); + position: absolute; + top: 100%; + left: 0; + z-index: 1000; + display: none; + float: left; + min-width: 160px; + padding: 5px 0; + margin: 2px 0 0; + font-size: 14px; + list-style: none; + background-color: #fff; + background-clip: padding-box; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, .15); + border-radius: 4px; + -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175); + box-shadow: 0 6px 12px rgba(0, 0, 0, .175); } + .dropdown-menu.pull-right { - right: 0; - left: auto; + right: 0; + left: auto; } + .dropdown-menu .divider { - height: 1px; - margin: 9px 0; - overflow: hidden; - background-color: #e5e5e5; + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; } + .dropdown-menu > li > a { - display: block; - padding: 3px 20px; - clear: both; - font-weight: normal; - line-height: 1.42857143; - color: #333; - white-space: nowrap; + display: block; + padding: 3px 20px; + clear: both; + font-weight: normal; + line-height: 1.42857143; + color: #333; + white-space: nowrap; } + .dropdown-menu > li > a:hover, .dropdown-menu > li > a:focus { - color: #262626; - text-decoration: none; - background-color: #f5f5f5; + color: #262626; + text-decoration: none; + background-color: #f5f5f5; } + .dropdown-menu > .active > a, .dropdown-menu > .active > a:hover, .dropdown-menu > .active > a:focus { - color: #fff; - text-decoration: none; - background-color: #428bca; - outline: 0; + color: #fff; + text-decoration: none; + background-color: #428bca; + outline: 0; } + .dropdown-menu > .disabled > a, .dropdown-menu > .disabled > a:hover, .dropdown-menu > .disabled > a:focus { - color: #999; + color: #999; } + .dropdown-menu > .disabled > a:hover, .dropdown-menu > .disabled > a:focus { - text-decoration: none; - cursor: not-allowed; - background-color: transparent; - background-image: none; - filter: progid:DXImageTransform.Microsoft.gradient(enabled = false); + text-decoration: none; + cursor: not-allowed; + background-color: transparent; + background-image: none; + filter: progid:DXImageTransform.Microsoft.gradient(enabled=false); } + .open > .dropdown-menu { - display: block; + display: block; } + .open > a { - outline: 0; + outline: 0; } + .dropdown-menu-right { - right: 0; - left: auto; + right: 0; + left: auto; } + .dropdown-menu-left { - right: auto; - left: 0; + right: auto; + left: 0; } + .dropdown-header { - display: block; - padding: 3px 20px; - font-size: 12px; - line-height: 1.42857143; - color: #999; + display: block; + padding: 3px 20px; + font-size: 12px; + line-height: 1.42857143; + color: #999; } + .dropdown-backdrop { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 990; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 990; } + .pull-right > .dropdown-menu { - right: 0; - left: auto; + right: 0; + left: auto; } + .dropup .caret, .navbar-fixed-bottom .dropdown .caret { - content: ""; - border-top: 0; - border-bottom: 4px solid; + content: ""; + border-top: 0; + border-bottom: 4px solid; } + .dropup .dropdown-menu, .navbar-fixed-bottom .dropdown .dropdown-menu { - top: auto; - bottom: 100%; - margin-bottom: 1px; + top: auto; + bottom: 100%; + margin-bottom: 1px; } + @media (min-width: 768px) { - .navbar-right .dropdown-menu { - right: 0; - left: auto; - } - .navbar-right .dropdown-menu-left { - right: auto; - left: 0; - } + .navbar-right .dropdown-menu { + right: 0; + left: auto; + } + + .navbar-right .dropdown-menu-left { + right: auto; + left: 0; + } } + .btn-group, .btn-group-vertical { - position: relative; - display: inline-block; - vertical-align: middle; + position: relative; + display: inline-block; + vertical-align: middle; } + .btn-group > .btn, .btn-group-vertical > .btn { - position: relative; - float: left; + position: relative; + float: left; } + .btn-group > .btn:hover, .btn-group-vertical > .btn:hover, .btn-group > .btn:focus, @@ -3147,256 +3883,307 @@ input[type="button"].btn-block { .btn-group-vertical > .btn:active, .btn-group > .btn.active, .btn-group-vertical > .btn.active { - z-index: 2; + z-index: 2; } + .btn-group > .btn:focus, .btn-group-vertical > .btn:focus { - outline: none; + outline: none; } + .btn-group .btn + .btn, .btn-group .btn + .btn-group, .btn-group .btn-group + .btn, .btn-group .btn-group + .btn-group { - margin-left: -1px; + margin-left: -1px; } + .btn-toolbar { - margin-left: -5px; + margin-left: -5px; } + .btn-toolbar .btn-group, .btn-toolbar .input-group { - float: left; + float: left; } + .btn-toolbar > .btn, .btn-toolbar > .btn-group, .btn-toolbar > .input-group { - margin-left: 5px; + margin-left: 5px; } + .btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) { - border-radius: 0; + border-radius: 0; } + .btn-group > .btn:first-child { - margin-left: 0; + margin-left: 0; } + .btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) { - border-top-right-radius: 0; - border-bottom-right-radius: 0; + border-top-right-radius: 0; + border-bottom-right-radius: 0; } + .btn-group > .btn:last-child:not(:first-child), .btn-group > .dropdown-toggle:not(:first-child) { - border-top-left-radius: 0; - border-bottom-left-radius: 0; + border-top-left-radius: 0; + border-bottom-left-radius: 0; } + .btn-group > .btn-group { - float: left; + float: left; } + .btn-group > .btn-group:not(:first-child):not(:last-child) > .btn { - border-radius: 0; + border-radius: 0; } + .btn-group > .btn-group:first-child > .btn:last-child, .btn-group > .btn-group:first-child > .dropdown-toggle { - border-top-right-radius: 0; - border-bottom-right-radius: 0; + border-top-right-radius: 0; + border-bottom-right-radius: 0; } + .btn-group > .btn-group:last-child > .btn:first-child { - border-top-left-radius: 0; - border-bottom-left-radius: 0; + border-top-left-radius: 0; + border-bottom-left-radius: 0; } + .btn-group .dropdown-toggle:active, .btn-group.open .dropdown-toggle { - outline: 0; + outline: 0; } + .btn-group > .btn + .dropdown-toggle { - padding-right: 8px; - padding-left: 8px; + padding-right: 8px; + padding-left: 8px; } + .btn-group > .btn-lg + .dropdown-toggle { - padding-right: 12px; - padding-left: 12px; + padding-right: 12px; + padding-left: 12px; } + .btn-group.open .dropdown-toggle { - -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); - box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); } + .btn-group.open .dropdown-toggle.btn-link { - -webkit-box-shadow: none; - box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; } + .btn .caret { - margin-left: 0; + margin-left: 0; } + .btn-lg .caret { - border-width: 5px 5px 0; - border-bottom-width: 0; + border-width: 5px 5px 0; + border-bottom-width: 0; } + .dropup .btn-lg .caret { - border-width: 0 5px 5px; + border-width: 0 5px 5px; } + .btn-group-vertical > .btn, .btn-group-vertical > .btn-group, .btn-group-vertical > .btn-group > .btn { - display: block; - float: none; - width: 100%; - max-width: 100%; + display: block; + float: none; + width: 100%; + max-width: 100%; } + .btn-group-vertical > .btn-group > .btn { - float: none; + float: none; } + .btn-group-vertical > .btn + .btn, .btn-group-vertical > .btn + .btn-group, .btn-group-vertical > .btn-group + .btn, .btn-group-vertical > .btn-group + .btn-group { - margin-top: -1px; - margin-left: 0; + margin-top: -1px; + margin-left: 0; } + .btn-group-vertical > .btn:not(:first-child):not(:last-child) { - border-radius: 0; + border-radius: 0; } + .btn-group-vertical > .btn:first-child:not(:last-child) { - border-top-right-radius: 4px; - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; + border-top-right-radius: 4px; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; } + .btn-group-vertical > .btn:last-child:not(:first-child) { - border-top-left-radius: 0; - border-top-right-radius: 0; - border-bottom-left-radius: 4px; + border-top-left-radius: 0; + border-top-right-radius: 0; + border-bottom-left-radius: 4px; } + .btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn { - border-radius: 0; + border-radius: 0; } + .btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child, .btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle { - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; } + .btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child { - border-top-left-radius: 0; - border-top-right-radius: 0; + border-top-left-radius: 0; + border-top-right-radius: 0; } + .btn-group-justified { - display: table; - width: 100%; - table-layout: fixed; - border-collapse: separate; + display: table; + width: 100%; + table-layout: fixed; + border-collapse: separate; } + .btn-group-justified > .btn, .btn-group-justified > .btn-group { - display: table-cell; - float: none; - width: 1%; + display: table-cell; + float: none; + width: 1%; } + .btn-group-justified > .btn-group .btn { - width: 100%; + width: 100%; } + [data-toggle="buttons"] > .btn > input[type="radio"], [data-toggle="buttons"] > .btn > input[type="checkbox"] { - display: none; + display: none; } + .input-group { - position: relative; - display: table; - border-collapse: separate; + position: relative; + display: table; + border-collapse: separate; } + .input-group[class*="col-"] { - float: none; - padding-right: 0; - padding-left: 0; + float: none; + padding-right: 0; + padding-left: 0; } + .input-group .form-control { - position: relative; - z-index: 2; - float: left; - width: 100%; - margin-bottom: 0; + position: relative; + z-index: 2; + float: left; + width: 100%; + margin-bottom: 0; } + .input-group-lg > .form-control, .input-group-lg > .input-group-addon, .input-group-lg > .input-group-btn > .btn { - height: 46px; - padding: 10px 16px; - font-size: 18px; - line-height: 1.33; - border-radius: 6px; + height: 46px; + padding: 10px 16px; + font-size: 18px; + line-height: 1.33; + border-radius: 6px; } + select.input-group-lg > .form-control, select.input-group-lg > .input-group-addon, select.input-group-lg > .input-group-btn > .btn { - height: 46px; - line-height: 46px; + height: 46px; + line-height: 46px; } + textarea.input-group-lg > .form-control, textarea.input-group-lg > .input-group-addon, textarea.input-group-lg > .input-group-btn > .btn, select[multiple].input-group-lg > .form-control, select[multiple].input-group-lg > .input-group-addon, select[multiple].input-group-lg > .input-group-btn > .btn { - height: auto; + height: auto; } + .input-group-sm > .form-control, .input-group-sm > .input-group-addon, .input-group-sm > .input-group-btn > .btn { - height: 30px; - padding: 5px 10px; - font-size: 12px; - line-height: 1.5; - border-radius: 3px; + height: 30px; + padding: 5px 10px; + font-size: 12px; + line-height: 1.5; + border-radius: 3px; } + select.input-group-sm > .form-control, select.input-group-sm > .input-group-addon, select.input-group-sm > .input-group-btn > .btn { - height: 30px; - line-height: 30px; + height: 30px; + line-height: 30px; } + textarea.input-group-sm > .form-control, textarea.input-group-sm > .input-group-addon, textarea.input-group-sm > .input-group-btn > .btn, select[multiple].input-group-sm > .form-control, select[multiple].input-group-sm > .input-group-addon, select[multiple].input-group-sm > .input-group-btn > .btn { - height: auto; + height: auto; } + .input-group-addon, .input-group-btn, .input-group .form-control { - display: table-cell; + display: table-cell; } + .input-group-addon:not(:first-child):not(:last-child), .input-group-btn:not(:first-child):not(:last-child), .input-group .form-control:not(:first-child):not(:last-child) { - border-radius: 0; + border-radius: 0; } + .input-group-addon, .input-group-btn { - width: 1%; - white-space: nowrap; - vertical-align: middle; + width: 1%; + white-space: nowrap; + vertical-align: middle; } + .input-group-addon { - padding: 6px 12px; - font-size: 14px; - font-weight: normal; - line-height: 1; - color: #555; - text-align: center; - background-color: #eee; - border: 1px solid #ccc; - border-radius: 4px; + padding: 6px 12px; + font-size: 14px; + font-weight: normal; + line-height: 1; + color: #555; + text-align: center; + background-color: #eee; + border: 1px solid #ccc; + border-radius: 4px; } + .input-group-addon.input-sm { - padding: 5px 10px; - font-size: 12px; - border-radius: 3px; + padding: 5px 10px; + font-size: 12px; + border-radius: 3px; } + .input-group-addon.input-lg { - padding: 10px 16px; - font-size: 18px; - border-radius: 6px; + padding: 10px 16px; + font-size: 18px; + border-radius: 6px; } + .input-group-addon input[type="radio"], .input-group-addon input[type="checkbox"] { - margin-top: 0; + margin-top: 0; } + .input-group .form-control:first-child, .input-group-addon:first-child, .input-group-btn:first-child > .btn, @@ -3404,12 +4191,14 @@ select[multiple].input-group-sm > .input-group-btn > .btn { .input-group-btn:first-child > .dropdown-toggle, .input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle), .input-group-btn:last-child > .btn-group:not(:last-child) > .btn { - border-top-right-radius: 0; - border-bottom-right-radius: 0; + border-top-right-radius: 0; + border-bottom-right-radius: 0; } + .input-group-addon:first-child { - border-right: 0; + border-right: 0; } + .input-group .form-control:last-child, .input-group-addon:last-child, .input-group-btn:last-child > .btn, @@ -3417,1407 +4206,1704 @@ select[multiple].input-group-sm > .input-group-btn > .btn { .input-group-btn:last-child > .dropdown-toggle, .input-group-btn:first-child > .btn:not(:first-child), .input-group-btn:first-child > .btn-group:not(:first-child) > .btn { - border-top-left-radius: 0; - border-bottom-left-radius: 0; + border-top-left-radius: 0; + border-bottom-left-radius: 0; } + .input-group-addon:last-child { - border-left: 0; + border-left: 0; } + .input-group-btn { - position: relative; - font-size: 0; - white-space: nowrap; + position: relative; + font-size: 0; + white-space: nowrap; } + .input-group-btn > .btn { - position: relative; + position: relative; } + .input-group-btn > .btn + .btn { - margin-left: -1px; + margin-left: -1px; } + .input-group-btn > .btn:hover, .input-group-btn > .btn:focus, .input-group-btn > .btn:active { - z-index: 2; + z-index: 2; } + .input-group-btn:first-child > .btn, .input-group-btn:first-child > .btn-group { - margin-right: -1px; + margin-right: -1px; } + .input-group-btn:last-child > .btn, .input-group-btn:last-child > .btn-group { - margin-left: -1px; + margin-left: -1px; } + .nav { - padding-left: 0; - margin-bottom: 0; - list-style: none; + padding-left: 0; + margin-bottom: 0; + list-style: none; } + .nav > li { - position: relative; - display: block; + position: relative; + display: block; } + .nav > li > a { - position: relative; - display: block; - padding: 10px 15px; + position: relative; + display: block; + padding: 10px 15px; } + .nav > li > a:hover, .nav > li > a:focus { - text-decoration: none; - background-color: #eee; + text-decoration: none; + background-color: #eee; } + .nav > li.disabled > a { - color: #999; + color: #999; } + .nav > li.disabled > a:hover, .nav > li.disabled > a:focus { - color: #999; - text-decoration: none; - cursor: not-allowed; - background-color: transparent; + color: #999; + text-decoration: none; + cursor: not-allowed; + background-color: transparent; } + .nav .open > a, .nav .open > a:hover, .nav .open > a:focus { - background-color: #eee; - border-color: #428bca; + background-color: #eee; + border-color: #428bca; } + .nav .nav-divider { - height: 1px; - margin: 9px 0; - overflow: hidden; - background-color: #e5e5e5; + height: 1px; + margin: 9px 0; + overflow: hidden; + background-color: #e5e5e5; } + .nav > li > a > img { - max-width: none; + max-width: none; } + .nav-tabs { - border-bottom: 1px solid #ddd; + border-bottom: 1px solid #ddd; } + .nav-tabs > li { - float: left; - margin-bottom: -1px; + float: left; + margin-bottom: -1px; } + .nav-tabs > li > a { - margin-right: 2px; - line-height: 1.42857143; - border: 1px solid transparent; - border-radius: 4px 4px 0 0; + margin-right: 2px; + line-height: 1.42857143; + border: 1px solid transparent; + border-radius: 4px 4px 0 0; } + .nav-tabs > li > a:hover { - border-color: #eee #eee #ddd; + border-color: #eee #eee #ddd; } + .nav-tabs > li.active > a, .nav-tabs > li.active > a:hover, .nav-tabs > li.active > a:focus { - color: #555; - cursor: default; - background-color: #fff; - border: 1px solid #ddd; - border-bottom-color: transparent; + color: #555; + cursor: default; + background-color: #fff; + border: 1px solid #ddd; + border-bottom-color: transparent; } + .nav-tabs.nav-justified { - width: 100%; - border-bottom: 0; + width: 100%; + border-bottom: 0; } + .nav-tabs.nav-justified > li { - float: none; + float: none; } + .nav-tabs.nav-justified > li > a { - margin-bottom: 5px; - text-align: center; + margin-bottom: 5px; + text-align: center; } + .nav-tabs.nav-justified > .dropdown .dropdown-menu { - top: auto; - left: auto; + top: auto; + left: auto; } + @media (min-width: 768px) { - .nav-tabs.nav-justified > li { - display: table-cell; - width: 1%; - } - .nav-tabs.nav-justified > li > a { - margin-bottom: 0; - } + .nav-tabs.nav-justified > li { + display: table-cell; + width: 1%; + } + + .nav-tabs.nav-justified > li > a { + margin-bottom: 0; + } } + .nav-tabs.nav-justified > li > a { - margin-right: 0; - border-radius: 4px; + margin-right: 0; + border-radius: 4px; } + .nav-tabs.nav-justified > .active > a, .nav-tabs.nav-justified > .active > a:hover, .nav-tabs.nav-justified > .active > a:focus { - border: 1px solid #ddd; + border: 1px solid #ddd; } + @media (min-width: 768px) { - .nav-tabs.nav-justified > li > a { - border-bottom: 1px solid #ddd; - border-radius: 4px 4px 0 0; - } - .nav-tabs.nav-justified > .active > a, - .nav-tabs.nav-justified > .active > a:hover, - .nav-tabs.nav-justified > .active > a:focus { - border-bottom-color: #fff; - } + .nav-tabs.nav-justified > li > a { + border-bottom: 1px solid #ddd; + border-radius: 4px 4px 0 0; + } + + .nav-tabs.nav-justified > .active > a, + .nav-tabs.nav-justified > .active > a:hover, + .nav-tabs.nav-justified > .active > a:focus { + border-bottom-color: #fff; + } } + .nav-pills > li { - float: left; + float: left; } + .nav-pills > li > a { - border-radius: 4px; + border-radius: 4px; } + .nav-pills > li + li { - margin-left: 2px; + margin-left: 2px; } + .nav-pills > li.active > a, .nav-pills > li.active > a:hover, .nav-pills > li.active > a:focus { - color: #fff; - background-color: #428bca; + color: #fff; + background-color: #428bca; } + .nav-stacked > li { - float: none; + float: none; } + .nav-stacked > li + li { - margin-top: 2px; - margin-left: 0; + margin-top: 2px; + margin-left: 0; } + .nav-justified { - width: 100%; + width: 100%; } + .nav-justified > li { - float: none; + float: none; } + .nav-justified > li > a { - margin-bottom: 5px; - text-align: center; + margin-bottom: 5px; + text-align: center; } + .nav-justified > .dropdown .dropdown-menu { - top: auto; - left: auto; + top: auto; + left: auto; } + @media (min-width: 768px) { - .nav-justified > li { - display: table-cell; - width: 1%; - } - .nav-justified > li > a { - margin-bottom: 0; - } + .nav-justified > li { + display: table-cell; + width: 1%; + } + + .nav-justified > li > a { + margin-bottom: 0; + } } + .nav-tabs-justified { - border-bottom: 0; + border-bottom: 0; } + .nav-tabs-justified > li > a { - margin-right: 0; - border-radius: 4px; + margin-right: 0; + border-radius: 4px; } + .nav-tabs-justified > .active > a, .nav-tabs-justified > .active > a:hover, .nav-tabs-justified > .active > a:focus { - border: 1px solid #ddd; + border: 1px solid #ddd; } + @media (min-width: 768px) { - .nav-tabs-justified > li > a { - border-bottom: 1px solid #ddd; - border-radius: 4px 4px 0 0; - } - .nav-tabs-justified > .active > a, - .nav-tabs-justified > .active > a:hover, - .nav-tabs-justified > .active > a:focus { - border-bottom-color: #fff; - } + .nav-tabs-justified > li > a { + border-bottom: 1px solid #ddd; + border-radius: 4px 4px 0 0; + } + + .nav-tabs-justified > .active > a, + .nav-tabs-justified > .active > a:hover, + .nav-tabs-justified > .active > a:focus { + border-bottom-color: #fff; + } } + .tab-content > .tab-pane { - display: none; + display: none; } + .tab-content > .active { - display: block; + display: block; } + .nav-tabs .dropdown-menu { - margin-top: -1px; - border-top-left-radius: 0; - border-top-right-radius: 0; + margin-top: -1px; + border-top-left-radius: 0; + border-top-right-radius: 0; } + .navbar { - position: relative; - min-height: 50px; - margin-bottom: 20px; - border: 1px solid transparent; + position: relative; + min-height: 50px; + margin-bottom: 20px; + border: 1px solid transparent; } + @media (min-width: 768px) { - .navbar { - border-radius: 4px; - } + .navbar { + border-radius: 4px; + } } + @media (min-width: 768px) { - .navbar-header { - float: left; - } + .navbar-header { + float: left; + } } + .navbar-collapse { - max-height: 340px; - padding-right: 15px; - padding-left: 15px; - overflow-x: visible; - -webkit-overflow-scrolling: touch; - border-top: 1px solid transparent; - box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); + max-height: 340px; + padding-right: 15px; + padding-left: 15px; + overflow-x: visible; + -webkit-overflow-scrolling: touch; + border-top: 1px solid transparent; + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1); } + .navbar-collapse.in { - overflow-y: auto; + overflow-y: auto; } + @media (min-width: 768px) { - .navbar-collapse { - width: auto; - border-top: 0; - box-shadow: none; - } - .navbar-collapse.collapse { - display: block !important; - height: auto !important; - padding-bottom: 0; - overflow: visible !important; - } - .navbar-collapse.in { - overflow-y: visible; - } - .navbar-fixed-top .navbar-collapse, - .navbar-static-top .navbar-collapse, - .navbar-fixed-bottom .navbar-collapse { - padding-right: 0; - padding-left: 0; - } + .navbar-collapse { + width: auto; + border-top: 0; + box-shadow: none; + } + + .navbar-collapse.collapse { + display: block !important; + height: auto !important; + padding-bottom: 0; + overflow: visible !important; + } + + .navbar-collapse.in { + overflow-y: visible; + } + + .navbar-fixed-top .navbar-collapse, + .navbar-static-top .navbar-collapse, + .navbar-fixed-bottom .navbar-collapse { + padding-right: 0; + padding-left: 0; + } } + .container > .navbar-header, .container-fluid > .navbar-header, .container > .navbar-collapse, .container-fluid > .navbar-collapse { - margin-right: -15px; - margin-left: -15px; + margin-right: -15px; + margin-left: -15px; } + @media (min-width: 768px) { - .container > .navbar-header, - .container-fluid > .navbar-header, - .container > .navbar-collapse, - .container-fluid > .navbar-collapse { - margin-right: 0; - margin-left: 0; - } + .container > .navbar-header, + .container-fluid > .navbar-header, + .container > .navbar-collapse, + .container-fluid > .navbar-collapse { + margin-right: 0; + margin-left: 0; + } } + .navbar-static-top { - z-index: 1000; - border-width: 0 0 1px; + z-index: 1000; + border-width: 0 0 1px; } + @media (min-width: 768px) { - .navbar-static-top { - border-radius: 0; - } + .navbar-static-top { + border-radius: 0; + } } + .navbar-fixed-top, .navbar-fixed-bottom { - position: fixed; - right: 0; - left: 0; - z-index: 1030; + position: fixed; + right: 0; + left: 0; + z-index: 1030; } + @media (min-width: 768px) { - .navbar-fixed-top, - .navbar-fixed-bottom { - border-radius: 0; - } + .navbar-fixed-top, + .navbar-fixed-bottom { + border-radius: 0; + } } + .navbar-fixed-top { - top: 0; - border-width: 0 0 1px; + top: 0; + border-width: 0 0 1px; } + .navbar-fixed-bottom { - bottom: 0; - margin-bottom: 0; - border-width: 1px 0 0; + bottom: 0; + margin-bottom: 0; + border-width: 1px 0 0; } + .navbar-brand { - float: left; - height: 50px; - padding: 15px 15px; - font-size: 18px; - line-height: 20px; + float: left; + height: 50px; + padding: 15px 15px; + font-size: 18px; + line-height: 20px; } + .navbar-brand:hover, .navbar-brand:focus { - text-decoration: none; + text-decoration: none; } + @media (min-width: 768px) { - .navbar > .container .navbar-brand, - .navbar > .container-fluid .navbar-brand { - margin-left: -15px; - } + .navbar > .container .navbar-brand, + .navbar > .container-fluid .navbar-brand { + margin-left: -15px; + } } + .navbar-toggle { - position: relative; - float: right; - padding: 9px 10px; - margin-top: 8px; - margin-right: 15px; - margin-bottom: 8px; - background-color: transparent; - background-image: none; - border: 1px solid transparent; - border-radius: 4px; + position: relative; + float: right; + padding: 9px 10px; + margin-top: 8px; + margin-right: 15px; + margin-bottom: 8px; + background-color: transparent; + background-image: none; + border: 1px solid transparent; + border-radius: 4px; } + .navbar-toggle:focus { - outline: none; + outline: none; } + .navbar-toggle .icon-bar { - display: block; - width: 22px; - height: 2px; - border-radius: 1px; + display: block; + width: 22px; + height: 2px; + border-radius: 1px; } + .navbar-toggle .icon-bar + .icon-bar { - margin-top: 4px; + margin-top: 4px; } + @media (min-width: 768px) { - .navbar-toggle { - display: none; - } + .navbar-toggle { + display: none; + } } + .navbar-nav { - margin: 7.5px -15px; + margin: 7.5px -15px; } + .navbar-nav > li > a { - padding-top: 10px; - padding-bottom: 10px; - line-height: 20px; + padding-top: 10px; + padding-bottom: 10px; + line-height: 20px; } + @media (max-width: 767px) { - .navbar-nav .open .dropdown-menu { - position: static; - float: none; - width: auto; - margin-top: 0; - background-color: transparent; - border: 0; - box-shadow: none; - } - .navbar-nav .open .dropdown-menu > li > a, - .navbar-nav .open .dropdown-menu .dropdown-header { - padding: 5px 15px 5px 25px; - } - .navbar-nav .open .dropdown-menu > li > a { - line-height: 20px; - } - .navbar-nav .open .dropdown-menu > li > a:hover, - .navbar-nav .open .dropdown-menu > li > a:focus { - background-image: none; - } + .navbar-nav .open .dropdown-menu { + position: static; + float: none; + width: auto; + margin-top: 0; + background-color: transparent; + border: 0; + box-shadow: none; + } + + .navbar-nav .open .dropdown-menu > li > a, + .navbar-nav .open .dropdown-menu .dropdown-header { + padding: 5px 15px 5px 25px; + } + + .navbar-nav .open .dropdown-menu > li > a { + line-height: 20px; + } + + .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-nav .open .dropdown-menu > li > a:focus { + background-image: none; + } } + @media (min-width: 768px) { - .navbar-nav { - float: left; - margin: 0; - } - .navbar-nav > li { - float: left; - } - .navbar-nav > li > a { - padding-top: 15px; - padding-bottom: 15px; - } - .navbar-nav.navbar-right:last-child { - margin-right: -15px; - } + .navbar-nav { + float: left; + margin: 0; + } + + .navbar-nav > li { + float: left; + } + + .navbar-nav > li > a { + padding-top: 15px; + padding-bottom: 15px; + } + + .navbar-nav.navbar-right:last-child { + margin-right: -15px; + } } + @media (min-width: 768px) { - .navbar-left { - float: left !important; - } - .navbar-right { - float: right !important; - } + .navbar-left { + float: left !important; + } + + .navbar-right { + float: right !important; + } } + .navbar-form { - padding: 10px 15px; - margin-top: 8px; - margin-right: -15px; - margin-bottom: 8px; - margin-left: -15px; - border-top: 1px solid transparent; - border-bottom: 1px solid transparent; - -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); + padding: 10px 15px; + margin-top: 8px; + margin-right: -15px; + margin-bottom: 8px; + margin-left: -15px; + border-top: 1px solid transparent; + border-bottom: 1px solid transparent; + -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); + box-shadow: inset 0 1px 0 rgba(255, 255, 255, .1), 0 1px 0 rgba(255, 255, 255, .1); } + @media (min-width: 768px) { - .navbar-form .form-group { - display: inline-block; - margin-bottom: 0; - vertical-align: middle; - } - .navbar-form .form-control { - display: inline-block; - width: auto; - vertical-align: middle; - } - .navbar-form .input-group > .form-control { - width: 100%; - } - .navbar-form .control-label { - margin-bottom: 0; - vertical-align: middle; - } - .navbar-form .radio, - .navbar-form .checkbox { - display: inline-block; - padding-left: 0; - margin-top: 0; - margin-bottom: 0; - vertical-align: middle; - } - .navbar-form .radio input[type="radio"], - .navbar-form .checkbox input[type="checkbox"] { - float: none; - margin-left: 0; - } - .navbar-form .has-feedback .form-control-feedback { - top: 0; - } + .navbar-form .form-group { + display: inline-block; + margin-bottom: 0; + vertical-align: middle; + } + + .navbar-form .form-control { + display: inline-block; + width: auto; + vertical-align: middle; + } + + .navbar-form .input-group > .form-control { + width: 100%; + } + + .navbar-form .control-label { + margin-bottom: 0; + vertical-align: middle; + } + + .navbar-form .radio, + .navbar-form .checkbox { + display: inline-block; + padding-left: 0; + margin-top: 0; + margin-bottom: 0; + vertical-align: middle; + } + + .navbar-form .radio input[type="radio"], + .navbar-form .checkbox input[type="checkbox"] { + float: none; + margin-left: 0; + } + + .navbar-form .has-feedback .form-control-feedback { + top: 0; + } } + @media (max-width: 767px) { - .navbar-form .form-group { - margin-bottom: 5px; - } + .navbar-form .form-group { + margin-bottom: 5px; + } } + @media (min-width: 768px) { - .navbar-form { - width: auto; - padding-top: 0; - padding-bottom: 0; - margin-right: 0; - margin-left: 0; - border: 0; - -webkit-box-shadow: none; - box-shadow: none; - } - .navbar-form.navbar-right:last-child { - margin-right: -15px; - } + .navbar-form { + width: auto; + padding-top: 0; + padding-bottom: 0; + margin-right: 0; + margin-left: 0; + border: 0; + -webkit-box-shadow: none; + box-shadow: none; + } + + .navbar-form.navbar-right:last-child { + margin-right: -15px; + } } + .navbar-nav > li > .dropdown-menu { - margin-top: 0; - border-top-left-radius: 0; - border-top-right-radius: 0; + margin-top: 0; + border-top-left-radius: 0; + border-top-right-radius: 0; } + .navbar-fixed-bottom .navbar-nav > li > .dropdown-menu { - border-bottom-right-radius: 0; - border-bottom-left-radius: 0; + border-bottom-right-radius: 0; + border-bottom-left-radius: 0; } + .navbar-btn { - margin-top: 8px; - margin-bottom: 8px; + margin-top: 8px; + margin-bottom: 8px; } + .navbar-btn.btn-sm { - margin-top: 10px; - margin-bottom: 10px; + margin-top: 10px; + margin-bottom: 10px; } + .navbar-btn.btn-xs { - margin-top: 14px; - margin-bottom: 14px; + margin-top: 14px; + margin-bottom: 14px; } + .navbar-text { - margin-top: 15px; - margin-bottom: 15px; + margin-top: 15px; + margin-bottom: 15px; } + @media (min-width: 768px) { - .navbar-text { - float: left; - margin-right: 15px; - margin-left: 15px; - } - .navbar-text.navbar-right:last-child { - margin-right: 0; - } + .navbar-text { + float: left; + margin-right: 15px; + margin-left: 15px; + } + + .navbar-text.navbar-right:last-child { + margin-right: 0; + } } + .navbar-default { - background-color: #f8f8f8; - border-color: #e7e7e7; + background-color: #f8f8f8; + border-color: #e7e7e7; } + .navbar-default .navbar-brand { - color: #777; + color: #777; } + .navbar-default .navbar-brand:hover, .navbar-default .navbar-brand:focus { - color: #5e5e5e; - background-color: transparent; + color: #5e5e5e; + background-color: transparent; } + .navbar-default .navbar-text { - color: #777; + color: #777; } + .navbar-default .navbar-nav > li > a { - color: #777; + color: #777; } + .navbar-default .navbar-nav > li > a:hover, .navbar-default .navbar-nav > li > a:focus { - color: #333; - background-color: transparent; + color: #333; + background-color: transparent; } + .navbar-default .navbar-nav > .active > a, .navbar-default .navbar-nav > .active > a:hover, .navbar-default .navbar-nav > .active > a:focus { - color: #555; - background-color: #e7e7e7; + color: #555; + background-color: #e7e7e7; } + .navbar-default .navbar-nav > .disabled > a, .navbar-default .navbar-nav > .disabled > a:hover, .navbar-default .navbar-nav > .disabled > a:focus { - color: #ccc; - background-color: transparent; + color: #ccc; + background-color: transparent; } + .navbar-default .navbar-toggle { - border-color: #ddd; + border-color: #ddd; } + .navbar-default .navbar-toggle:hover, .navbar-default .navbar-toggle:focus { - background-color: #ddd; + background-color: #ddd; } + .navbar-default .navbar-toggle .icon-bar { - background-color: #888; + background-color: #888; } + .navbar-default .navbar-collapse, .navbar-default .navbar-form { - border-color: #e7e7e7; + border-color: #e7e7e7; } + .navbar-default .navbar-nav > .open > a, .navbar-default .navbar-nav > .open > a:hover, .navbar-default .navbar-nav > .open > a:focus { - color: #555; - background-color: #e7e7e7; -} -@media (max-width: 767px) { - .navbar-default .navbar-nav .open .dropdown-menu > li > a { - color: #777; - } - .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, - .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { - color: #333; - background-color: transparent; - } - .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 { color: #555; background-color: #e7e7e7; - } - .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 { - color: #ccc; - background-color: transparent; - } } + +@media (max-width: 767px) { + .navbar-default .navbar-nav .open .dropdown-menu > li > a { + color: #777; + } + + .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { + color: #333; + background-color: transparent; + } + + .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 { + color: #555; + background-color: #e7e7e7; + } + + .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 { + color: #ccc; + background-color: transparent; + } +} + .navbar-default .navbar-link { - color: #777; + color: #777; } + .navbar-default .navbar-link:hover { - color: #333; + color: #333; } + .navbar-inverse { - background-color: #222; - border-color: #080808; + background-color: #222; + border-color: #080808; } + .navbar-inverse .navbar-brand { - color: #999; + color: #999; } + .navbar-inverse .navbar-brand:hover, .navbar-inverse .navbar-brand:focus { - color: #fff; - background-color: transparent; + color: #fff; + background-color: transparent; } + .navbar-inverse .navbar-text { - color: #999; + color: #999; } + .navbar-inverse .navbar-nav > li > a { - color: #999; + color: #999; } + .navbar-inverse .navbar-nav > li > a:hover, .navbar-inverse .navbar-nav > li > a:focus { - color: #fff; - background-color: transparent; + color: #fff; + background-color: transparent; } + .navbar-inverse .navbar-nav > .active > a, .navbar-inverse .navbar-nav > .active > a:hover, .navbar-inverse .navbar-nav > .active > a:focus { - color: #fff; - background-color: #080808; + color: #fff; + background-color: #080808; } + .navbar-inverse .navbar-nav > .disabled > a, .navbar-inverse .navbar-nav > .disabled > a:hover, .navbar-inverse .navbar-nav > .disabled > a:focus { - color: #444; - background-color: transparent; + color: #444; + background-color: transparent; } + .navbar-inverse .navbar-toggle { - border-color: #333; + border-color: #333; } + .navbar-inverse .navbar-toggle:hover, .navbar-inverse .navbar-toggle:focus { - background-color: #333; + background-color: #333; } + .navbar-inverse .navbar-toggle .icon-bar { - background-color: #fff; + background-color: #fff; } + .navbar-inverse .navbar-collapse, .navbar-inverse .navbar-form { - border-color: #101010; -} -.navbar-inverse .navbar-nav > .open > a, -.navbar-inverse .navbar-nav > .open > a:hover, -.navbar-inverse .navbar-nav > .open > a:focus { - color: #fff; - background-color: #080808; -} -@media (max-width: 767px) { - .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { - border-color: #080808; - } - .navbar-inverse .navbar-nav .open .dropdown-menu .divider { - background-color: #080808; - } - .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { - color: #999; - } - .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, - .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { - color: #fff; - background-color: transparent; - } - .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 { + border-color: #101010; +} + +.navbar-inverse .navbar-nav > .open > a, +.navbar-inverse .navbar-nav > .open > a:hover, +.navbar-inverse .navbar-nav > .open > a:focus { color: #fff; background-color: #080808; - } - .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 { - color: #444; - background-color: transparent; - } } + +@media (max-width: 767px) { + .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header { + border-color: #080808; + } + + .navbar-inverse .navbar-nav .open .dropdown-menu .divider { + background-color: #080808; + } + + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a { + color: #999; + } + + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover, + .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus { + color: #fff; + background-color: transparent; + } + + .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 { + color: #fff; + background-color: #080808; + } + + .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 { + color: #444; + background-color: transparent; + } +} + .navbar-inverse .navbar-link { - color: #999; + color: #999; } + .navbar-inverse .navbar-link:hover { - color: #fff; + color: #fff; } + .breadcrumb { - padding: 8px 15px; - margin-bottom: 20px; - list-style: none; - background-color: #f5f5f5; - border-radius: 4px; + padding: 8px 15px; + margin-bottom: 20px; + list-style: none; + background-color: #f5f5f5; + border-radius: 4px; } + .breadcrumb > li { - display: inline-block; + display: inline-block; } + .breadcrumb > li + li:before { - padding: 0 5px; - color: #ccc; - content: "/\00a0"; + padding: 0 5px; + color: #ccc; + content: "/\00a0"; } + .breadcrumb > .active { - color: #999; + color: #999; } + .pagination { - display: inline-block; - padding-left: 0; - margin: 20px 0; - border-radius: 4px; + display: inline-block; + padding-left: 0; + margin: 20px 0; + border-radius: 4px; } + .pagination > li { - display: inline; + display: inline; } + .pagination > li > a, .pagination > li > span { - position: relative; - float: left; - padding: 6px 12px; - margin-left: -1px; - line-height: 1.42857143; - color: #428bca; - text-decoration: none; - background-color: #fff; - border: 1px solid #ddd; + position: relative; + float: left; + padding: 6px 12px; + margin-left: -1px; + line-height: 1.42857143; + color: #428bca; + text-decoration: none; + background-color: #fff; + border: 1px solid #ddd; } + .pagination > li:first-child > a, .pagination > li:first-child > span { - margin-left: 0; - border-top-left-radius: 4px; - border-bottom-left-radius: 4px; + margin-left: 0; + border-top-left-radius: 4px; + border-bottom-left-radius: 4px; } + .pagination > li:last-child > a, .pagination > li:last-child > span { - border-top-right-radius: 4px; - border-bottom-right-radius: 4px; + border-top-right-radius: 4px; + border-bottom-right-radius: 4px; } + .pagination > li > a:hover, .pagination > li > span:hover, .pagination > li > a:focus, .pagination > li > span:focus { - color: #2a6496; - background-color: #eee; - border-color: #ddd; + color: #2a6496; + background-color: #eee; + border-color: #ddd; } + .pagination > .active > a, .pagination > .active > span, .pagination > .active > a:hover, .pagination > .active > span:hover, .pagination > .active > a:focus, .pagination > .active > span:focus { - z-index: 2; - color: #fff; - cursor: default; - background-color: #428bca; - border-color: #428bca; + z-index: 2; + color: #fff; + cursor: default; + background-color: #428bca; + border-color: #428bca; } + .pagination > .disabled > span, .pagination > .disabled > span:hover, .pagination > .disabled > span:focus, .pagination > .disabled > a, .pagination > .disabled > a:hover, .pagination > .disabled > a:focus { - color: #999; - cursor: not-allowed; - background-color: #fff; - border-color: #ddd; + color: #999; + cursor: not-allowed; + background-color: #fff; + border-color: #ddd; } + .pagination-lg > li > a, .pagination-lg > li > span { - padding: 10px 16px; - font-size: 18px; + padding: 10px 16px; + font-size: 18px; } + .pagination-lg > li:first-child > a, .pagination-lg > li:first-child > span { - border-top-left-radius: 6px; - border-bottom-left-radius: 6px; + border-top-left-radius: 6px; + border-bottom-left-radius: 6px; } + .pagination-lg > li:last-child > a, .pagination-lg > li:last-child > span { - border-top-right-radius: 6px; - border-bottom-right-radius: 6px; + border-top-right-radius: 6px; + border-bottom-right-radius: 6px; } + .pagination-sm > li > a, .pagination-sm > li > span { - padding: 5px 10px; - font-size: 12px; + padding: 5px 10px; + font-size: 12px; } + .pagination-sm > li:first-child > a, .pagination-sm > li:first-child > span { - border-top-left-radius: 3px; - border-bottom-left-radius: 3px; + border-top-left-radius: 3px; + border-bottom-left-radius: 3px; } + .pagination-sm > li:last-child > a, .pagination-sm > li:last-child > span { - border-top-right-radius: 3px; - border-bottom-right-radius: 3px; + border-top-right-radius: 3px; + border-bottom-right-radius: 3px; } + .pager { - padding-left: 0; - margin: 20px 0; - text-align: center; - list-style: none; + padding-left: 0; + margin: 20px 0; + text-align: center; + list-style: none; } + .pager li { - display: inline; + display: inline; } + .pager li > a, .pager li > span { - display: inline-block; - padding: 5px 14px; - background-color: #fff; - border: 1px solid #ddd; - border-radius: 15px; + display: inline-block; + padding: 5px 14px; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 15px; } + .pager li > a:hover, .pager li > a:focus { - text-decoration: none; - background-color: #eee; + text-decoration: none; + background-color: #eee; } + .pager .next > a, .pager .next > span { - float: right; + float: right; } + .pager .previous > a, .pager .previous > span { - float: left; + float: left; } + .pager .disabled > a, .pager .disabled > a:hover, .pager .disabled > a:focus, .pager .disabled > span { - color: #999; - cursor: not-allowed; - background-color: #fff; + color: #999; + cursor: not-allowed; + background-color: #fff; } + .label { - display: inline; - padding: .2em .6em .3em; - font-size: 75%; - font-weight: bold; - line-height: 1; - color: #fff; - text-align: center; - white-space: nowrap; - vertical-align: baseline; - border-radius: .25em; + display: inline; + padding: .2em .6em .3em; + font-size: 75%; + font-weight: bold; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + border-radius: .25em; } + .label[href]:hover, .label[href]:focus { - color: #fff; - text-decoration: none; - cursor: pointer; + color: #fff; + text-decoration: none; + cursor: pointer; } + .label:empty { - display: none; + display: none; } + .btn .label { - position: relative; - top: -1px; + position: relative; + top: -1px; } + .label-default { - background-color: #999; + background-color: #999; } + .label-default[href]:hover, .label-default[href]:focus { - background-color: #808080; + background-color: #808080; } + .label-primary { - background-color: #428bca; + background-color: #428bca; } + .label-primary[href]:hover, .label-primary[href]:focus { - background-color: #3071a9; + background-color: #3071a9; } + .label-success { - background-color: #5cb85c; + background-color: #5cb85c; } + .label-success[href]:hover, .label-success[href]:focus { - background-color: #449d44; + background-color: #449d44; } + .label-info { - background-color: #5bc0de; + background-color: #5bc0de; } + .label-info[href]:hover, .label-info[href]:focus { - background-color: #31b0d5; + background-color: #31b0d5; } + .label-warning { - background-color: #f0ad4e; + background-color: #f0ad4e; } + .label-warning[href]:hover, .label-warning[href]:focus { - background-color: #ec971f; + background-color: #ec971f; } + .label-danger { - background-color: #d9534f; + background-color: #d9534f; } + .label-danger[href]:hover, .label-danger[href]:focus { - background-color: #c9302c; + background-color: #c9302c; } + .badge { - display: inline-block; - min-width: 10px; - padding: 3px 7px; - font-size: 12px; - font-weight: bold; - line-height: 1; - color: #fff; - text-align: center; - white-space: nowrap; - vertical-align: baseline; - background-color: #999; - border-radius: 10px; + display: inline-block; + min-width: 10px; + padding: 3px 7px; + font-size: 12px; + font-weight: bold; + line-height: 1; + color: #fff; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + background-color: #999; + border-radius: 10px; } + .badge:empty { - display: none; + display: none; } + .btn .badge { - position: relative; - top: -1px; + position: relative; + top: -1px; } + .btn-xs .badge { - top: 0; - padding: 1px 5px; + top: 0; + padding: 1px 5px; } + a.badge:hover, a.badge:focus { - color: #fff; - text-decoration: none; - cursor: pointer; + color: #fff; + text-decoration: none; + cursor: pointer; } + a.list-group-item.active > .badge, .nav-pills > .active > a > .badge { - color: #428bca; - background-color: #fff; + color: #428bca; + background-color: #fff; } + .nav-pills > li > a > .badge { - margin-left: 3px; + margin-left: 3px; } + .jumbotron { - padding: 30px; - margin-bottom: 30px; - color: inherit; - background-color: #eee; + padding: 30px; + margin-bottom: 30px; + color: inherit; + background-color: #eee; } + .jumbotron h1, .jumbotron .h1 { - color: inherit; + color: inherit; } + .jumbotron p { - margin-bottom: 15px; - font-size: 21px; - font-weight: 200; + margin-bottom: 15px; + font-size: 21px; + font-weight: 200; } + .container .jumbotron { - border-radius: 6px; + border-radius: 6px; } + .jumbotron .container { - max-width: 100%; + max-width: 100%; } + @media screen and (min-width: 768px) { - .jumbotron { - padding-top: 48px; - padding-bottom: 48px; - } - .container .jumbotron { - padding-right: 60px; - padding-left: 60px; - } - .jumbotron h1, - .jumbotron .h1 { - font-size: 63px; - } + .jumbotron { + padding-top: 48px; + padding-bottom: 48px; + } + + .container .jumbotron { + padding-right: 60px; + padding-left: 60px; + } + + .jumbotron h1, + .jumbotron .h1 { + font-size: 63px; + } } + .thumbnail { - display: block; - padding: 4px; - margin-bottom: 20px; - line-height: 1.42857143; - background-color: #fff; - border: 1px solid #ddd; - border-radius: 4px; - -webkit-transition: all .2s ease-in-out; - transition: all .2s ease-in-out; + display: block; + padding: 4px; + margin-bottom: 20px; + line-height: 1.42857143; + background-color: #fff; + border: 1px solid #ddd; + border-radius: 4px; + -webkit-transition: all .2s ease-in-out; + transition: all .2s ease-in-out; } + .thumbnail > img, .thumbnail a > img { - margin-right: auto; - margin-left: auto; + margin-right: auto; + margin-left: auto; } + a.thumbnail:hover, a.thumbnail:focus, a.thumbnail.active { - border-color: #428bca; + border-color: #428bca; } + .thumbnail .caption { - padding: 9px; - color: #333; + padding: 9px; + color: #333; } + .alert { - padding: 15px; - margin-bottom: 20px; - border: 1px solid transparent; - border-radius: 4px; + padding: 15px; + margin-bottom: 20px; + border: 1px solid transparent; + border-radius: 4px; } + .alert h4 { - margin-top: 0; - color: inherit; + margin-top: 0; + color: inherit; } + .alert .alert-link { - font-weight: bold; + font-weight: bold; } + .alert > p, .alert > ul { - margin-bottom: 0; + margin-bottom: 0; } + .alert > p + p { - margin-top: 5px; + margin-top: 5px; } + .alert-dismissable { - padding-right: 35px; + padding-right: 35px; } + .alert-dismissable .close { - position: relative; - top: -2px; - right: -21px; - color: inherit; + position: relative; + top: -2px; + right: -21px; + color: inherit; } + .alert-success { - color: #3c763d; - background-color: #dff0d8; - border-color: #d6e9c6; + color: #3c763d; + background-color: #dff0d8; + border-color: #d6e9c6; } + .alert-success hr { - border-top-color: #c9e2b3; + border-top-color: #c9e2b3; } + .alert-success .alert-link { - color: #2b542c; + color: #2b542c; } + .alert-info { - color: #31708f; - background-color: #d9edf7; - border-color: #bce8f1; + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1; } + .alert-info hr { - border-top-color: #a6e1ec; + border-top-color: #a6e1ec; } + .alert-info .alert-link { - color: #245269; + color: #245269; } + .alert-warning { - color: #8a6d3b; - background-color: #fcf8e3; - border-color: #faebcc; + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc; } + .alert-warning hr { - border-top-color: #f7e1b5; + border-top-color: #f7e1b5; } + .alert-warning .alert-link { - color: #66512c; + color: #66512c; } + .alert-danger { - color: #a94442; - background-color: #f2dede; - border-color: #ebccd1; + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; } + .alert-danger hr { - border-top-color: #e4b9c0; + border-top-color: #e4b9c0; } + .alert-danger .alert-link { - color: #843534; + color: #843534; } + @-webkit-keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } } + @keyframes progress-bar-stripes { - from { - background-position: 40px 0; - } - to { - background-position: 0 0; - } + from { + background-position: 40px 0; + } + to { + background-position: 0 0; + } } + .progress { - height: 20px; - margin-bottom: 20px; - overflow: hidden; - background-color: #f5f5f5; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); - box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); + height: 20px; + margin-bottom: 20px; + overflow: hidden; + background-color: #f5f5f5; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); + box-shadow: inset 0 1px 2px rgba(0, 0, 0, .1); } + .progress-bar { - float: left; - width: 0; - height: 100%; - font-size: 12px; - line-height: 20px; - color: #fff; - text-align: center; - background-color: #428bca; - -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); - box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); - -webkit-transition: width .6s ease; - transition: width .6s ease; + float: left; + width: 0; + height: 100%; + font-size: 12px; + line-height: 20px; + color: #fff; + text-align: center; + background-color: #428bca; + -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); + box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .15); + -webkit-transition: width .6s ease; + transition: width .6s ease; } + .progress-striped .progress-bar { - 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); - 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); - background-size: 40px 40px; + 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); + 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); + background-size: 40px 40px; } + .progress.active .progress-bar { - -webkit-animation: progress-bar-stripes 2s linear infinite; - animation: progress-bar-stripes 2s linear infinite; + -webkit-animation: progress-bar-stripes 2s linear infinite; + animation: progress-bar-stripes 2s linear infinite; } + .progress-bar-success { - background-color: #5cb85c; + background-color: #5cb85c; } + .progress-striped .progress-bar-success { - 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); - 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); + 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); + 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); } + .progress-bar-info { - background-color: #5bc0de; + background-color: #5bc0de; } + .progress-striped .progress-bar-info { - 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); - 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); + 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); + 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); } + .progress-bar-warning { - background-color: #f0ad4e; + background-color: #f0ad4e; } + .progress-striped .progress-bar-warning { - 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); - 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); + 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); + 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); } + .progress-bar-danger { - background-color: #d9534f; + background-color: #d9534f; } + .progress-striped .progress-bar-danger { - 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); - 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); + 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); + 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); } + .media, .media-body { - overflow: hidden; - zoom: 1; + overflow: hidden; + zoom: 1; } + .media, .media .media { - margin-top: 15px; + margin-top: 15px; } + .media:first-child { - margin-top: 0; + margin-top: 0; } + .media-object { - display: block; + display: block; } + .media-heading { - margin: 0 0 5px; + margin: 0 0 5px; } + .media > .pull-left { - margin-right: 10px; + margin-right: 10px; } + .media > .pull-right { - margin-left: 10px; + margin-left: 10px; } + .media-list { - padding-left: 0; - list-style: none; + padding-left: 0; + list-style: none; } + .list-group { - padding-left: 0; - margin-bottom: 20px; + padding-left: 0; + margin-bottom: 20px; } + .list-group-item { - position: relative; - display: block; - padding: 10px 15px; - margin-bottom: -1px; - background-color: #fff; - border: 1px solid #ddd; + position: relative; + display: block; + padding: 10px 15px; + margin-bottom: -1px; + background-color: #fff; + border: 1px solid #ddd; } + .list-group-item:first-child { - border-top-left-radius: 4px; - border-top-right-radius: 4px; + border-top-left-radius: 4px; + border-top-right-radius: 4px; } + .list-group-item:last-child { - margin-bottom: 0; - border-bottom-right-radius: 4px; - border-bottom-left-radius: 4px; + margin-bottom: 0; + border-bottom-right-radius: 4px; + border-bottom-left-radius: 4px; } + .list-group-item > .badge { - float: right; + float: right; } + .list-group-item > .badge + .badge { - margin-right: 5px; + margin-right: 5px; } + a.list-group-item { - color: #555; + color: #555; } + a.list-group-item .list-group-item-heading { - color: #333; + color: #333; } + a.list-group-item:hover, a.list-group-item:focus { - text-decoration: none; - background-color: #f5f5f5; + text-decoration: none; + background-color: #f5f5f5; } + a.list-group-item.active, a.list-group-item.active:hover, a.list-group-item.active:focus { - z-index: 2; - color: #fff; - background-color: #428bca; - border-color: #428bca; + z-index: 2; + color: #fff; + background-color: #428bca; + border-color: #428bca; } + a.list-group-item.active .list-group-item-heading, a.list-group-item.active:hover .list-group-item-heading, a.list-group-item.active:focus .list-group-item-heading { - color: inherit; + color: inherit; } + a.list-group-item.active .list-group-item-text, a.list-group-item.active:hover .list-group-item-text, a.list-group-item.active:focus .list-group-item-text { - color: #e1edf7; + color: #e1edf7; } + .list-group-item-success { - color: #3c763d; - background-color: #dff0d8; + color: #3c763d; + background-color: #dff0d8; } + a.list-group-item-success { - color: #3c763d; + color: #3c763d; } + a.list-group-item-success .list-group-item-heading { - color: inherit; + color: inherit; } + a.list-group-item-success:hover, a.list-group-item-success:focus { - color: #3c763d; - background-color: #d0e9c6; + color: #3c763d; + background-color: #d0e9c6; } + a.list-group-item-success.active, a.list-group-item-success.active:hover, a.list-group-item-success.active:focus { - color: #fff; - background-color: #3c763d; - border-color: #3c763d; + color: #fff; + background-color: #3c763d; + border-color: #3c763d; } + .list-group-item-info { - color: #31708f; - background-color: #d9edf7; + color: #31708f; + background-color: #d9edf7; } + a.list-group-item-info { - color: #31708f; + color: #31708f; } + a.list-group-item-info .list-group-item-heading { - color: inherit; + color: inherit; } + a.list-group-item-info:hover, a.list-group-item-info:focus { - color: #31708f; - background-color: #c4e3f3; + color: #31708f; + background-color: #c4e3f3; } + a.list-group-item-info.active, a.list-group-item-info.active:hover, a.list-group-item-info.active:focus { - color: #fff; - background-color: #31708f; - border-color: #31708f; + color: #fff; + background-color: #31708f; + border-color: #31708f; } + .list-group-item-warning { - color: #8a6d3b; - background-color: #fcf8e3; + color: #8a6d3b; + background-color: #fcf8e3; } + a.list-group-item-warning { - color: #8a6d3b; + color: #8a6d3b; } + a.list-group-item-warning .list-group-item-heading { - color: inherit; + color: inherit; } + a.list-group-item-warning:hover, a.list-group-item-warning:focus { - color: #8a6d3b; - background-color: #faf2cc; + color: #8a6d3b; + background-color: #faf2cc; } + a.list-group-item-warning.active, a.list-group-item-warning.active:hover, a.list-group-item-warning.active:focus { - color: #fff; - background-color: #8a6d3b; - border-color: #8a6d3b; + color: #fff; + background-color: #8a6d3b; + border-color: #8a6d3b; } + .list-group-item-danger { - color: #a94442; - background-color: #f2dede; + color: #a94442; + background-color: #f2dede; } + a.list-group-item-danger { - color: #a94442; + color: #a94442; } + a.list-group-item-danger .list-group-item-heading { - color: inherit; + color: inherit; } + a.list-group-item-danger:hover, a.list-group-item-danger:focus { - color: #a94442; - background-color: #ebcccc; + color: #a94442; + background-color: #ebcccc; } + a.list-group-item-danger.active, a.list-group-item-danger.active:hover, a.list-group-item-danger.active:focus { - color: #fff; - background-color: #a94442; - border-color: #a94442; + color: #fff; + background-color: #a94442; + border-color: #a94442; } + .list-group-item-heading { - margin-top: 0; - margin-bottom: 5px; + margin-top: 0; + margin-bottom: 5px; } + .list-group-item-text { - margin-bottom: 0; - line-height: 1.3; + margin-bottom: 0; + line-height: 1.3; } + .panel { - margin-bottom: 20px; - background-color: #fff; - border: 1px solid transparent; - border-radius: 4px; - -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05); - box-shadow: 0 1px 1px rgba(0, 0, 0, .05); + margin-bottom: 20px; + background-color: #fff; + border: 1px solid transparent; + border-radius: 4px; + -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, .05); + box-shadow: 0 1px 1px rgba(0, 0, 0, .05); } + .panel-body { - padding: 15px; + padding: 15px; } + .panel-heading { - padding: 10px 15px; - border-bottom: 1px solid transparent; - border-top-left-radius: 3px; - border-top-right-radius: 3px; + padding: 10px 15px; + border-bottom: 1px solid transparent; + border-top-left-radius: 3px; + border-top-right-radius: 3px; } + .panel-heading > .dropdown .dropdown-toggle { - color: inherit; + color: inherit; } + .panel-title { - margin-top: 0; - margin-bottom: 0; - font-size: 16px; - color: inherit; + margin-top: 0; + margin-bottom: 0; + font-size: 16px; + color: inherit; } + .panel-title > a { - color: inherit; + color: inherit; } + .panel-footer { - padding: 10px 15px; - background-color: #f5f5f5; - border-top: 1px solid #ddd; - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px; + padding: 10px 15px; + background-color: #f5f5f5; + border-top: 1px solid #ddd; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; } + .panel > .list-group { - margin-bottom: 0; + margin-bottom: 0; } + .panel > .list-group .list-group-item { - border-width: 1px 0; - border-radius: 0; + border-width: 1px 0; + border-radius: 0; } + .panel > .list-group:first-child .list-group-item:first-child { - border-top: 0; - border-top-left-radius: 3px; - border-top-right-radius: 3px; + border-top: 0; + border-top-left-radius: 3px; + border-top-right-radius: 3px; } + .panel > .list-group:last-child .list-group-item:last-child { - border-bottom: 0; - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px; + border-bottom: 0; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; } + .panel-heading + .list-group .list-group-item:first-child { - border-top-width: 0; + border-top-width: 0; } + .panel > .table, .panel > .table-responsive > .table { - margin-bottom: 0; + margin-bottom: 0; } + .panel > .table:first-child, .panel > .table-responsive:first-child > .table:first-child { - border-top-left-radius: 3px; - border-top-right-radius: 3px; + border-top-left-radius: 3px; + border-top-right-radius: 3px; } + .panel > .table:first-child > thead:first-child > tr:first-child td:first-child, .panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child, .panel > .table:first-child > tbody:first-child > tr:first-child td:first-child, @@ -4826,8 +5912,9 @@ a.list-group-item-danger.active:focus { .panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child, .panel > .table:first-child > tbody:first-child > tr:first-child th:first-child, .panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child { - border-top-left-radius: 3px; + border-top-left-radius: 3px; } + .panel > .table:first-child > thead:first-child > tr:first-child td:last-child, .panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child, .panel > .table:first-child > tbody:first-child > tr:first-child td:last-child, @@ -4836,13 +5923,15 @@ a.list-group-item-danger.active:focus { .panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child, .panel > .table:first-child > tbody:first-child > tr:first-child th:last-child, .panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child { - border-top-right-radius: 3px; + border-top-right-radius: 3px; } + .panel > .table:last-child, .panel > .table-responsive:last-child > .table:last-child { - border-bottom-right-radius: 3px; - border-bottom-left-radius: 3px; + border-bottom-right-radius: 3px; + border-bottom-left-radius: 3px; } + .panel > .table:last-child > tbody:last-child > tr:last-child td:first-child, .panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child, .panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child, @@ -4851,8 +5940,9 @@ a.list-group-item-danger.active:focus { .panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child, .panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child, .panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child { - border-bottom-left-radius: 3px; + border-bottom-left-radius: 3px; } + .panel > .table:last-child > tbody:last-child > tr:last-child td:last-child, .panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child, .panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child, @@ -4861,20 +5951,24 @@ a.list-group-item-danger.active:focus { .panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child, .panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child, .panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child { - border-bottom-right-radius: 3px; + border-bottom-right-radius: 3px; } + .panel > .panel-body + .table, .panel > .panel-body + .table-responsive { - border-top: 1px solid #ddd; + border-top: 1px solid #ddd; } + .panel > .table > tbody:first-child > tr:first-child th, .panel > .table > tbody:first-child > tr:first-child td { - border-top: 0; + border-top: 0; } + .panel > .table-bordered, .panel > .table-responsive > .table-bordered { - border: 0; + border: 0; } + .panel > .table-bordered > thead > tr > th:first-child, .panel > .table-responsive > .table-bordered > thead > tr > th:first-child, .panel > .table-bordered > tbody > tr > th:first-child, @@ -4887,8 +5981,9 @@ a.list-group-item-danger.active:focus { .panel > .table-responsive > .table-bordered > tbody > tr > td:first-child, .panel > .table-bordered > tfoot > tr > td:first-child, .panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child { - border-left: 0; + border-left: 0; } + .panel > .table-bordered > thead > tr > th:last-child, .panel > .table-responsive > .table-bordered > thead > tr > th:last-child, .panel > .table-bordered > tbody > tr > th:last-child, @@ -4901,8 +5996,9 @@ a.list-group-item-danger.active:focus { .panel > .table-responsive > .table-bordered > tbody > tr > td:last-child, .panel > .table-bordered > tfoot > tr > td:last-child, .panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child { - border-right: 0; + border-right: 0; } + .panel > .table-bordered > thead > tr:first-child > td, .panel > .table-responsive > .table-bordered > thead > tr:first-child > td, .panel > .table-bordered > tbody > tr:first-child > td, @@ -4911,8 +6007,9 @@ a.list-group-item-danger.active:focus { .panel > .table-responsive > .table-bordered > thead > tr:first-child > th, .panel > .table-bordered > tbody > tr:first-child > th, .panel > .table-responsive > .table-bordered > tbody > tr:first-child > th { - border-bottom: 0; + border-bottom: 0; } + .panel > .table-bordered > tbody > tr:last-child > td, .panel > .table-responsive > .table-bordered > tbody > tr:last-child > td, .panel > .table-bordered > tfoot > tr:last-child > td, @@ -4921,674 +6018,799 @@ a.list-group-item-danger.active:focus { .panel > .table-responsive > .table-bordered > tbody > tr:last-child > th, .panel > .table-bordered > tfoot > tr:last-child > th, .panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th { - border-bottom: 0; + border-bottom: 0; } + .panel > .table-responsive { - margin-bottom: 0; - border: 0; + margin-bottom: 0; + border: 0; } + .panel-group { - margin-bottom: 20px; + margin-bottom: 20px; } + .panel-group .panel { - margin-bottom: 0; - overflow: hidden; - border-radius: 4px; + margin-bottom: 0; + overflow: hidden; + border-radius: 4px; } + .panel-group .panel + .panel { - margin-top: 5px; + margin-top: 5px; } + .panel-group .panel-heading { - border-bottom: 0; + border-bottom: 0; } + .panel-group .panel-heading + .panel-collapse .panel-body { - border-top: 1px solid #ddd; + border-top: 1px solid #ddd; } + .panel-group .panel-footer { - border-top: 0; + border-top: 0; } + .panel-group .panel-footer + .panel-collapse .panel-body { - border-bottom: 1px solid #ddd; + border-bottom: 1px solid #ddd; } + .panel-default { - border-color: #ddd; + border-color: #ddd; } + .panel-default > .panel-heading { - color: #333; - background-color: #f5f5f5; - border-color: #ddd; + color: #333; + background-color: #f5f5f5; + border-color: #ddd; } + .panel-default > .panel-heading + .panel-collapse .panel-body { - border-top-color: #ddd; + border-top-color: #ddd; } + .panel-default > .panel-footer + .panel-collapse .panel-body { - border-bottom-color: #ddd; + border-bottom-color: #ddd; } + .panel-primary { - border-color: #428bca; + border-color: #428bca; } + .panel-primary > .panel-heading { - color: #fff; - background-color: #428bca; - border-color: #428bca; + color: #fff; + background-color: #428bca; + border-color: #428bca; } + .panel-primary > .panel-heading + .panel-collapse .panel-body { - border-top-color: #428bca; + border-top-color: #428bca; } + .panel-primary > .panel-footer + .panel-collapse .panel-body { - border-bottom-color: #428bca; + border-bottom-color: #428bca; } + .panel-success { - border-color: #d6e9c6; + border-color: #d6e9c6; } + .panel-success > .panel-heading { - color: #3c763d; - background-color: #dff0d8; - border-color: #d6e9c6; + color: #3c763d; + background-color: #dff0d8; + border-color: #d6e9c6; } + .panel-success > .panel-heading + .panel-collapse .panel-body { - border-top-color: #d6e9c6; + border-top-color: #d6e9c6; } + .panel-success > .panel-footer + .panel-collapse .panel-body { - border-bottom-color: #d6e9c6; + border-bottom-color: #d6e9c6; } + .panel-info { - border-color: #bce8f1; + border-color: #bce8f1; } + .panel-info > .panel-heading { - color: #31708f; - background-color: #d9edf7; - border-color: #bce8f1; + color: #31708f; + background-color: #d9edf7; + border-color: #bce8f1; } + .panel-info > .panel-heading + .panel-collapse .panel-body { - border-top-color: #bce8f1; + border-top-color: #bce8f1; } + .panel-info > .panel-footer + .panel-collapse .panel-body { - border-bottom-color: #bce8f1; + border-bottom-color: #bce8f1; } + .panel-warning { - border-color: #faebcc; + border-color: #faebcc; } + .panel-warning > .panel-heading { - color: #8a6d3b; - background-color: #fcf8e3; - border-color: #faebcc; + color: #8a6d3b; + background-color: #fcf8e3; + border-color: #faebcc; } + .panel-warning > .panel-heading + .panel-collapse .panel-body { - border-top-color: #faebcc; + border-top-color: #faebcc; } + .panel-warning > .panel-footer + .panel-collapse .panel-body { - border-bottom-color: #faebcc; + border-bottom-color: #faebcc; } + .panel-danger { - border-color: #ebccd1; + border-color: #ebccd1; } + .panel-danger > .panel-heading { - color: #a94442; - background-color: #f2dede; - border-color: #ebccd1; + color: #a94442; + background-color: #f2dede; + border-color: #ebccd1; } + .panel-danger > .panel-heading + .panel-collapse .panel-body { - border-top-color: #ebccd1; + border-top-color: #ebccd1; } + .panel-danger > .panel-footer + .panel-collapse .panel-body { - border-bottom-color: #ebccd1; + border-bottom-color: #ebccd1; } + .well { - min-height: 20px; - padding: 19px; - margin-bottom: 20px; - background-color: #f5f5f5; - border: 1px solid #e3e3e3; - border-radius: 4px; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); + min-height: 20px; + padding: 19px; + margin-bottom: 20px; + background-color: #f5f5f5; + border: 1px solid #e3e3e3; + border-radius: 4px; + -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); + box-shadow: inset 0 1px 1px rgba(0, 0, 0, .05); } + .well blockquote { - border-color: #ddd; - border-color: rgba(0, 0, 0, .15); + border-color: #ddd; + border-color: rgba(0, 0, 0, .15); } + .well-lg { - padding: 24px; - border-radius: 6px; + padding: 24px; + border-radius: 6px; } + .well-sm { - padding: 9px; - border-radius: 3px; + padding: 9px; + border-radius: 3px; } + .close { - float: right; - font-size: 21px; - font-weight: bold; - line-height: 1; - color: #000; - text-shadow: 0 1px 0 #fff; - filter: alpha(opacity=20); - opacity: .2; + float: right; + font-size: 21px; + font-weight: bold; + line-height: 1; + color: #000; + text-shadow: 0 1px 0 #fff; + filter: alpha(opacity=20); + opacity: .2; } + .close:hover, .close:focus { - color: #000; - text-decoration: none; - cursor: pointer; - filter: alpha(opacity=50); - opacity: .5; + color: #000; + text-decoration: none; + cursor: pointer; + filter: alpha(opacity=50); + opacity: .5; } + button.close { - -webkit-appearance: none; - padding: 0; - cursor: pointer; - background: transparent; - border: 0; + -webkit-appearance: none; + padding: 0; + cursor: pointer; + background: transparent; + border: 0; } + .modal-open { - overflow: hidden; + overflow: hidden; } + .modal { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1050; - display: none; - overflow: auto; - overflow-y: scroll; - -webkit-overflow-scrolling: touch; - outline: 0; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1050; + display: none; + overflow: auto; + overflow-y: scroll; + -webkit-overflow-scrolling: touch; + outline: 0; } + .modal.fade .modal-dialog { - -webkit-transition: -webkit-transform .3s ease-out; - -moz-transition: -moz-transform .3s ease-out; - -o-transition: -o-transform .3s ease-out; - transition: transform .3s ease-out; - -webkit-transform: translate(0, -25%); - -ms-transform: translate(0, -25%); - transform: translate(0, -25%); + -webkit-transition: -webkit-transform .3s ease-out; + -moz-transition: -moz-transform .3s ease-out; + -o-transition: -o-transform .3s ease-out; + transition: transform .3s ease-out; + -webkit-transform: translate(0, -25%); + -ms-transform: translate(0, -25%); + transform: translate(0, -25%); } + .modal.in .modal-dialog { - -webkit-transform: translate(0, 0); - -ms-transform: translate(0, 0); - transform: translate(0, 0); + -webkit-transform: translate(0, 0); + -ms-transform: translate(0, 0); + transform: translate(0, 0); } + .modal-dialog { - position: relative; - width: auto; - margin: 10px; + position: relative; + width: auto; + margin: 10px; } + .modal-content { - position: relative; - background-color: #fff; - background-clip: padding-box; - border: 1px solid #999; - border: 1px solid rgba(0, 0, 0, .2); - border-radius: 6px; - outline: none; - -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5); - box-shadow: 0 3px 9px rgba(0, 0, 0, .5); + position: relative; + background-color: #fff; + background-clip: padding-box; + border: 1px solid #999; + border: 1px solid rgba(0, 0, 0, .2); + border-radius: 6px; + outline: none; + -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, .5); + box-shadow: 0 3px 9px rgba(0, 0, 0, .5); } + .modal-backdrop { - position: fixed; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1040; - background-color: #000; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1040; + background-color: #000; } + .modal-backdrop.fade { - filter: alpha(opacity=0); - opacity: 0; + filter: alpha(opacity=0); + opacity: 0; } + .modal-backdrop.in { - filter: alpha(opacity=50); - opacity: .5; + filter: alpha(opacity=50); + opacity: .5; } + .modal-header { - min-height: 16.42857143px; - padding: 15px; - border-bottom: 1px solid #e5e5e5; + min-height: 16.42857143px; + padding: 15px; + border-bottom: 1px solid #e5e5e5; } + .modal-header .close { - margin-top: -2px; + margin-top: -2px; } + .modal-title { - margin: 0; - line-height: 1.42857143; + margin: 0; + line-height: 1.42857143; } + .modal-body { - position: relative; - padding: 20px; + position: relative; + padding: 20px; } + .modal-footer { - padding: 19px 20px 20px; - margin-top: 15px; - text-align: right; - border-top: 1px solid #e5e5e5; + padding: 19px 20px 20px; + margin-top: 15px; + text-align: right; + border-top: 1px solid #e5e5e5; } + .modal-footer .btn + .btn { - margin-bottom: 0; - margin-left: 5px; + margin-bottom: 0; + margin-left: 5px; } + .modal-footer .btn-group .btn + .btn { - margin-left: -1px; + margin-left: -1px; } + .modal-footer .btn-block + .btn-block { - margin-left: 0; + margin-left: 0; } + @media (min-width: 768px) { - .modal-dialog { - width: 600px; - margin: 30px auto; - } - .modal-content { - -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5); - box-shadow: 0 5px 15px rgba(0, 0, 0, .5); - } - .modal-sm { - width: 300px; - } + .modal-dialog { + width: 600px; + margin: 30px auto; + } + + .modal-content { + -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, .5); + box-shadow: 0 5px 15px rgba(0, 0, 0, .5); + } + + .modal-sm { + width: 300px; + } } + @media (min-width: 992px) { - .modal-lg { - width: 900px; - } + .modal-lg { + width: 900px; + } } + .tooltip { - position: absolute; - z-index: 1030; - display: block; - font-size: 12px; - line-height: 1.4; - visibility: visible; - filter: alpha(opacity=0); - opacity: 0; + position: absolute; + z-index: 1030; + display: block; + font-size: 12px; + line-height: 1.4; + visibility: visible; + filter: alpha(opacity=0); + opacity: 0; } + .tooltip.in { - filter: alpha(opacity=90); - opacity: .9; + filter: alpha(opacity=90); + opacity: .9; } + .tooltip.top { - padding: 5px 0; - margin-top: -3px; + padding: 5px 0; + margin-top: -3px; } + .tooltip.right { - padding: 0 5px; - margin-left: 3px; + padding: 0 5px; + margin-left: 3px; } + .tooltip.bottom { - padding: 5px 0; - margin-top: 3px; + padding: 5px 0; + margin-top: 3px; } + .tooltip.left { - padding: 0 5px; - margin-left: -3px; + padding: 0 5px; + margin-left: -3px; } + .tooltip-inner { - max-width: 200px; - padding: 3px 8px; - color: #fff; - text-align: center; - text-decoration: none; - background-color: #000; - border-radius: 4px; + max-width: 200px; + padding: 3px 8px; + color: #fff; + text-align: center; + text-decoration: none; + background-color: #000; + border-radius: 4px; } + .tooltip-arrow { - position: absolute; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; + position: absolute; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; } + .tooltip.top .tooltip-arrow { - bottom: 0; - left: 50%; - margin-left: -5px; - border-width: 5px 5px 0; - border-top-color: #000; + bottom: 0; + left: 50%; + margin-left: -5px; + border-width: 5px 5px 0; + border-top-color: #000; } + .tooltip.top-left .tooltip-arrow { - bottom: 0; - left: 5px; - border-width: 5px 5px 0; - border-top-color: #000; + bottom: 0; + left: 5px; + border-width: 5px 5px 0; + border-top-color: #000; } + .tooltip.top-right .tooltip-arrow { - right: 5px; - bottom: 0; - border-width: 5px 5px 0; - border-top-color: #000; + right: 5px; + bottom: 0; + border-width: 5px 5px 0; + border-top-color: #000; } + .tooltip.right .tooltip-arrow { - top: 50%; - left: 0; - margin-top: -5px; - border-width: 5px 5px 5px 0; - border-right-color: #000; + top: 50%; + left: 0; + margin-top: -5px; + border-width: 5px 5px 5px 0; + border-right-color: #000; } + .tooltip.left .tooltip-arrow { - top: 50%; - right: 0; - margin-top: -5px; - border-width: 5px 0 5px 5px; - border-left-color: #000; + top: 50%; + right: 0; + margin-top: -5px; + border-width: 5px 0 5px 5px; + border-left-color: #000; } + .tooltip.bottom .tooltip-arrow { - top: 0; - left: 50%; - margin-left: -5px; - border-width: 0 5px 5px; - border-bottom-color: #000; + top: 0; + left: 50%; + margin-left: -5px; + border-width: 0 5px 5px; + border-bottom-color: #000; } + .tooltip.bottom-left .tooltip-arrow { - top: 0; - left: 5px; - border-width: 0 5px 5px; - border-bottom-color: #000; + top: 0; + left: 5px; + border-width: 0 5px 5px; + border-bottom-color: #000; } + .tooltip.bottom-right .tooltip-arrow { - top: 0; - right: 5px; - border-width: 0 5px 5px; - border-bottom-color: #000; + top: 0; + right: 5px; + border-width: 0 5px 5px; + border-bottom-color: #000; } + .popover { - position: absolute; - top: 0; - left: 0; - z-index: 1010; - display: none; - max-width: 276px; - padding: 1px; - text-align: left; - white-space: normal; - background-color: #fff; - background-clip: padding-box; - border: 1px solid #ccc; - border: 1px solid rgba(0, 0, 0, .2); - border-radius: 6px; - -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2); - box-shadow: 0 5px 10px rgba(0, 0, 0, .2); + position: absolute; + top: 0; + left: 0; + z-index: 1010; + display: none; + max-width: 276px; + padding: 1px; + text-align: left; + white-space: normal; + background-color: #fff; + background-clip: padding-box; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, .2); + border-radius: 6px; + -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, .2); + box-shadow: 0 5px 10px rgba(0, 0, 0, .2); } + .popover.top { - margin-top: -10px; + margin-top: -10px; } + .popover.right { - margin-left: 10px; + margin-left: 10px; } + .popover.bottom { - margin-top: 10px; + margin-top: 10px; } + .popover.left { - margin-left: -10px; + margin-left: -10px; } + .popover-title { - padding: 8px 14px; - margin: 0; - font-size: 14px; - font-weight: normal; - line-height: 18px; - background-color: #f7f7f7; - border-bottom: 1px solid #ebebeb; - border-radius: 5px 5px 0 0; + padding: 8px 14px; + margin: 0; + font-size: 14px; + font-weight: normal; + line-height: 18px; + background-color: #f7f7f7; + border-bottom: 1px solid #ebebeb; + border-radius: 5px 5px 0 0; } + .popover-content { - padding: 9px 14px; + padding: 9px 14px; } + .popover > .arrow, .popover > .arrow:after { - position: absolute; - display: block; - width: 0; - height: 0; - border-color: transparent; - border-style: solid; + position: absolute; + display: block; + width: 0; + height: 0; + border-color: transparent; + border-style: solid; } + .popover > .arrow { - border-width: 11px; + border-width: 11px; } + .popover > .arrow:after { - content: ""; - border-width: 10px; + content: ""; + border-width: 10px; } + .popover.top > .arrow { - bottom: -11px; - left: 50%; - margin-left: -11px; - border-top-color: #999; - border-top-color: rgba(0, 0, 0, .25); - border-bottom-width: 0; + bottom: -11px; + left: 50%; + margin-left: -11px; + border-top-color: #999; + border-top-color: rgba(0, 0, 0, .25); + border-bottom-width: 0; } + .popover.top > .arrow:after { - bottom: 1px; - margin-left: -10px; - content: " "; - border-top-color: #fff; - border-bottom-width: 0; + bottom: 1px; + margin-left: -10px; + content: " "; + border-top-color: #fff; + border-bottom-width: 0; } + .popover.right > .arrow { - top: 50%; - left: -11px; - margin-top: -11px; - border-right-color: #999; - border-right-color: rgba(0, 0, 0, .25); - border-left-width: 0; + top: 50%; + left: -11px; + margin-top: -11px; + border-right-color: #999; + border-right-color: rgba(0, 0, 0, .25); + border-left-width: 0; } + .popover.right > .arrow:after { - bottom: -10px; - left: 1px; - content: " "; - border-right-color: #fff; - border-left-width: 0; + bottom: -10px; + left: 1px; + content: " "; + border-right-color: #fff; + border-left-width: 0; } + .popover.bottom > .arrow { - top: -11px; - left: 50%; - margin-left: -11px; - border-top-width: 0; - border-bottom-color: #999; - border-bottom-color: rgba(0, 0, 0, .25); + top: -11px; + left: 50%; + margin-left: -11px; + border-top-width: 0; + border-bottom-color: #999; + border-bottom-color: rgba(0, 0, 0, .25); } + .popover.bottom > .arrow:after { - top: 1px; - margin-left: -10px; - content: " "; - border-top-width: 0; - border-bottom-color: #fff; + top: 1px; + margin-left: -10px; + content: " "; + border-top-width: 0; + border-bottom-color: #fff; } + .popover.left > .arrow { - top: 50%; - right: -11px; - margin-top: -11px; - border-right-width: 0; - border-left-color: #999; - border-left-color: rgba(0, 0, 0, .25); + top: 50%; + right: -11px; + margin-top: -11px; + border-right-width: 0; + border-left-color: #999; + border-left-color: rgba(0, 0, 0, .25); } + .popover.left > .arrow:after { - right: 1px; - bottom: -10px; - content: " "; - border-right-width: 0; - border-left-color: #fff; + right: 1px; + bottom: -10px; + content: " "; + border-right-width: 0; + border-left-color: #fff; } + .carousel { - position: relative; + position: relative; } + .carousel-inner { - position: relative; - width: 100%; - overflow: hidden; + position: relative; + width: 100%; + overflow: hidden; } + .carousel-inner > .item { - position: relative; - display: none; - -webkit-transition: .6s ease-in-out left; - transition: .6s ease-in-out left; + position: relative; + display: none; + -webkit-transition: .6s ease-in-out left; + transition: .6s ease-in-out left; } + .carousel-inner > .item > img, .carousel-inner > .item > a > img { - line-height: 1; + line-height: 1; } + .carousel-inner > .active, .carousel-inner > .next, .carousel-inner > .prev { - display: block; + display: block; } + .carousel-inner > .active { - left: 0; + left: 0; } + .carousel-inner > .next, .carousel-inner > .prev { - position: absolute; - top: 0; - width: 100%; + position: absolute; + top: 0; + width: 100%; } + .carousel-inner > .next { - left: 100%; + left: 100%; } + .carousel-inner > .prev { - left: -100%; + left: -100%; } + .carousel-inner > .next.left, .carousel-inner > .prev.right { - left: 0; + left: 0; } + .carousel-inner > .active.left { - left: -100%; + left: -100%; } + .carousel-inner > .active.right { - left: 100%; + left: 100%; } + .carousel-control { - position: absolute; - top: 0; - bottom: 0; - left: 0; - width: 15%; - font-size: 20px; - color: #fff; - text-align: center; - text-shadow: 0 1px 2px rgba(0, 0, 0, .6); - filter: alpha(opacity=50); - opacity: .5; + position: absolute; + top: 0; + bottom: 0; + left: 0; + width: 15%; + font-size: 20px; + color: #fff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, .6); + filter: alpha(opacity=50); + opacity: .5; } + .carousel-control.left { - background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, .5) 0%), color-stop(rgba(0, 0, 0, .0001) 100%)); - background-image: linear-gradient(to right, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); - background-repeat: repeat-x; + background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, .5) 0%), color-stop(rgba(0, 0, 0, .0001) 100%)); + background-image: linear-gradient(to right, rgba(0, 0, 0, .5) 0%, rgba(0, 0, 0, .0001) 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1); + background-repeat: repeat-x; } + .carousel-control.right { - right: 0; - left: auto; - background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, .0001) 0%), color-stop(rgba(0, 0, 0, .5) 100%)); - background-image: linear-gradient(to right, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); - filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); - background-repeat: repeat-x; + right: 0; + left: auto; + background-image: -webkit-linear-gradient(left, color-stop(rgba(0, 0, 0, .0001) 0%), color-stop(rgba(0, 0, 0, .5) 100%)); + background-image: linear-gradient(to right, rgba(0, 0, 0, .0001) 0%, rgba(0, 0, 0, .5) 100%); + filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1); + background-repeat: repeat-x; } + .carousel-control:hover, .carousel-control:focus { - color: #fff; - text-decoration: none; - filter: alpha(opacity=90); - outline: none; - opacity: .9; + color: #fff; + text-decoration: none; + filter: alpha(opacity=90); + outline: none; + opacity: .9; } + .carousel-control .icon-prev, .carousel-control .icon-next, .carousel-control .glyphicon-chevron-left, .carousel-control .glyphicon-chevron-right { - position: absolute; - top: 50%; - z-index: 5; - display: inline-block; + position: absolute; + top: 50%; + z-index: 5; + display: inline-block; } + .carousel-control .icon-prev, .carousel-control .glyphicon-chevron-left { - left: 50%; + left: 50%; } + .carousel-control .icon-next, .carousel-control .glyphicon-chevron-right { - right: 50%; + right: 50%; } + .carousel-control .icon-prev, .carousel-control .icon-next { - width: 20px; - height: 20px; - margin-top: -10px; - margin-left: -10px; - font-family: serif; + width: 20px; + height: 20px; + margin-top: -10px; + margin-left: -10px; + font-family: serif; } + .carousel-control .icon-prev:before { - content: '\2039'; + content: '\2039'; } + .carousel-control .icon-next:before { - content: '\203a'; + content: '\203a'; } + .carousel-indicators { - position: absolute; - bottom: 10px; - left: 50%; - z-index: 15; - width: 60%; - padding-left: 0; - margin-left: -30%; - text-align: center; - list-style: none; + position: absolute; + bottom: 10px; + left: 50%; + z-index: 15; + width: 60%; + padding-left: 0; + margin-left: -30%; + text-align: center; + list-style: none; } + .carousel-indicators li { - display: inline-block; - width: 10px; - height: 10px; - margin: 1px; - text-indent: -999px; - cursor: pointer; - background-color: #000 \9; - background-color: rgba(0, 0, 0, 0); - border: 1px solid #fff; - border-radius: 10px; + display: inline-block; + width: 10px; + height: 10px; + margin: 1px; + text-indent: -999px; + cursor: pointer; + background-color: #000 \9; + background-color: rgba(0, 0, 0, 0); + border: 1px solid #fff; + border-radius: 10px; } + .carousel-indicators .active { - width: 12px; - height: 12px; - margin: 0; - background-color: #fff; + width: 12px; + height: 12px; + margin: 0; + background-color: #fff; } + .carousel-caption { - position: absolute; - right: 15%; - bottom: 20px; - left: 15%; - z-index: 10; - padding-top: 20px; - padding-bottom: 20px; - color: #fff; - text-align: center; - text-shadow: 0 1px 2px rgba(0, 0, 0, .6); + position: absolute; + right: 15%; + bottom: 20px; + left: 15%; + z-index: 10; + padding-top: 20px; + padding-bottom: 20px; + color: #fff; + text-align: center; + text-shadow: 0 1px 2px rgba(0, 0, 0, .6); } + .carousel-caption .btn { - text-shadow: none; + text-shadow: none; } + @media screen and (min-width: 768px) { - .carousel-control .glyphicon-chevron-left, - .carousel-control .glyphicon-chevron-right, - .carousel-control .icon-prev, - .carousel-control .icon-next { - width: 30px; - height: 30px; - margin-top: -15px; - margin-left: -15px; - font-size: 30px; - } - .carousel-caption { - right: 20%; - left: 20%; - padding-bottom: 30px; - } - .carousel-indicators { - bottom: 20px; - } + .carousel-control .glyphicon-chevron-left, + .carousel-control .glyphicon-chevron-right, + .carousel-control .icon-prev, + .carousel-control .icon-next { + width: 30px; + height: 30px; + margin-top: -15px; + margin-left: -15px; + font-size: 30px; + } + + .carousel-caption { + right: 20%; + left: 20%; + padding-bottom: 30px; + } + + .carousel-indicators { + bottom: 20px; + } } + .clearfix:before, .clearfix:after, .container:before, @@ -5617,9 +6839,10 @@ button.close { .panel-body:after, .modal-footer:before, .modal-footer:after { - display: table; - content: " "; + display: table; + content: " "; } + .clearfix:after, .container:after, .container-fluid:after, @@ -5634,152 +6857,190 @@ button.close { .pager:after, .panel-body:after, .modal-footer:after { - clear: both; + clear: both; } + .center-block { - display: block; - margin-right: auto; - margin-left: auto; + display: block; + margin-right: auto; + margin-left: auto; } + .pull-right { - float: right !important; + float: right !important; } + .pull-left { - float: left !important; + float: left !important; } + .hide { - display: none !important; + display: none !important; } + .show { - display: block !important; + display: block !important; } + .invisible { - visibility: hidden; + visibility: hidden; } + .text-hide { - font: 0/0 a; - color: transparent; - text-shadow: none; - background-color: transparent; - border: 0; + font: 0/0 a; + color: transparent; + text-shadow: none; + background-color: transparent; + border: 0; } + .hidden { - display: none !important; - visibility: hidden !important; + display: none !important; + visibility: hidden !important; } + .affix { - position: fixed; + position: fixed; } + @-ms-viewport { - width: device-width; + width: device-width; } + .visible-xs, .visible-sm, .visible-md, .visible-lg { - display: none !important; + display: none !important; } + @media (max-width: 767px) { - .visible-xs { - display: block !important; - } - table.visible-xs { - display: table; - } - tr.visible-xs { - display: table-row !important; - } - th.visible-xs, - td.visible-xs { - display: table-cell !important; - } + .visible-xs { + display: block !important; + } + + table.visible-xs { + display: table; + } + + tr.visible-xs { + display: table-row !important; + } + + th.visible-xs, + td.visible-xs { + display: table-cell !important; + } } + @media (min-width: 768px) and (max-width: 991px) { - .visible-sm { - display: block !important; - } - table.visible-sm { - display: table; - } - tr.visible-sm { - display: table-row !important; - } - th.visible-sm, - td.visible-sm { - display: table-cell !important; - } + .visible-sm { + display: block !important; + } + + table.visible-sm { + display: table; + } + + tr.visible-sm { + display: table-row !important; + } + + th.visible-sm, + td.visible-sm { + display: table-cell !important; + } } + @media (min-width: 992px) and (max-width: 1199px) { - .visible-md { - display: block !important; - } - table.visible-md { - display: table; - } - tr.visible-md { - display: table-row !important; - } - th.visible-md, - td.visible-md { - display: table-cell !important; - } + .visible-md { + display: block !important; + } + + table.visible-md { + display: table; + } + + tr.visible-md { + display: table-row !important; + } + + th.visible-md, + td.visible-md { + display: table-cell !important; + } } + @media (min-width: 1200px) { - .visible-lg { - display: block !important; - } - table.visible-lg { - display: table; - } - tr.visible-lg { - display: table-row !important; - } - th.visible-lg, - td.visible-lg { - display: table-cell !important; - } + .visible-lg { + display: block !important; + } + + table.visible-lg { + display: table; + } + + tr.visible-lg { + display: table-row !important; + } + + th.visible-lg, + td.visible-lg { + display: table-cell !important; + } } + @media (max-width: 767px) { - .hidden-xs { - display: none !important; - } + .hidden-xs { + display: none !important; + } } + @media (min-width: 768px) and (max-width: 991px) { - .hidden-sm { - display: none !important; - } + .hidden-sm { + display: none !important; + } } + @media (min-width: 992px) and (max-width: 1199px) { - .hidden-md { - display: none !important; - } + .hidden-md { + display: none !important; + } } + @media (min-width: 1200px) { - .hidden-lg { - display: none !important; - } + .hidden-lg { + display: none !important; + } } + .visible-print { - display: none !important; + display: none !important; } + @media print { - .visible-print { - display: block !important; - } - table.visible-print { - display: table; - } - tr.visible-print { - display: table-row !important; - } - th.visible-print, - td.visible-print { - display: table-cell !important; - } + .visible-print { + display: block !important; + } + + table.visible-print { + display: table; + } + + tr.visible-print { + display: table-row !important; + } + + th.visible-print, + td.visible-print { + display: table-cell !important; + } } + @media print { - .hidden-print { - display: none !important; - } + .hidden-print { + display: none !important; + } } + /*# sourceMappingURL=bootstrap.css.map */ diff --git a/pear-modules/pear-process/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/css/bootstrap.css.map b/pear-modules/pear-process/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/css/bootstrap.css.map index 6bc5a2dc75413860670f9e657d62b64cf15fd195..9068d21f18a35e0088382d338465fd95601343ed 100644 --- a/pear-modules/pear-process/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/css/bootstrap.css.map +++ b/pear-modules/pear-process/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/css/bootstrap.css.map @@ -1 +1,85 @@ -{"version":3,"sources":["less/normalize.less","less/print.less","less/scaffolding.less","less/mixins.less","less/variables.less","less/thumbnails.less","less/carousel.less","less/type.less","less/code.less","less/grid.less","less/tables.less","less/forms.less","less/buttons.less","less/button-groups.less","less/component-animations.less","less/glyphicons.less","less/dropdowns.less","less/input-groups.less","less/navs.less","less/navbar.less","less/utilities.less","less/breadcrumbs.less","less/pagination.less","less/pager.less","less/labels.less","less/badges.less","less/jumbotron.less","less/alerts.less","less/progress-bars.less","less/media.less","less/list-group.less","less/panels.less","less/wells.less","less/close.less","less/modals.less","less/tooltip.less","less/popovers.less","less/responsive-utilities.less"],"names":[],"mappings":"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","sourcesContent":["/*! normalize.css v3.0.0 | MIT License | git.io/normalize */\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 -ms-text-size-adjust: 100%; // 2\n -webkit-text-size-adjust: 100%; // 2\n}\n\n//\n// Remove default margin.\n//\n\nbody {\n margin: 0;\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// 1. Correct `inline-block` display not defined in IE 8/9.\n// 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.\n//\n\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block; // 1\n vertical-align: baseline; // 2\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 `[hidden]` styling not present in IE 8/9.\n// Hide the `template` element in IE, Safari, and Firefox < 22.\n//\n\n[hidden],\ntemplate {\n display: none;\n}\n\n// Links\n// ==========================================================================\n\n//\n// Remove the gray background color from active links in IE 10.\n//\n\na {\n background: transparent;\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// Text-level semantics\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 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.\n//\n\nmark {\n background: #ff0;\n color: #000;\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// 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// Grouping content\n// ==========================================================================\n\n//\n// Address margin not present in IE 8/9 and Safari 5.\n//\n\nfigure {\n margin: 1em 40px;\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// Contain overflow in all browsers.\n//\n\npre {\n overflow: auto;\n}\n\n//\n// Address odd `em`-unit font size rendering in all browsers.\n//\n\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\n\n// Forms\n// ==========================================================================\n\n//\n// Known limitation: by default, Chrome and Safari on OS X allow very limited\n// styling of `select`, unless a `border` property is set.\n//\n\n//\n// 1. Correct color not being inherited.\n// Known issue: affects color of disabled elements.\n// 2. Correct font properties not being inherited.\n// 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome.\n//\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n color: inherit; // 1\n font: inherit; // 2\n margin: 0; // 3\n}\n\n//\n// Address `overflow` set to `hidden` in IE 8/9/10.\n//\n\nbutton {\n overflow: visible;\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 Firefox, IE 8+, and Opera\n// Correct `select` style inheritance in Firefox.\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// 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// Address Firefox 4+ setting `line-height` on `input` using `!important` in\n// the UA stylesheet.\n//\n\ninput {\n line-height: normal;\n}\n\n//\n// It's recommended that you don't attempt to style these elements.\n// Firefox's implementation doesn't respect box-sizing, padding, or width.\n//\n// 1. Address box sizing set to `content-box` in IE 8/9/10.\n// 2. Remove excess padding in IE 8/9/10.\n//\n\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n box-sizing: border-box; // 1\n padding: 0; // 2\n}\n\n//\n// Fix the cursor style for Chrome's increment/decrement buttons. For certain\n// `font-size` values of the `input`, it causes the cursor style of the\n// decrement button to change from `default` to `text`.\n//\n\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\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 and Chrome on OS X.\n// Safari (but not Chrome) clips the cancel button when the search input has\n// padding (and `textfield` appearance).\n//\n\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\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// Remove default vertical scrollbar in IE 8/9.\n//\n\ntextarea {\n overflow: auto;\n}\n\n//\n// Don't inherit the `font-weight` (applied by a rule above).\n// NOTE: the default cannot safely be changed in Chrome and Safari on OS X.\n//\n\noptgroup {\n font-weight: bold;\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\ntd,\nth {\n padding: 0;\n}","//\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 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 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 // Chrome (OSX) fix for https://github.com/twbs/bootstrap/issues/11245\n // Once fixed, we can just straight up remove this.\n select {\n background: #fff !important;\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","//\n// Scaffolding\n// --------------------------------------------------\n\n\n// Reset the box-sizing\n//\n// Heads up! This reset may cause conflicts with some third-party widgets.\n// For recommendations on resolving such conflicts, see\n// http://getbootstrap.com/getting-started/#third-box-sizing\n* {\n .box-sizing(border-box);\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\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// Figures\n//\n// We reset this here because previously Normalize had no `figure` margins. This\n// ensures we don't break anyone's use of the element.\n\nfigure {\n margin: 0;\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","//\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;\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\n opacity: 1; } // See https://github.com/twbs/bootstrap/pull/11526\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//\n// Heads up! v3 launched with with only `.hide-text()`, but per our pattern for\n// mixins being reused as classes with the same name, this doesn't hold up. As\n// of v3.0.1 we have added `.text-hide()` and deprecated `.hide-text()`. Note\n// that we cannot chain the mixins together in Less, so they are repeated.\n//\n// Source: https://github.com/h5bp/html5-boilerplate/commit/aa0396eae757\n\n// Deprecated as of v3.0.1 (will be removed in v4)\n.hide-text() {\n font: ~\"0/0\" a;\n color: transparent;\n text-shadow: none;\n background-color: transparent;\n border: 0;\n}\n// New mixin to use as of v3.0.1\n.text-hide() {\n .hide-text();\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//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support the\n// standard `box-shadow` property.\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-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\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 only\n transform: rotate(@degrees);\n}\n.scale(@ratio; @ratio-y...) {\n -webkit-transform: scale(@ratio, @ratio-y);\n -ms-transform: scale(@ratio, @ratio-y); // IE9 only\n transform: scale(@ratio, @ratio-y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\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.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\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.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 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-linear-gradient(left, color-stop(@start-color @start-percent), color-stop(@end-color @end-percent)); // Safari 5.1-6, Chrome 10+\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\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-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\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-6, Chrome 10+\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-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-linear-gradient(@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-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: rgba(255,255,255,.15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 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\n & > .panel-heading {\n color: @heading-text-color;\n background-color: @heading-bg-color;\n border-color: @heading-border;\n\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\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) {\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 }\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 &.@{state}:hover > th {\n background-color: darken(@background, 5%);\n }\n }\n}\n\n// List Groups\n// -------------------------\n.list-group-item-variant(@state; @background; @color) {\n .list-group-item-@{state} {\n color: @color;\n background-color: @background;\n\n a& {\n color: @color;\n\n .list-group-item-heading { color: inherit; }\n\n &:hover,\n &:focus {\n color: @color;\n background-color: darken(@background, 5%);\n }\n &.active,\n &.active:hover,\n &.active:focus {\n color: #fff;\n background-color: @color;\n border-color: @color;\n }\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 .badge {\n color: @background;\n background-color: @color;\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// Contextual backgrounds\n// -------------------------\n.bg-variant(@color) {\n background-color: @color;\n a&:hover {\n background-color: darken(@color, 10%);\n }\n}\n\n// Typography\n// -------------------------\n.text-emphasis-variant(@color) {\n color: @color;\n a&:hover {\n color: darken(@color, 10%);\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();\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 table& { display: table; }\n tr& { display: table-row !important; }\n th&,\n td& { display: table-cell !important; }\n}\n\n.responsive-invisibility() {\n display: none !important;\n}\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 &:extend(.clearfix all);\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 &:extend(.clearfix all);\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 min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n}\n.make-xs-column-offset(@columns) {\n @media (min-width: @screen-xs-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-xs-column-push(@columns) {\n @media (min-width: @screen-xs-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-xs-column-pull(@columns) {\n @media (min-width: @screen-xs-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n\n// Generate the small columns\n.make-sm-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-sm-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-offset(@columns) {\n @media (min-width: @screen-sm-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-push(@columns) {\n @media (min-width: @screen-sm-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-pull(@columns) {\n @media (min-width: @screen-sm-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n\n// Generate the medium columns\n.make-md-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-md-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-offset(@columns) {\n @media (min-width: @screen-md-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-push(@columns) {\n @media (min-width: @screen-md-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-pull(@columns) {\n @media (min-width: @screen-md-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n\n// Generate the large columns\n.make-lg-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-lg-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-offset(@columns) {\n @media (min-width: @screen-lg-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-push(@columns) {\n @media (min-width: @screen-lg-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-pull(@columns) {\n @media (min-width: @screen-lg-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n\n// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `@grid-columns`.\n\n.make-grid-columns() {\n // Common styles for all sizes of grid columns, widths 1-12\n .col(@index) when (@index = 1) { // initial\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general; \"=<\" isn't a typo\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\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 .col(1); // kickstart it\n}\n\n.float-grid-columns(@class) {\n .col(@index) when (@index = 1) { // initial\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n float: left;\n }\n }\n .col(1); // kickstart it\n}\n\n.calc-grid-column(@index, @class, @type) when (@type = width) and (@index > 0) {\n .col-@{class}-@{index} {\n width: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) {\n .col-@{class}-push-@{index} {\n left: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) {\n .col-@{class}-pull-@{index} {\n right: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = offset) {\n .col-@{class}-offset-@{index} {\n margin-left: percentage((@index / @grid-columns));\n }\n}\n\n// Basic looping in LESS\n.loop-grid-columns(@index, @class, @type) when (@index >= 0) {\n .calc-grid-column(@index, @class, @type);\n // next iteration\n .loop-grid-columns((@index - 1), @class, @type);\n}\n\n// Create grid for specific class\n.make-grid(@class) {\n .float-grid-columns(@class);\n .loop-grid-columns(@grid-columns, @class, width);\n .loop-grid-columns(@grid-columns, @class, pull);\n .loop-grid-columns(@grid-columns, @class, push);\n .loop-grid-columns(@grid-columns, @class, offset);\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 .radio,\n .checkbox,\n .radio-inline,\n .checkbox-inline {\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 // Optional feedback icon\n .form-control-feedback {\n color: @text-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. `` background color\n@input-bg: #fff;\n//** `` background color\n@input-bg-disabled: @gray-lighter;\n\n//** Text color for ``s\n@input-color: @gray;\n//** `` border color\n@input-border: #ccc;\n//** `` border radius\n@input-border-radius: @border-radius-base;\n//** Border color for inputs on focus\n@input-border-focus: #66afe9;\n\n//** Placeholder text color\n@input-color-placeholder: @gray-light;\n\n//** Default `.form-control` height\n@input-height-base: (@line-height-computed + (@padding-base-vertical * 2) + 2);\n//** Large `.form-control` height\n@input-height-large: (ceil(@font-size-large * @line-height-large) + (@padding-large-vertical * 2) + 2);\n//** Small `.form-control` height\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//** Background color for textual input addons\n@input-group-addon-bg: @gray-lighter;\n//** Border color for textual input addons\n@input-group-addon-border-color: @input-border;\n\n\n//== Dropdowns\n//\n//## Dropdown menu container and contents.\n\n//** Background for the dropdown menu.\n@dropdown-bg: #fff;\n//** Dropdown menu `border-color`.\n@dropdown-border: rgba(0,0,0,.15);\n//** Dropdown menu `border-color` **for IE8**.\n@dropdown-fallback-border: #ccc;\n//** Divider color for between dropdown items.\n@dropdown-divider-bg: #e5e5e5;\n\n//** Dropdown link text color.\n@dropdown-link-color: @gray-dark;\n//** Hover color for dropdown links.\n@dropdown-link-hover-color: darken(@gray-dark, 5%);\n//** Hover background for dropdown links.\n@dropdown-link-hover-bg: #f5f5f5;\n\n//** Active dropdown menu item text color.\n@dropdown-link-active-color: @component-active-color;\n//** Active dropdown menu item background color.\n@dropdown-link-active-bg: @component-active-bg;\n\n//** Disabled dropdown menu item background color.\n@dropdown-link-disabled-color: @gray-light;\n\n//** Text color for headers within dropdown menus.\n@dropdown-header-color: @gray-light;\n\n// Note: Deprecated @dropdown-caret-color as of v3.1.0\n@dropdown-caret-color: #000;\n\n\n//-- Z-index master list\n//\n// Warning: Avoid customizing these values. They're used for a bird's eye view\n// of components dependent on the z-axis and are designed to all work together.\n//\n// Note: These variables are not generated into the Customizer.\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\n//== Media queries breakpoints\n//\n//## Define the breakpoints at which your layout will change, adapting to different screen sizes.\n\n// Extra small screen / phone\n// Note: Deprecated @screen-xs and @screen-phone as of v3.0.1\n@screen-xs: 480px;\n@screen-xs-min: @screen-xs;\n@screen-phone: @screen-xs-min;\n\n// Small screen / tablet\n// Note: Deprecated @screen-sm and @screen-tablet as of v3.0.1\n@screen-sm: 768px;\n@screen-sm-min: @screen-sm;\n@screen-tablet: @screen-sm-min;\n\n// Medium screen / desktop\n// Note: Deprecated @screen-md and @screen-desktop as of v3.0.1\n@screen-md: 992px;\n@screen-md-min: @screen-md;\n@screen-desktop: @screen-md-min;\n\n// Large screen / wide desktop\n// Note: Deprecated @screen-lg and @screen-lg-desktop as of v3.0.1\n@screen-lg: 1200px;\n@screen-lg-min: @screen-lg;\n@screen-lg-desktop: @screen-lg-min;\n\n// So media queries don't overlap when required, provide a maximum\n@screen-xs-max: (@screen-sm-min - 1);\n@screen-sm-max: (@screen-md-min - 1);\n@screen-md-max: (@screen-lg-min - 1);\n\n\n//== Grid system\n//\n//## Define your custom responsive grid.\n\n//** Number of columns in the grid.\n@grid-columns: 12;\n//** Padding between columns. Gets divided in half for the left and right.\n@grid-gutter-width: 30px;\n// Navbar collapse\n//** Point at which the navbar becomes uncollapsed.\n@grid-float-breakpoint: @screen-sm-min;\n//** Point at which the navbar begins collapsing.\n@grid-float-breakpoint-max: (@grid-float-breakpoint - 1);\n\n\n//== Container sizes\n//\n//## Define the maximum width of `.container` for different screen sizes.\n\n// Small screen / tablet\n@container-tablet: ((720px + @grid-gutter-width));\n//** For `@screen-sm-min` and up.\n@container-sm: @container-tablet;\n\n// Medium screen / desktop\n@container-desktop: ((940px + @grid-gutter-width));\n//** For `@screen-md-min` and up.\n@container-md: @container-desktop;\n\n// Large screen / wide desktop\n@container-large-desktop: ((1140px + @grid-gutter-width));\n//** For `@screen-lg-min` and up.\n@container-lg: @container-large-desktop;\n\n\n//== Navbar\n//\n//##\n\n// Basics of a navbar\n@navbar-height: 50px;\n@navbar-margin-bottom: @line-height-computed;\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@navbar-collapse-max-height: 340px;\n\n@navbar-default-color: #777;\n@navbar-default-bg: #f8f8f8;\n@navbar-default-border: darken(@navbar-default-bg, 6.5%);\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-brand-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: #888;\n@navbar-default-toggle-border-color: #ddd;\n\n\n// Inverted navbar\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 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\n//=== Shared nav styles\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\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-border-radius: @border-radius-base;\n@nav-pills-active-link-hover-bg: @component-active-bg;\n@nav-pills-active-link-hover-color: @component-active-color;\n\n\n//== Pagination\n//\n//##\n\n@pagination-color: @link-color;\n@pagination-bg: #fff;\n@pagination-border: #ddd;\n\n@pagination-hover-color: @link-hover-color;\n@pagination-hover-bg: @gray-lighter;\n@pagination-hover-border: #ddd;\n\n@pagination-active-color: #fff;\n@pagination-active-bg: @brand-primary;\n@pagination-active-border: @brand-primary;\n\n@pagination-disabled-color: @gray-light;\n@pagination-disabled-bg: #fff;\n@pagination-disabled-border: #ddd;\n\n\n//== Pager\n//\n//##\n\n@pager-bg: @pagination-bg;\n@pager-border: @pagination-border;\n@pager-border-radius: 15px;\n\n@pager-hover-bg: @pagination-hover-bg;\n\n@pager-active-bg: @pagination-active-bg;\n@pager-active-color: @pagination-active-color;\n\n@pager-disabled-color: @pagination-disabled-color;\n\n\n//== Jumbotron\n//\n//##\n\n@jumbotron-padding: 30px;\n@jumbotron-color: inherit;\n@jumbotron-bg: @gray-lighter;\n@jumbotron-heading-color: inherit;\n@jumbotron-font-size: ceil((@font-size-base * 1.5));\n\n\n//== Form states and alerts\n//\n//## Define colors for form feedback states and, by default, alerts.\n\n@state-success-text: #3c763d;\n@state-success-bg: #dff0d8;\n@state-success-border: darken(spin(@state-success-bg, -10), 5%);\n\n@state-info-text: #31708f;\n@state-info-bg: #d9edf7;\n@state-info-border: darken(spin(@state-info-bg, -10), 7%);\n\n@state-warning-text: #8a6d3b;\n@state-warning-bg: #fcf8e3;\n@state-warning-border: darken(spin(@state-warning-bg, -10), 5%);\n\n@state-danger-text: #a94442;\n@state-danger-bg: #f2dede;\n@state-danger-border: darken(spin(@state-danger-bg, -10), 5%);\n\n\n//== Tooltips\n//\n//##\n\n//** Tooltip max width\n@tooltip-max-width: 200px;\n//** Tooltip text color\n@tooltip-color: #fff;\n//** Tooltip background color\n@tooltip-bg: #000;\n@tooltip-opacity: .9;\n\n//** Tooltip arrow width\n@tooltip-arrow-width: 5px;\n//** Tooltip arrow color\n@tooltip-arrow-color: @tooltip-bg;\n\n\n//== Popovers\n//\n//##\n\n//** Popover body background color\n@popover-bg: #fff;\n//** Popover maximum width\n@popover-max-width: 276px;\n//** Popover border color\n@popover-border-color: rgba(0,0,0,.2);\n//** Popover fallback border color\n@popover-fallback-border-color: #ccc;\n\n//** Popover title background color\n@popover-title-bg: darken(@popover-bg, 3%);\n\n//** Popover arrow width\n@popover-arrow-width: 10px;\n//** Popover arrow color\n@popover-arrow-color: #fff;\n\n//** Popover outer arrow width\n@popover-arrow-outer-width: (@popover-arrow-width + 1);\n//** Popover outer arrow color\n@popover-arrow-outer-color: fadein(@popover-border-color, 5%);\n//** Popover outer arrow fallback color\n@popover-arrow-outer-fallback-color: darken(@popover-fallback-border-color, 20%);\n\n\n//== Labels\n//\n//##\n\n//** Default label background color\n@label-default-bg: @gray-light;\n//** Primary label background color\n@label-primary-bg: @brand-primary;\n//** Success label background color\n@label-success-bg: @brand-success;\n//** Info label background color\n@label-info-bg: @brand-info;\n//** Warning label background color\n@label-warning-bg: @brand-warning;\n//** Danger label background color\n@label-danger-bg: @brand-danger;\n\n//** Default label text color\n@label-color: #fff;\n//** Default text color of a linked label\n@label-link-hover-color: #fff;\n\n\n//== Modals\n//\n//##\n\n//** Padding applied to the modal body\n@modal-inner-padding: 20px;\n\n//** Padding applied to the modal title\n@modal-title-padding: 15px;\n//** Modal title line-height\n@modal-title-line-height: @line-height-base;\n\n//** Background color of modal content area\n@modal-content-bg: #fff;\n//** Modal content border color\n@modal-content-border-color: rgba(0,0,0,.2);\n//** Modal content border color **for IE8**\n@modal-content-fallback-border-color: #999;\n\n//** Modal backdrop background color\n@modal-backdrop-bg: #000;\n//** Modal backdrop opacity\n@modal-backdrop-opacity: .5;\n//** Modal header border color\n@modal-header-border-color: #e5e5e5;\n//** Modal footer border color\n@modal-footer-border-color: @modal-header-border-color;\n\n@modal-lg: 900px;\n@modal-md: 600px;\n@modal-sm: 300px;\n\n\n//== Alerts\n//\n//## Define alert colors, border radius, and padding.\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//##\n\n//** Background color of the whole progress component\n@progress-bg: #f5f5f5;\n//** Progress bar text color\n@progress-bar-color: #fff;\n\n//** Default progress bar color\n@progress-bar-bg: @brand-primary;\n//** Success progress bar color\n@progress-bar-success-bg: @brand-success;\n//** Warning progress bar color\n@progress-bar-warning-bg: @brand-warning;\n//** Danger progress bar color\n@progress-bar-danger-bg: @brand-danger;\n//** Info progress bar color\n@progress-bar-info-bg: @brand-info;\n\n\n//== List group\n//\n//##\n\n//** Background color on `.list-group-item`\n@list-group-bg: #fff;\n//** `.list-group-item` border color\n@list-group-border: #ddd;\n//** List group border radius\n@list-group-border-radius: @border-radius-base;\n\n//** Background color of single list elements on hover\n@list-group-hover-bg: #f5f5f5;\n//** Text color of active list elements\n@list-group-active-color: @component-active-color;\n//** Background color of active list elements\n@list-group-active-bg: @component-active-bg;\n//** Border color of active list elements\n@list-group-active-border: @list-group-active-bg;\n@list-group-active-text-color: lighten(@list-group-active-bg, 40%);\n\n@list-group-link-color: #555;\n@list-group-link-heading-color: #333;\n\n\n//== Panels\n//\n//##\n\n@panel-bg: #fff;\n@panel-body-padding: 15px;\n@panel-border-radius: @border-radius-base;\n\n//** Border color for elements within panels\n@panel-inner-border: #ddd;\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-info-text: @state-info-text;\n@panel-info-border: @state-info-border;\n@panel-info-heading-bg: @state-info-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\n//== Thumbnails\n//\n//##\n\n//** Padding around the thumbnail image\n@thumbnail-padding: 4px;\n//** Thumbnail background color\n@thumbnail-bg: @body-bg;\n//** Thumbnail border color\n@thumbnail-border: #ddd;\n//** Thumbnail border radius\n@thumbnail-border-radius: @border-radius-base;\n\n//** Custom text color for thumbnail captions\n@thumbnail-caption-color: @text-color;\n//** Padding around the thumbnail caption\n@thumbnail-caption-padding: 9px;\n\n\n//== Wells\n//\n//##\n\n@well-bg: #f5f5f5;\n@well-border: darken(@well-bg, 7%);\n\n\n//== Badges\n//\n//##\n\n@badge-color: #fff;\n//** Linked badge text color on hover\n@badge-link-hover-color: #fff;\n@badge-bg: @gray-light;\n\n//** Badge text color in active nav link\n@badge-active-color: @link-color;\n//** Badge background color in active nav link\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//##\n\n@breadcrumb-padding-vertical: 8px;\n@breadcrumb-padding-horizontal: 15px;\n//** Breadcrumb background color\n@breadcrumb-bg: #f5f5f5;\n//** Breadcrumb text color\n@breadcrumb-color: #ccc;\n//** Text color of current page in the breadcrumb\n@breadcrumb-active-color: @gray-light;\n//** Textual separator for between breadcrumb elements\n@breadcrumb-separator: \"/\";\n\n\n//== Carousel\n//\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//##\n\n@close-font-weight: bold;\n@close-color: #000;\n@close-text-shadow: 0 1px 0 #fff;\n\n\n//== Code\n//\n//##\n\n@code-color: #c7254e;\n@code-bg: #f9f2f4;\n\n@kbd-color: #fff;\n@kbd-bg: #333;\n\n@pre-bg: #f5f5f5;\n@pre-color: @gray-dark;\n@pre-border-color: #ccc;\n@pre-scrollable-max-height: 340px;\n\n\n//== Type\n//\n//##\n\n//** Text muted color\n@text-muted: @gray-light;\n//** Abbreviations and acronyms border color\n@abbr-border-color: @gray-light;\n//** Headings small color\n@headings-small-color: @gray-light;\n//** Blockquote small color\n@blockquote-small-color: @gray-light;\n//** Blockquote font size\n@blockquote-font-size: (@font-size-base * 1.25);\n//** Blockquote border color\n@blockquote-border-color: @gray-lighter;\n//** Page header border color\n@page-header-border-color: @gray-lighter;\n\n\n//== Miscellaneous\n//\n//##\n\n//** Horizontal line color.\n@hr-border: @gray-lighter;\n\n//** Horizontal offset for forms and lists.\n@component-offset-horizontal: 180px;\n","//\n// Thumbnails\n// --------------------------------------------------\n\n\n// Mixin and adjust the regular image class\n.thumbnail {\n display: block;\n padding: @thumbnail-padding;\n margin-bottom: @line-height-computed;\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 > img,\n a > img {\n &:extend(.img-responsive);\n margin-left: auto;\n margin-right: auto;\n }\n\n // Add a hover state for linked versions only\n a&:hover,\n a&:focus,\n a&.active {\n border-color: @link-color;\n }\n\n // Image captions\n .caption {\n padding: @thumbnail-caption-padding;\n color: @thumbnail-caption-color;\n }\n}\n","//\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 &:extend(.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 outline: none;\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 z-index: 5;\n display: inline-block;\n }\n .icon-prev,\n .glyphicon-chevron-left {\n left: 50%;\n }\n .icon-next,\n .glyphicon-chevron-right {\n right: 50%;\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 // IE8-9 hack for event handling\n //\n // Internet Explorer 8-9 does not support clicks on elements without a set\n // `background-color`. We cannot use `filter` since that's not viewed as a\n // background color by the browser. Thus, a hack is needed.\n //\n // For IE8, we set solid black as it doesn't support `rgba()`. For IE9, we\n // set alpha transparency for the best results possible.\n background-color: #000 \\9; // IE8\n background-color: rgba(0,0,0,0); // IE9\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-sm-min) {\n\n // Scale up the controls a smidge\n .carousel-control {\n .glyphicon-chevron-left,\n .glyphicon-chevron-right,\n .icon-prev,\n .icon-next {\n width: 30px;\n height: 30px;\n margin-top: -15px;\n margin-left: -15px;\n font-size: 30px;\n }\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","//\n// Typography\n// --------------------------------------------------\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 color: @headings-color;\n\n small,\n .small {\n font-weight: normal;\n line-height: 1;\n color: @headings-small-color;\n }\n}\n\nh1, .h1,\nh2, .h2,\nh3, .h3 {\n margin-top: @line-height-computed;\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 65%;\n }\n}\nh4, .h4,\nh5, .h5,\nh6, .h6 {\n margin-top: (@line-height-computed / 2);\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 75%;\n }\n}\n\nh1, .h1 { font-size: @font-size-h1; }\nh2, .h2 { font-size: @font-size-h2; }\nh3, .h3 { font-size: @font-size-h3; }\nh4, .h4 { font-size: @font-size-h4; }\nh5, .h5 { font-size: @font-size-h5; }\nh6, .h6 { font-size: @font-size-h6; }\n\n\n// Body text\n// -------------------------\n\np {\n margin: 0 0 (@line-height-computed / 2);\n}\n\n.lead {\n margin-bottom: @line-height-computed;\n font-size: floor((@font-size-base * 1.15));\n font-weight: 200;\n line-height: 1.4;\n\n @media (min-width: @screen-sm-min) {\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,\n.small { font-size: 85%; }\n\n// Undo browser default styling\ncite { font-style: normal; }\n\n// Alignment\n.text-left { text-align: left; }\n.text-right { text-align: right; }\n.text-center { text-align: center; }\n.text-justify { text-align: justify; }\n\n// Contextual colors\n.text-muted {\n color: @text-muted;\n}\n.text-primary {\n .text-emphasis-variant(@brand-primary);\n}\n.text-success {\n .text-emphasis-variant(@state-success-text);\n}\n.text-info {\n .text-emphasis-variant(@state-info-text);\n}\n.text-warning {\n .text-emphasis-variant(@state-warning-text);\n}\n.text-danger {\n .text-emphasis-variant(@state-danger-text);\n}\n\n// Contextual backgrounds\n// For now we'll leave these alongside the text classes until v4 when we can\n// safely shift things around (per SemVer rules).\n.bg-primary {\n // Given the contrast here, this is the only class to have its color inverted\n // automatically.\n color: #fff;\n .bg-variant(@brand-primary);\n}\n.bg-success {\n .bg-variant(@state-success-bg);\n}\n.bg-info {\n .bg-variant(@state-info-bg);\n}\n.bg-warning {\n .bg-variant(@state-warning-bg);\n}\n.bg-danger {\n .bg-variant(@state-danger-bg);\n}\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// 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\n// Inline turns list items into inline-block\n.list-inline {\n .list-unstyled();\n margin-left: -5px;\n\n > li {\n display: inline-block;\n padding-left: 5px;\n padding-right: 5px;\n }\n}\n\n// Description Lists\ndl {\n margin-top: 0; // Remove browser default\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 &:extend(.clearfix all); // 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// Add 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}\n.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 font-size: @blockquote-font-size;\n border-left: 5px solid @blockquote-border-color;\n\n p,\n ul,\n ol {\n &:last-child {\n margin-bottom: 0;\n }\n }\n\n // Note: Deprecated small and .small as of v3.1.0\n // Context: https://github.com/twbs/bootstrap/issues/11660\n footer,\n small,\n .small {\n display: block;\n font-size: 80%; // back to default font-size\n line-height: @line-height-base;\n color: @blockquote-small-color;\n\n &:before {\n content: '\\2014 \\00A0'; // em dash, nbsp\n }\n }\n}\n\n// Opposite alignment of blockquote\n//\n// Heads up: `blockquote.pull-right` has been deprecated as of v3.1.0.\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n border-right: 5px solid @blockquote-border-color;\n border-left: 0;\n text-align: right;\n\n // Account for citation\n footer,\n small,\n .small {\n &:before { content: ''; }\n &:after {\n content: '\\00A0 \\2014'; // nbsp, em dash\n }\n }\n}\n\n// Quotes\nblockquote:before,\nblockquote:after {\n content: \"\";\n}\n\n// Addresses\naddress {\n margin-bottom: @line-height-computed;\n font-style: normal;\n line-height: @line-height-base;\n}\n","//\n// Code (inline and block)\n// --------------------------------------------------\n\n\n// Inline and block code styles\ncode,\nkbd,\npre,\nsamp {\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// User input typically entered via keyboard\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: @kbd-color;\n background-color: @kbd-bg;\n border-radius: @border-radius-small;\n box-shadow: inset 0 -1px 0 rgba(0,0,0,.25);\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 // 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-radius: 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","//\n// Grid system\n// --------------------------------------------------\n\n\n// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n.container {\n .container-fixed();\n\n @media (min-width: @screen-sm-min) {\n width: @container-sm;\n }\n @media (min-width: @screen-md-min) {\n width: @container-md;\n }\n @media (min-width: @screen-lg-min) {\n width: @container-lg;\n }\n}\n\n\n// Fluid container\n//\n// Utilizes the mixin meant for fixed width containers, but without any defined\n// width for fluid, full width layouts.\n\n.container-fluid {\n .container-fixed();\n}\n\n\n// Row\n//\n// Rows contain and clear the floats of your columns.\n\n.row {\n .make-row();\n}\n\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n.make-grid-columns();\n\n\n// Extra small grid\n//\n// Columns, offsets, pushes, and pulls for extra small devices like\n// smartphones.\n\n.make-grid(xs);\n\n\n// Small grid\n//\n// Columns, offsets, pushes, and pulls for the small device range, from phones\n// to tablets.\n\n@media (min-width: @screen-sm-min) {\n .make-grid(sm);\n}\n\n\n// Medium grid\n//\n// Columns, offsets, pushes, and pulls for the desktop device range.\n\n@media (min-width: @screen-md-min) {\n .make-grid(md);\n}\n\n\n// Large grid\n//\n// Columns, offsets, pushes, and pulls for the large desktop device range.\n\n@media (min-width: @screen-lg-min) {\n .make-grid(lg);\n}\n","//\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,\n > 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 > tr {\n > th,\n > td {\n border-bottom-width: 2px;\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 > tr:nth-child(odd) {\n > td,\n > th {\n background-color: @table-bg-accent;\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 > tr:hover {\n > td,\n > th {\n background-color: @table-bg-hover;\n }\n }\n}\n\n\n// Table cell sizing\n//\n// Reset default table behavior\n\ntable col[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9/10 (see https://github.com/twbs/bootstrap/issues/11623)\n float: none;\n display: table-column;\n}\ntable {\n td,\n th {\n &[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9/10 (see https://github.com/twbs/bootstrap/issues/11623)\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// Generate the contextual variants\n.table-row-variant(active; @table-bg-active);\n.table-row-variant(success; @state-success-bg);\n.table-row-variant(info; @state-info-bg);\n.table-row-variant(warning; @state-warning-bg);\n.table-row-variant(danger; @state-danger-bg);\n\n\n// Responsive tables\n//\n// Wrap your tables in `.table-responsive` 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-xs-max) {\n .table-responsive {\n width: 100%;\n margin-bottom: (@line-height-computed * 0.75);\n overflow-y: hidden;\n overflow-x: scroll;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid @table-border-color;\n -webkit-overflow-scrolling: touch;\n\n // Tighten up spacing\n > .table {\n margin-bottom: 0;\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 }\n\n // Only nuke the last row's bottom-border in `tbody` and `tfoot` since\n // chances are there will be only one `tr` in a `thead` and that would\n // remove the border altogether.\n > tbody,\n > tfoot {\n > tr:last-child {\n > th,\n > td {\n border-bottom: 0;\n }\n }\n }\n\n }\n }\n}\n","//\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 // Chrome and Firefox set a `min-width: -webkit-min-content;` on fieldsets,\n // so we reset that to ensure it behaves more like a standard block element.\n // See https://github.com/twbs/bootstrap/issues/12359.\n min-width: 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// While most of our form styles require extra classes, some basic normalization\n// is required to ensure optimum display with or without those classes to better\n// address browser inconsistencies.\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 file controls to match text inputs\ninput[type=\"file\"] {\n display: block;\n}\n\n// Make range inputs behave like textual form controls\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\n\n// Make multiple select elements height not fixed\nselect[multiple],\nselect[size] {\n height: auto;\n}\n\n// Focus for file, radio, and checkbox\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n .tab-focus();\n}\n\n// Adjust output element\noutput {\n display: block;\n padding-top: (@padding-base-vertical + 1);\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @input-color;\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 background-color: @input-bg;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\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 // Placeholder\n .placeholder();\n\n // Disabled and read-only inputs\n //\n // HTML5 says that controls under a fieldset > legend:first-child won't be\n // disabled if the fieldset is disabled. Due to implementation difficulty, we\n // 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 opacity: 1; // iOS fix for unreadable disabled content\n }\n\n // Reset height for `textarea`s\n textarea& {\n height: auto;\n }\n}\n\n\n// Search inputs in iOS\n//\n// This overrides the extra rounded corners on search inputs in iOS so that our\n// `.form-control` class can properly style them. Note that this cannot simply\n// be added to `.form-control` as it's not specific enough. For details, see\n// https://github.com/twbs/bootstrap/issues/11586.\n\ninput[type=\"search\"] {\n -webkit-appearance: none;\n}\n\n\n// Special styles for iOS date input\n//\n// In Mobile Safari, date inputs require a pixel line-height that matches the\n// given height of the input.\n\ninput[type=\"date\"] {\n line-height: @input-height-base;\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 label {\n display: inline;\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\n// Form control sizing\n//\n// Build on `.form-control` with modifier classes to decrease or increase the\n// height and font-size of form controls.\n\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.has-feedback {\n // Enable absolute positioning\n position: relative;\n\n // Ensure icons don't overlap text\n .form-control {\n padding-right: (@input-height-base * 1.25);\n }\n\n // Feedback icon (requires .glyphicon classes)\n .form-control-feedback {\n position: absolute;\n top: (@line-height-computed + 5); // Height of the `label` and its margin\n right: 0;\n display: block;\n width: @input-height-base;\n height: @input-height-base;\n line-height: @input-height-base;\n text-align: center;\n }\n}\n\n// Feedback states\n.has-success {\n .form-control-validation(@state-success-text; @state-success-text; @state-success-bg);\n}\n.has-warning {\n .form-control-validation(@state-warning-text; @state-warning-text; @state-warning-bg);\n}\n.has-error {\n .form-control-validation(@state-danger-text; @state-danger-text; @state-danger-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}\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-sm-min) {\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 width: auto; // Prevent labels from stacking above inputs in `.form-group`\n vertical-align: middle;\n }\n // Input groups need that 100% width though\n .input-group > .form-control {\n width: 100%;\n }\n\n .control-label {\n margin-bottom: 0;\n vertical-align: middle;\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 vertical-align: middle;\n }\n .radio input[type=\"radio\"],\n .checkbox input[type=\"checkbox\"] {\n float: none;\n margin-left: 0;\n }\n\n // Validation states\n //\n // Reposition the icon because it's now within a grid column and columns have\n // `position: relative;` on them. Also accounts for the grid gutter padding.\n .has-feedback .form-control-feedback {\n top: 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 // Account for padding we're adding to ensure the alignment and of help text\n // and other content below items\n .radio,\n .checkbox {\n min-height: (@line-height-computed + (@padding-base-vertical + 1));\n }\n\n // Make form groups behave like rows\n .form-group {\n .make-row();\n }\n\n .form-control-static {\n padding-top: (@padding-base-vertical + 1);\n }\n\n // Only right align form labels here when the columns stop stacking\n @media (min-width: @screen-sm-min) {\n .control-label {\n text-align: right;\n }\n }\n\n // Validation states\n //\n // Reposition the icon because it's now within a grid column and columns have\n // `position: relative;` on them. Also accounts for the grid gutter padding.\n .has-feedback .form-control-feedback {\n top: 0;\n right: (@grid-gutter-width / 2);\n }\n}\n","//\n// Buttons\n// --------------------------------------------------\n\n\n// Base styles\n// --------------------------------------------------\n\n.btn {\n display: inline-block;\n margin-bottom: 0; // For input.btn\n font-weight: @btn-font-weight;\n text-align: center;\n vertical-align: middle;\n cursor: pointer;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid transparent;\n white-space: nowrap;\n .button-size(@padding-base-vertical; @padding-base-horizontal; @font-size-base; @line-height-base; @border-radius-base);\n .user-select(none);\n\n &,\n &:active,\n &.active {\n &:focus {\n .tab-focus();\n }\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// 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// 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// 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\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 // 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 .button-size(@padding-xs-vertical; @padding-xs-horizontal; @font-size-small; @line-height-small; @border-radius-small);\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","//\n// Button groups\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 margin-left: -5px; // Offset the first child's margin\n &:extend(.clearfix all);\n\n .btn-group,\n .input-group {\n float: left;\n }\n > .btn,\n > .btn-group,\n > .input-group {\n margin-left: 5px;\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 { &: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 .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n\n // Show no shadow for `.btn-link` since it has no other button styles.\n &.btn-link {\n .box-shadow(none);\n }\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 > .btn-group > .btn {\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 &:extend(.clearfix all);\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:not(:last-child) {\n > .btn:last-child,\n > .dropdown-toggle {\n .border-bottom-radius(0);\n }\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-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 > .btn-group {\n float: none;\n display: table-cell;\n width: 1%;\n }\n > .btn-group .btn {\n width: 100%;\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","//\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","//\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// Star\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#@{icon-font-svg-id}') 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 -moz-osx-font-smoothing: grayscale;\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-lock { &:before { content: \"\\e033\"; } }\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-bookmark { &:before { content: \"\\e044\"; } }\n.glyphicon-print { &:before { content: \"\\e045\"; } }\n.glyphicon-camera { &:before { content: \"\\e046\"; } }\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-fire { &:before { content: \"\\e104\"; } }\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-calendar { &:before { content: \"\\e109\"; } }\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-bell { &:before { content: \"\\e123\"; } }\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-wrench { &:before { content: \"\\e136\"; } }\n.glyphicon-tasks { &:before { content: \"\\e137\"; } }\n.glyphicon-filter { &:before { content: \"\\e138\"; } }\n.glyphicon-briefcase { &:before { content: \"\\e139\"; } }\n.glyphicon-fullscreen { &:before { content: \"\\e140\"; } }\n.glyphicon-dashboard { &:before { content: \"\\e141\"; } }\n.glyphicon-paperclip { &:before { content: \"\\e142\"; } }\n.glyphicon-heart-empty { &:before { content: \"\\e143\"; } }\n.glyphicon-link { &:before { content: \"\\e144\"; } }\n.glyphicon-phone { &:before { content: \"\\e145\"; } }\n.glyphicon-pushpin { &:before { content: \"\\e146\"; } }\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","//\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;\n border-right: @caret-width-base solid transparent;\n border-left: @caret-width-base solid transparent;\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 //\n // Deprecated as of 3.1.0 in favor of `.dropdown-menu-[dir]`\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// Menu positioning\n//\n// Add extra class to `.dropdown-menu` to flip the alignment of the dropdown\n// menu with the parent.\n.dropdown-menu-right {\n left: auto; // Reset the default from `.dropdown-menu`\n right: 0;\n}\n// With v3, we enabled auto-flipping if you have a dropdown within a right\n// aligned nav component. To enable the undoing of that, we provide an override\n// to restore the default dropdown menu alignment.\n//\n// This is only for left-aligning a dropdown menu within a `.navbar-right` or\n// `.pull-right` nav component.\n.dropdown-menu-left {\n left: 0;\n right: auto;\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 border-top: 0;\n border-bottom: @caret-width-base solid;\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 .dropdown-menu-right();\n }\n // Necessary for overrides of the default right aligned menu.\n // Will remove come v4 in all likelihood.\n .dropdown-menu-left {\n .dropdown-menu-left();\n }\n }\n}\n\n","//\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 &[class*=\"col-\"] {\n float: none;\n padding-left: 0;\n padding-right: 0;\n }\n\n .form-control {\n // Ensure that the input is always above the *appended* addon button for\n // proper border colors.\n position: relative;\n z-index: 2;\n\n // IE9 fubars the placeholder attribute in text inputs and the arrows on\n // select elements in input groups. To fix it, we float the input. Details:\n // https://github.com/twbs/bootstrap/issues/11561#issuecomment-28936855\n float: left;\n\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 color: @input-color;\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 > .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-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-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 // Jankily prevent input button groups from wrapping with `white-space` and\n // `font-size` in combination with `inline-block` on buttons.\n font-size: 0;\n white-space: nowrap;\n\n // Negative margin for spacing, position for bringing hovered/focused/actived\n // element above the siblings.\n > .btn {\n position: relative;\n + .btn {\n margin-left: -1px;\n }\n // Bring the \"active\" button to the front\n &:hover,\n &:focus,\n &:active {\n z-index: 2;\n }\n }\n\n // Negative margin to only have a 1px border between the two\n &:first-child {\n > .btn,\n > .btn-group {\n margin-right: -1px;\n }\n }\n &:last-child {\n > .btn,\n > .btn-group {\n margin-left: -1px;\n }\n }\n}\n","//\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 &:extend(.clearfix all);\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 // Nav dividers (deprecated with v3.0.1)\n //\n // This should have been removed in v3 with the dropping of `.nav-list`, but\n // we missed it. We don't currently support this anywhere, but in the interest\n // of maintaining backward compatibility in case you use it, it's deprecated.\n .nav-divider {\n .nav-divider();\n }\n\n // Prevent IE8 from misplacing imgs\n //\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 its :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: @nav-pills-border-radius;\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 margin-bottom: 5px;\n }\n }\n\n > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n }\n\n @media (min-width: @screen-sm-min) {\n > li {\n display: table-cell;\n width: 1%;\n > a {\n margin-bottom: 0;\n }\n }\n }\n}\n\n// Move borders to anchors instead of bottom of list\n//\n// Mixin for adding on top the shared `.nav-justified` styles for our tabs\n.nav-tabs-justified {\n border-bottom: 0;\n\n > li > a {\n // Override margin from .nav-tabs\n margin-right: 0;\n border-radius: @border-radius-base;\n }\n\n > .active > a,\n > .active > a:hover,\n > .active > a:focus {\n border: 1px solid @nav-tabs-justified-link-border-color;\n }\n\n @media (min-width: @screen-sm-min) {\n > li > a {\n border-bottom: 1px solid @nav-tabs-justified-link-border-color;\n border-radius: @border-radius-base @border-radius-base 0 0;\n }\n > .active > a,\n > .active > a:hover,\n > .active > a:focus {\n border-bottom-color: @nav-tabs-justified-active-link-border-color;\n }\n }\n}\n\n\n// Tabbable tabs\n// -------------------------\n\n// Hide tabbable panes to start, show them when `.active`\n.tab-content {\n > .tab-pane {\n display: none;\n }\n > .active {\n display: block;\n }\n}\n\n\n// Dropdowns\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","//\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 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 &:extend(.clearfix all);\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 &:extend(.clearfix all);\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: @navbar-collapse-max-height;\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 &:extend(.clearfix all);\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 // Undo the collapse side padding for navbars with containers to ensure\n // alignment of right-aligned contents.\n .navbar-fixed-top &,\n .navbar-static-top &,\n .navbar-fixed-bottom & {\n padding-left: 0;\n padding-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,\n.container-fluid {\n > .navbar-header,\n > .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//\n// Navbar alignment options\n//\n// Display the navbar across the entirety 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 z-index: @zindex-navbar;\n border-width: 0 0 1px;\n\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 z-index: @zindex-navbar-fixed;\n\n // Undo the rounded corners\n @media (min-width: @grid-float-breakpoint) {\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; // override .navbar defaults\n border-width: 1px 0 0;\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 height: @navbar-height;\n\n &:hover,\n &:focus {\n text-decoration: none;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n .navbar > .container &,\n .navbar > .container-fluid & {\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 background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid transparent;\n border-radius: @border-radius-base;\n\n // We remove the `outline` here, but later compensate by attaching `:hover`\n // styles to `:focus`.\n &:focus {\n outline: none;\n }\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 its 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: @grid-float-breakpoint-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-padding-vertical;\n padding-bottom: @navbar-padding-vertical;\n }\n }\n\n &.navbar-right:last-child {\n margin-right: -@navbar-padding-horizontal;\n }\n }\n}\n\n\n// Component alignment\n//\n// Repurpose the pull utilities as their own navbar utilities to avoid specificity\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: @grid-float-breakpoint-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 // Outdent the form if last child to line up with content down the page\n &.navbar-right:last-child {\n margin-right: -@navbar-padding-horizontal;\n }\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\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 &.btn-sm {\n .navbar-vertical-align(@input-height-small);\n }\n &.btn-xs {\n .navbar-vertical-align(22);\n }\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 .navbar-vertical-align(@line-height-computed);\n\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n margin-left: @navbar-padding-horizontal;\n margin-right: @navbar-padding-horizontal;\n\n // Outdent the form if last child to line up with content down the page\n &.navbar-right:last-child {\n margin-right: 0;\n }\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: @navbar-default-border;\n }\n\n // Dropdown menu items\n .navbar-nav {\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 }\n }\n\n @media (max-width: @grid-float-breakpoint-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\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display\n .open .dropdown-menu {\n > .dropdown-header {\n border-color: @navbar-inverse-border;\n }\n .divider {\n background-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","//\n// Utility classes\n// --------------------------------------------------\n\n\n// Floats\n// -------------------------\n\n.clearfix {\n .clearfix();\n}\n.center-block {\n .center-block();\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// Note: Deprecated .hide in favor of .hidden or .sr-only (as appropriate) in v3.0.1\n.hide {\n display: none !important;\n}\n.show {\n display: block !important;\n}\n.invisible {\n visibility: hidden;\n}\n.text-hide {\n .text-hide();\n}\n\n\n// Hide from screenreaders and browsers\n//\n// Credit: HTML5 Boilerplate\n\n.hidden {\n display: none !important;\n visibility: hidden !important;\n}\n\n\n// For Affix plugin\n// -------------------------\n\n.affix {\n position: fixed;\n}\n","//\n// Breadcrumbs\n// --------------------------------------------------\n\n\n.breadcrumb {\n padding: @breadcrumb-padding-vertical @breadcrumb-padding-horizontal;\n margin-bottom: @line-height-computed;\n list-style: none;\n background-color: @breadcrumb-bg;\n border-radius: @border-radius-base;\n\n > li {\n display: inline-block;\n\n + li:before {\n content: \"@{breadcrumb-separator}\\00a0\"; // Unicode space added since inline-block means non-collapsing white-space\n padding: 0 5px;\n color: @breadcrumb-color;\n }\n }\n\n > .active {\n color: @breadcrumb-active-color;\n }\n}\n","//\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 color: @pagination-color;\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 color: @pagination-hover-color;\n background-color: @pagination-hover-bg;\n border-color: @pagination-hover-border;\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-border;\n cursor: default;\n }\n }\n\n > .disabled {\n > span,\n > span:hover,\n > span:focus,\n > a,\n > a:hover,\n > a:focus {\n color: @pagination-disabled-color;\n background-color: @pagination-disabled-bg;\n border-color: @pagination-disabled-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","//\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 &:extend(.clearfix all);\n li {\n display: inline;\n > a,\n > span {\n display: inline-block;\n padding: 5px 14px;\n background-color: @pager-bg;\n border: 1px solid @pager-border;\n border-radius: @pager-border-radius;\n }\n\n > a:hover,\n > a:focus {\n text-decoration: none;\n background-color: @pager-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: @pager-bg;\n cursor: not-allowed;\n }\n }\n\n}\n","//\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 // Quick fix for labels in buttons\n .btn & {\n position: relative;\n top: -1px;\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","//\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 // Quick fix for badges in buttons\n .btn & {\n position: relative;\n top: -1px;\n }\n .btn-xs & {\n top: 0;\n padding: 1px 5px;\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// 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","//\n// Jumbotron\n// --------------------------------------------------\n\n\n.jumbotron {\n padding: @jumbotron-padding;\n margin-bottom: @jumbotron-padding;\n color: @jumbotron-color;\n background-color: @jumbotron-bg;\n\n h1,\n .h1 {\n color: @jumbotron-heading-color;\n }\n p {\n margin-bottom: (@jumbotron-padding / 2);\n font-size: @jumbotron-font-size;\n font-weight: 200;\n }\n\n .container & {\n border-radius: @border-radius-large; // Only round corners at higher resolutions if contained in a container\n }\n\n .container {\n max-width: 100%;\n }\n\n @media screen and (min-width: @screen-sm-min) {\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 .h1 {\n font-size: (@font-size-base * 4.5);\n }\n }\n}\n","//\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 @headings-color\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","//\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// 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 line-height: @line-height-computed;\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();\n background-size: 40px 40px;\n}\n\n// Call animation for the active one\n.progress.active .progress-bar {\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","// 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","//\n// List groups\n// --------------------------------------------------\n\n\n// Base class\n//\n// Easily usable on
    ,
      , or
      .\n\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\n// Individual list items\n//\n// Use on `li`s or `div`s within the `.list-group` parent.\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\n\n// Linked list items\n//\n// Use anchor elements instead of `li`s or `div`s to create linked list items.\n// Includes an extra `.active` modifier class for showing selected items.\n\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 // 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: @list-group-active-text-color;\n }\n }\n}\n\n\n// Contextual variants\n//\n// Add modifier classes to change text and background color on individual items.\n// Organizationally, this must come after the `:hover` states.\n\n.list-group-item-variant(success; @state-success-bg; @state-success-text);\n.list-group-item-variant(info; @state-info-bg; @state-info-text);\n.list-group-item-variant(warning; @state-warning-bg; @state-warning-text);\n.list-group-item-variant(danger; @state-danger-bg; @state-danger-text);\n\n\n// Custom content options\n//\n// Extra classes for creating well-formatted content within `.list-group-item`s.\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","//\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: @panel-body-padding;\n &:extend(.clearfix all);\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 > .dropdown .dropdown-toggle {\n color: inherit;\n }\n}\n\n// Within heading, strip any `h*` tag of its 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 color: inherit;\n\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// 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 border-radius: 0;\n }\n\n // Add border top radius for first one\n &:first-child {\n .list-group-item:first-child {\n border-top: 0;\n .border-top-radius((@panel-border-radius - 1));\n }\n }\n // Add border bottom radius for last one\n &:last-child {\n .list-group-item:last-child {\n border-bottom: 0;\n .border-bottom-radius((@panel-border-radius - 1));\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 > .table-responsive > .table {\n margin-bottom: 0;\n }\n // Add border top radius for first one\n > .table:first-child,\n > .table-responsive:first-child > .table:first-child {\n .border-top-radius((@panel-border-radius - 1));\n\n > thead:first-child,\n > tbody:first-child {\n > tr:first-child {\n td:first-child,\n th:first-child {\n border-top-left-radius: (@panel-border-radius - 1);\n }\n td:last-child,\n th:last-child {\n border-top-right-radius: (@panel-border-radius - 1);\n }\n }\n }\n }\n // Add border bottom radius for last one\n > .table:last-child,\n > .table-responsive:last-child > .table:last-child {\n .border-bottom-radius((@panel-border-radius - 1));\n\n > tbody:last-child,\n > tfoot:last-child {\n > tr:last-child {\n td:first-child,\n th:first-child {\n border-bottom-left-radius: (@panel-border-radius - 1);\n }\n td:last-child,\n th:last-child {\n border-bottom-right-radius: (@panel-border-radius - 1);\n }\n }\n }\n }\n > .panel-body + .table,\n > .panel-body + .table-responsive {\n border-top: 1px solid @table-border-color;\n }\n > .table > tbody:first-child > tr:first-child th,\n > .table > tbody:first-child > tr:first-child td {\n border-top: 0;\n }\n > .table-bordered,\n > .table-responsive > .table-bordered {\n border: 0;\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 }\n > thead,\n > tbody {\n > tr:first-child {\n > td,\n > th {\n border-bottom: 0;\n }\n }\n }\n > tbody,\n > tfoot {\n > tr:last-child {\n > td,\n > th {\n border-bottom: 0;\n }\n }\n }\n }\n > .table-responsive {\n border: 0;\n margin-bottom: 0;\n }\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 margin-bottom: @line-height-computed;\n\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\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-info {\n .panel-variant(@panel-info-border; @panel-info-text; @panel-info-heading-bg; @panel-info-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","//\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 @well-border;\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","//\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","//\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// 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;\n -webkit-overflow-scrolling: touch;\n\n // Prevent Chrome on Windows from adding a focus outline. For details, see\n // https://github.com/twbs/bootstrap/pull/10951.\n outline: 0;\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 position: relative;\n width: auto;\n margin: 10px;\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;\n background-color: @modal-backdrop-bg;\n // Fade for backdrop\n &.fade { .opacity(0); }\n &.in { .opacity(@modal-backdrop-opacity); }\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 &:extend(.clearfix all); // 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 (min-width: @screen-sm-min) {\n // Automatically set modal's width for larger viewports\n .modal-dialog {\n width: @modal-md;\n margin: 30px auto;\n }\n .modal-content {\n .box-shadow(0 5px 15px rgba(0,0,0,.5));\n }\n\n // Modal sizes\n .modal-sm { width: @modal-sm; }\n}\n\n@media (min-width: @screen-md-min) {\n .modal-lg { width: @modal-lg; }\n}\n","//\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(@tooltip-opacity); }\n &.top { margin-top: -3px; padding: @tooltip-arrow-width 0; }\n &.right { margin-left: 3px; padding: 0 @tooltip-arrow-width; }\n &.bottom { margin-top: 3px; padding: @tooltip-arrow-width 0; }\n &.left { margin-left: -3px; padding: 0 @tooltip-arrow-width; }\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: @tooltip-arrow-width;\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: @tooltip-arrow-width;\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: @tooltip-arrow-width;\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: @tooltip-arrow-width;\n border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\n border-bottom-color: @tooltip-arrow-color;\n }\n}\n","//\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: -@popover-arrow-width; }\n &.right { margin-left: @popover-arrow-width; }\n &.bottom { margin-top: @popover-arrow-width; }\n &.left { margin-left: -@popover-arrow-width; }\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","//\n// Responsive: Utility classes\n// --------------------------------------------------\n\n\n// IE10 in Windows (Phone) 8\n//\n// Support for responsive views via media queries is kind of borked in IE10, for\n// Surface/desktop in split view and for Windows Phone 8. This particular fix\n// must be accompanied by a snippet of JavaScript to sniff the user agent and\n// apply some conditional CSS to *only* the Surface/desktop Windows 8. Look at\n// our Getting Started page for more information on this bug.\n//\n// For more information, see the following:\n//\n// Issue: https://github.com/twbs/bootstrap/issues/10497\n// Docs: http://getbootstrap.com/getting-started/#browsers\n// Source: http://timkadlec.com/2012/10/ie10-snap-mode-and-responsive-design/\n\n@-ms-viewport {\n width: device-width;\n}\n\n\n// Visibility utilities\n.visible-xs,\n.visible-sm,\n.visible-md,\n.visible-lg {\n .responsive-invisibility();\n}\n\n.visible-xs {\n @media (max-width: @screen-xs-max) {\n .responsive-visibility();\n }\n}\n.visible-sm {\n @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n .responsive-visibility();\n }\n}\n.visible-md {\n @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n .responsive-visibility();\n }\n}\n.visible-lg {\n @media (min-width: @screen-lg-min) {\n .responsive-visibility();\n }\n}\n\n.hidden-xs {\n @media (max-width: @screen-xs-max) {\n .responsive-invisibility();\n }\n}\n.hidden-sm {\n @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n .responsive-invisibility();\n }\n}\n.hidden-md {\n @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n .responsive-invisibility();\n }\n}\n.hidden-lg {\n @media (min-width: @screen-lg-min) {\n .responsive-invisibility();\n }\n}\n\n\n// Print utilities\n//\n// Media queries are placed on the inside to be mixin-friendly.\n\n.visible-print {\n .responsive-invisibility();\n\n @media print {\n .responsive-visibility();\n }\n}\n\n.hidden-print {\n @media print {\n .responsive-invisibility();\n }\n}\n"]} \ No newline at end of file +{ + "version": 3, + "sources": [ + "less/normalize.less", + "less/print.less", + "less/scaffolding.less", + "less/mixins.less", + "less/variables.less", + "less/thumbnails.less", + "less/carousel.less", + "less/type.less", + "less/code.less", + "less/grid.less", + "less/tables.less", + "less/forms.less", + "less/buttons.less", + "less/button-groups.less", + "less/component-animations.less", + "less/glyphicons.less", + "less/dropdowns.less", + "less/input-groups.less", + "less/navs.less", + "less/navbar.less", + "less/utilities.less", + "less/breadcrumbs.less", + "less/pagination.less", + "less/pager.less", + "less/labels.less", + "less/badges.less", + "less/jumbotron.less", + "less/alerts.less", + "less/progress-bars.less", + "less/media.less", + "less/list-group.less", + "less/panels.less", + "less/wells.less", + "less/close.less", + "less/modals.less", + "less/tooltip.less", + "less/popovers.less", + "less/responsive-utilities.less" + ], + "names": [], + "mappings": "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", + "sourcesContent": [ + "/*! normalize.css v3.0.0 | MIT License | git.io/normalize */\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 -ms-text-size-adjust: 100%; // 2\n -webkit-text-size-adjust: 100%; // 2\n}\n\n//\n// Remove default margin.\n//\n\nbody {\n margin: 0;\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// 1. Correct `inline-block` display not defined in IE 8/9.\n// 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.\n//\n\naudio,\ncanvas,\nprogress,\nvideo {\n display: inline-block; // 1\n vertical-align: baseline; // 2\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 `[hidden]` styling not present in IE 8/9.\n// Hide the `template` element in IE, Safari, and Firefox < 22.\n//\n\n[hidden],\ntemplate {\n display: none;\n}\n\n// Links\n// ==========================================================================\n\n//\n// Remove the gray background color from active links in IE 10.\n//\n\na {\n background: transparent;\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// Text-level semantics\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 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.\n//\n\nmark {\n background: #ff0;\n color: #000;\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// 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// Grouping content\n// ==========================================================================\n\n//\n// Address margin not present in IE 8/9 and Safari 5.\n//\n\nfigure {\n margin: 1em 40px;\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// Contain overflow in all browsers.\n//\n\npre {\n overflow: auto;\n}\n\n//\n// Address odd `em`-unit font size rendering in all browsers.\n//\n\ncode,\nkbd,\npre,\nsamp {\n font-family: monospace, monospace;\n font-size: 1em;\n}\n\n// Forms\n// ==========================================================================\n\n//\n// Known limitation: by default, Chrome and Safari on OS X allow very limited\n// styling of `select`, unless a `border` property is set.\n//\n\n//\n// 1. Correct color not being inherited.\n// Known issue: affects color of disabled elements.\n// 2. Correct font properties not being inherited.\n// 3. Address margins set differently in Firefox 4+, Safari 5, and Chrome.\n//\n\nbutton,\ninput,\noptgroup,\nselect,\ntextarea {\n color: inherit; // 1\n font: inherit; // 2\n margin: 0; // 3\n}\n\n//\n// Address `overflow` set to `hidden` in IE 8/9/10.\n//\n\nbutton {\n overflow: visible;\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 Firefox, IE 8+, and Opera\n// Correct `select` style inheritance in Firefox.\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// 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// Address Firefox 4+ setting `line-height` on `input` using `!important` in\n// the UA stylesheet.\n//\n\ninput {\n line-height: normal;\n}\n\n//\n// It's recommended that you don't attempt to style these elements.\n// Firefox's implementation doesn't respect box-sizing, padding, or width.\n//\n// 1. Address box sizing set to `content-box` in IE 8/9/10.\n// 2. Remove excess padding in IE 8/9/10.\n//\n\ninput[type=\"checkbox\"],\ninput[type=\"radio\"] {\n box-sizing: border-box; // 1\n padding: 0; // 2\n}\n\n//\n// Fix the cursor style for Chrome's increment/decrement buttons. For certain\n// `font-size` values of the `input`, it causes the cursor style of the\n// decrement button to change from `default` to `text`.\n//\n\ninput[type=\"number\"]::-webkit-inner-spin-button,\ninput[type=\"number\"]::-webkit-outer-spin-button {\n height: auto;\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 and Chrome on OS X.\n// Safari (but not Chrome) clips the cancel button when the search input has\n// padding (and `textfield` appearance).\n//\n\ninput[type=\"search\"]::-webkit-search-cancel-button,\ninput[type=\"search\"]::-webkit-search-decoration {\n -webkit-appearance: none;\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// Remove default vertical scrollbar in IE 8/9.\n//\n\ntextarea {\n overflow: auto;\n}\n\n//\n// Don't inherit the `font-weight` (applied by a rule above).\n// NOTE: the default cannot safely be changed in Chrome and Safari on OS X.\n//\n\noptgroup {\n font-weight: bold;\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\ntd,\nth {\n padding: 0;\n}", + "//\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 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 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 // Chrome (OSX) fix for https://github.com/twbs/bootstrap/issues/11245\n // Once fixed, we can just straight up remove this.\n select {\n background: #fff !important;\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", + "//\n// Scaffolding\n// --------------------------------------------------\n\n\n// Reset the box-sizing\n//\n// Heads up! This reset may cause conflicts with some third-party widgets.\n// For recommendations on resolving such conflicts, see\n// http://getbootstrap.com/getting-started/#third-box-sizing\n* {\n .box-sizing(border-box);\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\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// Figures\n//\n// We reset this here because previously Normalize had no `figure` margins. This\n// ensures we don't break anyone's use of the element.\n\nfigure {\n margin: 0;\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", + "//\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;\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\n opacity: 1; } // See https://github.com/twbs/bootstrap/pull/11526\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//\n// Heads up! v3 launched with with only `.hide-text()`, but per our pattern for\n// mixins being reused as classes with the same name, this doesn't hold up. As\n// of v3.0.1 we have added `.text-hide()` and deprecated `.hide-text()`. Note\n// that we cannot chain the mixins together in Less, so they are repeated.\n//\n// Source: https://github.com/h5bp/html5-boilerplate/commit/aa0396eae757\n\n// Deprecated as of v3.0.1 (will be removed in v4)\n.hide-text() {\n font: ~\"0/0\" a;\n color: transparent;\n text-shadow: none;\n background-color: transparent;\n border: 0;\n}\n// New mixin to use as of v3.0.1\n.text-hide() {\n .hide-text();\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//\n// Note: Deprecated `.box-shadow()` as of v3.1.0 since all of Bootstrap's\n// supported browsers that have box shadow capabilities now support the\n// standard `box-shadow` property.\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-property(@transition-property) {\n -webkit-transition-property: @transition-property;\n transition-property: @transition-property;\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 only\n transform: rotate(@degrees);\n}\n.scale(@ratio; @ratio-y...) {\n -webkit-transform: scale(@ratio, @ratio-y);\n -ms-transform: scale(@ratio, @ratio-y); // IE9 only\n transform: scale(@ratio, @ratio-y);\n}\n.translate(@x; @y) {\n -webkit-transform: translate(@x, @y);\n -ms-transform: translate(@x, @y); // IE9 only\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.rotateX(@degrees) {\n -webkit-transform: rotateX(@degrees);\n -ms-transform: rotateX(@degrees); // IE9 only\n transform: rotateX(@degrees);\n}\n.rotateY(@degrees) {\n -webkit-transform: rotateY(@degrees);\n -ms-transform: rotateY(@degrees); // IE9 only\n transform: rotateY(@degrees);\n}\n.perspective(@perspective) {\n -webkit-perspective: @perspective;\n -moz-perspective: @perspective;\n perspective: @perspective;\n}\n.perspective-origin(@perspective) {\n -webkit-perspective-origin: @perspective;\n -moz-perspective-origin: @perspective;\n perspective-origin: @perspective;\n}\n.transform-origin(@origin) {\n -webkit-transform-origin: @origin;\n -moz-transform-origin: @origin;\n -ms-transform-origin: @origin; // IE9 only\n transform-origin: @origin;\n}\n\n// Animations\n.animation(@animation) {\n -webkit-animation: @animation;\n animation: @animation;\n}\n.animation-name(@name) {\n -webkit-animation-name: @name;\n animation-name: @name;\n}\n.animation-duration(@duration) {\n -webkit-animation-duration: @duration;\n animation-duration: @duration;\n}\n.animation-timing-function(@timing-function) {\n -webkit-animation-timing-function: @timing-function;\n animation-timing-function: @timing-function;\n}\n.animation-delay(@delay) {\n -webkit-animation-delay: @delay;\n animation-delay: @delay;\n}\n.animation-iteration-count(@iteration-count) {\n -webkit-animation-iteration-count: @iteration-count;\n animation-iteration-count: @iteration-count;\n}\n.animation-direction(@direction) {\n -webkit-animation-direction: @direction;\n animation-direction: @direction;\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.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 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-linear-gradient(left, color-stop(@start-color @start-percent), color-stop(@end-color @end-percent)); // Safari 5.1-6, Chrome 10+\n background-image: linear-gradient(to right, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\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-linear-gradient(top, @start-color @start-percent, @end-color @end-percent); // Safari 5.1-6, Chrome 10+\n background-image: linear-gradient(to bottom, @start-color @start-percent, @end-color @end-percent); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\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-6, Chrome 10+\n background-image: linear-gradient(@deg, @start-color, @end-color); // Standard, IE10, Firefox 16+, Opera 12.10+, Safari 7+, Chrome 26+\n }\n .horizontal-three-colors(@start-color: #00b3ee; @mid-color: #7a43b6; @color-stop: 50%; @end-color: #c3325f) {\n background-image: -webkit-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-linear-gradient(@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-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: rgba(255,255,255,.15); @angle: 45deg) {\n background-image: -webkit-linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 75%, transparent 75%, transparent);\n background-image: linear-gradient(@angle, @color 25%, transparent 25%, transparent 50%, @color 50%, @color 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\n & > .panel-heading {\n color: @heading-text-color;\n background-color: @heading-bg-color;\n border-color: @heading-border;\n\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\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) {\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 }\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 &.@{state}:hover > th {\n background-color: darken(@background, 5%);\n }\n }\n}\n\n// List Groups\n// -------------------------\n.list-group-item-variant(@state; @background; @color) {\n .list-group-item-@{state} {\n color: @color;\n background-color: @background;\n\n a& {\n color: @color;\n\n .list-group-item-heading { color: inherit; }\n\n &:hover,\n &:focus {\n color: @color;\n background-color: darken(@background, 5%);\n }\n &.active,\n &.active:hover,\n &.active:focus {\n color: #fff;\n background-color: @color;\n border-color: @color;\n }\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 .badge {\n color: @background;\n background-color: @color;\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// Contextual backgrounds\n// -------------------------\n.bg-variant(@color) {\n background-color: @color;\n a&:hover {\n background-color: darken(@color, 10%);\n }\n}\n\n// Typography\n// -------------------------\n.text-emphasis-variant(@color) {\n color: @color;\n a&:hover {\n color: darken(@color, 10%);\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();\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 table& { display: table; }\n tr& { display: table-row !important; }\n th&,\n td& { display: table-cell !important; }\n}\n\n.responsive-invisibility() {\n display: none !important;\n}\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 &:extend(.clearfix all);\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 &:extend(.clearfix all);\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 min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n}\n.make-xs-column-offset(@columns) {\n @media (min-width: @screen-xs-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-xs-column-push(@columns) {\n @media (min-width: @screen-xs-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-xs-column-pull(@columns) {\n @media (min-width: @screen-xs-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n\n// Generate the small columns\n.make-sm-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-sm-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-offset(@columns) {\n @media (min-width: @screen-sm-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-push(@columns) {\n @media (min-width: @screen-sm-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-sm-column-pull(@columns) {\n @media (min-width: @screen-sm-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n\n// Generate the medium columns\n.make-md-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-md-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-offset(@columns) {\n @media (min-width: @screen-md-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-push(@columns) {\n @media (min-width: @screen-md-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-md-column-pull(@columns) {\n @media (min-width: @screen-md-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n\n// Generate the large columns\n.make-lg-column(@columns; @gutter: @grid-gutter-width) {\n position: relative;\n min-height: 1px;\n padding-left: (@gutter / 2);\n padding-right: (@gutter / 2);\n\n @media (min-width: @screen-lg-min) {\n float: left;\n width: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-offset(@columns) {\n @media (min-width: @screen-lg-min) {\n margin-left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-push(@columns) {\n @media (min-width: @screen-lg-min) {\n left: percentage((@columns / @grid-columns));\n }\n}\n.make-lg-column-pull(@columns) {\n @media (min-width: @screen-lg-min) {\n right: percentage((@columns / @grid-columns));\n }\n}\n\n\n// Framework grid generation\n//\n// Used only by Bootstrap to generate the correct number of grid classes given\n// any value of `@grid-columns`.\n\n.make-grid-columns() {\n // Common styles for all sizes of grid columns, widths 1-12\n .col(@index) when (@index = 1) { // initial\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general; \"=<\" isn't a typo\n @item: ~\".col-xs-@{index}, .col-sm-@{index}, .col-md-@{index}, .col-lg-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\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 .col(1); // kickstart it\n}\n\n.float-grid-columns(@class) {\n .col(@index) when (@index = 1) { // initial\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), @item);\n }\n .col(@index, @list) when (@index =< @grid-columns) { // general\n @item: ~\".col-@{class}-@{index}\";\n .col((@index + 1), ~\"@{list}, @{item}\");\n }\n .col(@index, @list) when (@index > @grid-columns) { // terminal\n @{list} {\n float: left;\n }\n }\n .col(1); // kickstart it\n}\n\n.calc-grid-column(@index, @class, @type) when (@type = width) and (@index > 0) {\n .col-@{class}-@{index} {\n width: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = push) {\n .col-@{class}-push-@{index} {\n left: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = pull) {\n .col-@{class}-pull-@{index} {\n right: percentage((@index / @grid-columns));\n }\n}\n.calc-grid-column(@index, @class, @type) when (@type = offset) {\n .col-@{class}-offset-@{index} {\n margin-left: percentage((@index / @grid-columns));\n }\n}\n\n// Basic looping in LESS\n.loop-grid-columns(@index, @class, @type) when (@index >= 0) {\n .calc-grid-column(@index, @class, @type);\n // next iteration\n .loop-grid-columns((@index - 1), @class, @type);\n}\n\n// Create grid for specific class\n.make-grid(@class) {\n .float-grid-columns(@class);\n .loop-grid-columns(@grid-columns, @class, width);\n .loop-grid-columns(@grid-columns, @class, pull);\n .loop-grid-columns(@grid-columns, @class, push);\n .loop-grid-columns(@grid-columns, @class, offset);\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 .radio,\n .checkbox,\n .radio-inline,\n .checkbox-inline {\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 // Optional feedback icon\n .form-control-feedback {\n color: @text-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. `` background color\n@input-bg: #fff;\n//** `` background color\n@input-bg-disabled: @gray-lighter;\n\n//** Text color for ``s\n@input-color: @gray;\n//** `` border color\n@input-border: #ccc;\n//** `` border radius\n@input-border-radius: @border-radius-base;\n//** Border color for inputs on focus\n@input-border-focus: #66afe9;\n\n//** Placeholder text color\n@input-color-placeholder: @gray-light;\n\n//** Default `.form-control` height\n@input-height-base: (@line-height-computed + (@padding-base-vertical * 2) + 2);\n//** Large `.form-control` height\n@input-height-large: (ceil(@font-size-large * @line-height-large) + (@padding-large-vertical * 2) + 2);\n//** Small `.form-control` height\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//** Background color for textual input addons\n@input-group-addon-bg: @gray-lighter;\n//** Border color for textual input addons\n@input-group-addon-border-color: @input-border;\n\n\n//== Dropdowns\n//\n//## Dropdown menu container and contents.\n\n//** Background for the dropdown menu.\n@dropdown-bg: #fff;\n//** Dropdown menu `border-color`.\n@dropdown-border: rgba(0,0,0,.15);\n//** Dropdown menu `border-color` **for IE8**.\n@dropdown-fallback-border: #ccc;\n//** Divider color for between dropdown items.\n@dropdown-divider-bg: #e5e5e5;\n\n//** Dropdown link text color.\n@dropdown-link-color: @gray-dark;\n//** Hover color for dropdown links.\n@dropdown-link-hover-color: darken(@gray-dark, 5%);\n//** Hover background for dropdown links.\n@dropdown-link-hover-bg: #f5f5f5;\n\n//** Active dropdown menu item text color.\n@dropdown-link-active-color: @component-active-color;\n//** Active dropdown menu item background color.\n@dropdown-link-active-bg: @component-active-bg;\n\n//** Disabled dropdown menu item background color.\n@dropdown-link-disabled-color: @gray-light;\n\n//** Text color for headers within dropdown menus.\n@dropdown-header-color: @gray-light;\n\n// Note: Deprecated @dropdown-caret-color as of v3.1.0\n@dropdown-caret-color: #000;\n\n\n//-- Z-index master list\n//\n// Warning: Avoid customizing these values. They're used for a bird's eye view\n// of components dependent on the z-axis and are designed to all work together.\n//\n// Note: These variables are not generated into the Customizer.\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\n//== Media queries breakpoints\n//\n//## Define the breakpoints at which your layout will change, adapting to different screen sizes.\n\n// Extra small screen / phone\n// Note: Deprecated @screen-xs and @screen-phone as of v3.0.1\n@screen-xs: 480px;\n@screen-xs-min: @screen-xs;\n@screen-phone: @screen-xs-min;\n\n// Small screen / tablet\n// Note: Deprecated @screen-sm and @screen-tablet as of v3.0.1\n@screen-sm: 768px;\n@screen-sm-min: @screen-sm;\n@screen-tablet: @screen-sm-min;\n\n// Medium screen / desktop\n// Note: Deprecated @screen-md and @screen-desktop as of v3.0.1\n@screen-md: 992px;\n@screen-md-min: @screen-md;\n@screen-desktop: @screen-md-min;\n\n// Large screen / wide desktop\n// Note: Deprecated @screen-lg and @screen-lg-desktop as of v3.0.1\n@screen-lg: 1200px;\n@screen-lg-min: @screen-lg;\n@screen-lg-desktop: @screen-lg-min;\n\n// So media queries don't overlap when required, provide a maximum\n@screen-xs-max: (@screen-sm-min - 1);\n@screen-sm-max: (@screen-md-min - 1);\n@screen-md-max: (@screen-lg-min - 1);\n\n\n//== Grid system\n//\n//## Define your custom responsive grid.\n\n//** Number of columns in the grid.\n@grid-columns: 12;\n//** Padding between columns. Gets divided in half for the left and right.\n@grid-gutter-width: 30px;\n// Navbar collapse\n//** Point at which the navbar becomes uncollapsed.\n@grid-float-breakpoint: @screen-sm-min;\n//** Point at which the navbar begins collapsing.\n@grid-float-breakpoint-max: (@grid-float-breakpoint - 1);\n\n\n//== Container sizes\n//\n//## Define the maximum width of `.container` for different screen sizes.\n\n// Small screen / tablet\n@container-tablet: ((720px + @grid-gutter-width));\n//** For `@screen-sm-min` and up.\n@container-sm: @container-tablet;\n\n// Medium screen / desktop\n@container-desktop: ((940px + @grid-gutter-width));\n//** For `@screen-md-min` and up.\n@container-md: @container-desktop;\n\n// Large screen / wide desktop\n@container-large-desktop: ((1140px + @grid-gutter-width));\n//** For `@screen-lg-min` and up.\n@container-lg: @container-large-desktop;\n\n\n//== Navbar\n//\n//##\n\n// Basics of a navbar\n@navbar-height: 50px;\n@navbar-margin-bottom: @line-height-computed;\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@navbar-collapse-max-height: 340px;\n\n@navbar-default-color: #777;\n@navbar-default-bg: #f8f8f8;\n@navbar-default-border: darken(@navbar-default-bg, 6.5%);\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-brand-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: #888;\n@navbar-default-toggle-border-color: #ddd;\n\n\n// Inverted navbar\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 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\n//=== Shared nav styles\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\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-border-radius: @border-radius-base;\n@nav-pills-active-link-hover-bg: @component-active-bg;\n@nav-pills-active-link-hover-color: @component-active-color;\n\n\n//== Pagination\n//\n//##\n\n@pagination-color: @link-color;\n@pagination-bg: #fff;\n@pagination-border: #ddd;\n\n@pagination-hover-color: @link-hover-color;\n@pagination-hover-bg: @gray-lighter;\n@pagination-hover-border: #ddd;\n\n@pagination-active-color: #fff;\n@pagination-active-bg: @brand-primary;\n@pagination-active-border: @brand-primary;\n\n@pagination-disabled-color: @gray-light;\n@pagination-disabled-bg: #fff;\n@pagination-disabled-border: #ddd;\n\n\n//== Pager\n//\n//##\n\n@pager-bg: @pagination-bg;\n@pager-border: @pagination-border;\n@pager-border-radius: 15px;\n\n@pager-hover-bg: @pagination-hover-bg;\n\n@pager-active-bg: @pagination-active-bg;\n@pager-active-color: @pagination-active-color;\n\n@pager-disabled-color: @pagination-disabled-color;\n\n\n//== Jumbotron\n//\n//##\n\n@jumbotron-padding: 30px;\n@jumbotron-color: inherit;\n@jumbotron-bg: @gray-lighter;\n@jumbotron-heading-color: inherit;\n@jumbotron-font-size: ceil((@font-size-base * 1.5));\n\n\n//== Form states and alerts\n//\n//## Define colors for form feedback states and, by default, alerts.\n\n@state-success-text: #3c763d;\n@state-success-bg: #dff0d8;\n@state-success-border: darken(spin(@state-success-bg, -10), 5%);\n\n@state-info-text: #31708f;\n@state-info-bg: #d9edf7;\n@state-info-border: darken(spin(@state-info-bg, -10), 7%);\n\n@state-warning-text: #8a6d3b;\n@state-warning-bg: #fcf8e3;\n@state-warning-border: darken(spin(@state-warning-bg, -10), 5%);\n\n@state-danger-text: #a94442;\n@state-danger-bg: #f2dede;\n@state-danger-border: darken(spin(@state-danger-bg, -10), 5%);\n\n\n//== Tooltips\n//\n//##\n\n//** Tooltip max width\n@tooltip-max-width: 200px;\n//** Tooltip text color\n@tooltip-color: #fff;\n//** Tooltip background color\n@tooltip-bg: #000;\n@tooltip-opacity: .9;\n\n//** Tooltip arrow width\n@tooltip-arrow-width: 5px;\n//** Tooltip arrow color\n@tooltip-arrow-color: @tooltip-bg;\n\n\n//== Popovers\n//\n//##\n\n//** Popover body background color\n@popover-bg: #fff;\n//** Popover maximum width\n@popover-max-width: 276px;\n//** Popover border color\n@popover-border-color: rgba(0,0,0,.2);\n//** Popover fallback border color\n@popover-fallback-border-color: #ccc;\n\n//** Popover title background color\n@popover-title-bg: darken(@popover-bg, 3%);\n\n//** Popover arrow width\n@popover-arrow-width: 10px;\n//** Popover arrow color\n@popover-arrow-color: #fff;\n\n//** Popover outer arrow width\n@popover-arrow-outer-width: (@popover-arrow-width + 1);\n//** Popover outer arrow color\n@popover-arrow-outer-color: fadein(@popover-border-color, 5%);\n//** Popover outer arrow fallback color\n@popover-arrow-outer-fallback-color: darken(@popover-fallback-border-color, 20%);\n\n\n//== Labels\n//\n//##\n\n//** Default label background color\n@label-default-bg: @gray-light;\n//** Primary label background color\n@label-primary-bg: @brand-primary;\n//** Success label background color\n@label-success-bg: @brand-success;\n//** Info label background color\n@label-info-bg: @brand-info;\n//** Warning label background color\n@label-warning-bg: @brand-warning;\n//** Danger label background color\n@label-danger-bg: @brand-danger;\n\n//** Default label text color\n@label-color: #fff;\n//** Default text color of a linked label\n@label-link-hover-color: #fff;\n\n\n//== Modals\n//\n//##\n\n//** Padding applied to the modal body\n@modal-inner-padding: 20px;\n\n//** Padding applied to the modal title\n@modal-title-padding: 15px;\n//** Modal title line-height\n@modal-title-line-height: @line-height-base;\n\n//** Background color of modal content area\n@modal-content-bg: #fff;\n//** Modal content border color\n@modal-content-border-color: rgba(0,0,0,.2);\n//** Modal content border color **for IE8**\n@modal-content-fallback-border-color: #999;\n\n//** Modal backdrop background color\n@modal-backdrop-bg: #000;\n//** Modal backdrop opacity\n@modal-backdrop-opacity: .5;\n//** Modal header border color\n@modal-header-border-color: #e5e5e5;\n//** Modal footer border color\n@modal-footer-border-color: @modal-header-border-color;\n\n@modal-lg: 900px;\n@modal-md: 600px;\n@modal-sm: 300px;\n\n\n//== Alerts\n//\n//## Define alert colors, border radius, and padding.\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//##\n\n//** Background color of the whole progress component\n@progress-bg: #f5f5f5;\n//** Progress bar text color\n@progress-bar-color: #fff;\n\n//** Default progress bar color\n@progress-bar-bg: @brand-primary;\n//** Success progress bar color\n@progress-bar-success-bg: @brand-success;\n//** Warning progress bar color\n@progress-bar-warning-bg: @brand-warning;\n//** Danger progress bar color\n@progress-bar-danger-bg: @brand-danger;\n//** Info progress bar color\n@progress-bar-info-bg: @brand-info;\n\n\n//== List group\n//\n//##\n\n//** Background color on `.list-group-item`\n@list-group-bg: #fff;\n//** `.list-group-item` border color\n@list-group-border: #ddd;\n//** List group border radius\n@list-group-border-radius: @border-radius-base;\n\n//** Background color of single list elements on hover\n@list-group-hover-bg: #f5f5f5;\n//** Text color of active list elements\n@list-group-active-color: @component-active-color;\n//** Background color of active list elements\n@list-group-active-bg: @component-active-bg;\n//** Border color of active list elements\n@list-group-active-border: @list-group-active-bg;\n@list-group-active-text-color: lighten(@list-group-active-bg, 40%);\n\n@list-group-link-color: #555;\n@list-group-link-heading-color: #333;\n\n\n//== Panels\n//\n//##\n\n@panel-bg: #fff;\n@panel-body-padding: 15px;\n@panel-border-radius: @border-radius-base;\n\n//** Border color for elements within panels\n@panel-inner-border: #ddd;\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-info-text: @state-info-text;\n@panel-info-border: @state-info-border;\n@panel-info-heading-bg: @state-info-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\n//== Thumbnails\n//\n//##\n\n//** Padding around the thumbnail image\n@thumbnail-padding: 4px;\n//** Thumbnail background color\n@thumbnail-bg: @body-bg;\n//** Thumbnail border color\n@thumbnail-border: #ddd;\n//** Thumbnail border radius\n@thumbnail-border-radius: @border-radius-base;\n\n//** Custom text color for thumbnail captions\n@thumbnail-caption-color: @text-color;\n//** Padding around the thumbnail caption\n@thumbnail-caption-padding: 9px;\n\n\n//== Wells\n//\n//##\n\n@well-bg: #f5f5f5;\n@well-border: darken(@well-bg, 7%);\n\n\n//== Badges\n//\n//##\n\n@badge-color: #fff;\n//** Linked badge text color on hover\n@badge-link-hover-color: #fff;\n@badge-bg: @gray-light;\n\n//** Badge text color in active nav link\n@badge-active-color: @link-color;\n//** Badge background color in active nav link\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//##\n\n@breadcrumb-padding-vertical: 8px;\n@breadcrumb-padding-horizontal: 15px;\n//** Breadcrumb background color\n@breadcrumb-bg: #f5f5f5;\n//** Breadcrumb text color\n@breadcrumb-color: #ccc;\n//** Text color of current page in the breadcrumb\n@breadcrumb-active-color: @gray-light;\n//** Textual separator for between breadcrumb elements\n@breadcrumb-separator: \"/\";\n\n\n//== Carousel\n//\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//##\n\n@close-font-weight: bold;\n@close-color: #000;\n@close-text-shadow: 0 1px 0 #fff;\n\n\n//== Code\n//\n//##\n\n@code-color: #c7254e;\n@code-bg: #f9f2f4;\n\n@kbd-color: #fff;\n@kbd-bg: #333;\n\n@pre-bg: #f5f5f5;\n@pre-color: @gray-dark;\n@pre-border-color: #ccc;\n@pre-scrollable-max-height: 340px;\n\n\n//== Type\n//\n//##\n\n//** Text muted color\n@text-muted: @gray-light;\n//** Abbreviations and acronyms border color\n@abbr-border-color: @gray-light;\n//** Headings small color\n@headings-small-color: @gray-light;\n//** Blockquote small color\n@blockquote-small-color: @gray-light;\n//** Blockquote font size\n@blockquote-font-size: (@font-size-base * 1.25);\n//** Blockquote border color\n@blockquote-border-color: @gray-lighter;\n//** Page header border color\n@page-header-border-color: @gray-lighter;\n\n\n//== Miscellaneous\n//\n//##\n\n//** Horizontal line color.\n@hr-border: @gray-lighter;\n\n//** Horizontal offset for forms and lists.\n@component-offset-horizontal: 180px;\n", + "//\n// Thumbnails\n// --------------------------------------------------\n\n\n// Mixin and adjust the regular image class\n.thumbnail {\n display: block;\n padding: @thumbnail-padding;\n margin-bottom: @line-height-computed;\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 > img,\n a > img {\n &:extend(.img-responsive);\n margin-left: auto;\n margin-right: auto;\n }\n\n // Add a hover state for linked versions only\n a&:hover,\n a&:focus,\n a&.active {\n border-color: @link-color;\n }\n\n // Image captions\n .caption {\n padding: @thumbnail-caption-padding;\n color: @thumbnail-caption-color;\n }\n}\n", + "//\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 &:extend(.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 outline: none;\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 z-index: 5;\n display: inline-block;\n }\n .icon-prev,\n .glyphicon-chevron-left {\n left: 50%;\n }\n .icon-next,\n .glyphicon-chevron-right {\n right: 50%;\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 // IE8-9 hack for event handling\n //\n // Internet Explorer 8-9 does not support clicks on elements without a set\n // `background-color`. We cannot use `filter` since that's not viewed as a\n // background color by the browser. Thus, a hack is needed.\n //\n // For IE8, we set solid black as it doesn't support `rgba()`. For IE9, we\n // set alpha transparency for the best results possible.\n background-color: #000 \\9; // IE8\n background-color: rgba(0,0,0,0); // IE9\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-sm-min) {\n\n // Scale up the controls a smidge\n .carousel-control {\n .glyphicon-chevron-left,\n .glyphicon-chevron-right,\n .icon-prev,\n .icon-next {\n width: 30px;\n height: 30px;\n margin-top: -15px;\n margin-left: -15px;\n font-size: 30px;\n }\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", + "//\n// Typography\n// --------------------------------------------------\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 color: @headings-color;\n\n small,\n .small {\n font-weight: normal;\n line-height: 1;\n color: @headings-small-color;\n }\n}\n\nh1, .h1,\nh2, .h2,\nh3, .h3 {\n margin-top: @line-height-computed;\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 65%;\n }\n}\nh4, .h4,\nh5, .h5,\nh6, .h6 {\n margin-top: (@line-height-computed / 2);\n margin-bottom: (@line-height-computed / 2);\n\n small,\n .small {\n font-size: 75%;\n }\n}\n\nh1, .h1 { font-size: @font-size-h1; }\nh2, .h2 { font-size: @font-size-h2; }\nh3, .h3 { font-size: @font-size-h3; }\nh4, .h4 { font-size: @font-size-h4; }\nh5, .h5 { font-size: @font-size-h5; }\nh6, .h6 { font-size: @font-size-h6; }\n\n\n// Body text\n// -------------------------\n\np {\n margin: 0 0 (@line-height-computed / 2);\n}\n\n.lead {\n margin-bottom: @line-height-computed;\n font-size: floor((@font-size-base * 1.15));\n font-weight: 200;\n line-height: 1.4;\n\n @media (min-width: @screen-sm-min) {\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,\n.small { font-size: 85%; }\n\n// Undo browser default styling\ncite { font-style: normal; }\n\n// Alignment\n.text-left { text-align: left; }\n.text-right { text-align: right; }\n.text-center { text-align: center; }\n.text-justify { text-align: justify; }\n\n// Contextual colors\n.text-muted {\n color: @text-muted;\n}\n.text-primary {\n .text-emphasis-variant(@brand-primary);\n}\n.text-success {\n .text-emphasis-variant(@state-success-text);\n}\n.text-info {\n .text-emphasis-variant(@state-info-text);\n}\n.text-warning {\n .text-emphasis-variant(@state-warning-text);\n}\n.text-danger {\n .text-emphasis-variant(@state-danger-text);\n}\n\n// Contextual backgrounds\n// For now we'll leave these alongside the text classes until v4 when we can\n// safely shift things around (per SemVer rules).\n.bg-primary {\n // Given the contrast here, this is the only class to have its color inverted\n // automatically.\n color: #fff;\n .bg-variant(@brand-primary);\n}\n.bg-success {\n .bg-variant(@state-success-bg);\n}\n.bg-info {\n .bg-variant(@state-info-bg);\n}\n.bg-warning {\n .bg-variant(@state-warning-bg);\n}\n.bg-danger {\n .bg-variant(@state-danger-bg);\n}\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// 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\n// Inline turns list items into inline-block\n.list-inline {\n .list-unstyled();\n margin-left: -5px;\n\n > li {\n display: inline-block;\n padding-left: 5px;\n padding-right: 5px;\n }\n}\n\n// Description Lists\ndl {\n margin-top: 0; // Remove browser default\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 &:extend(.clearfix all); // 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// Add 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}\n.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 font-size: @blockquote-font-size;\n border-left: 5px solid @blockquote-border-color;\n\n p,\n ul,\n ol {\n &:last-child {\n margin-bottom: 0;\n }\n }\n\n // Note: Deprecated small and .small as of v3.1.0\n // Context: https://github.com/twbs/bootstrap/issues/11660\n footer,\n small,\n .small {\n display: block;\n font-size: 80%; // back to default font-size\n line-height: @line-height-base;\n color: @blockquote-small-color;\n\n &:before {\n content: '\\2014 \\00A0'; // em dash, nbsp\n }\n }\n}\n\n// Opposite alignment of blockquote\n//\n// Heads up: `blockquote.pull-right` has been deprecated as of v3.1.0.\n.blockquote-reverse,\nblockquote.pull-right {\n padding-right: 15px;\n padding-left: 0;\n border-right: 5px solid @blockquote-border-color;\n border-left: 0;\n text-align: right;\n\n // Account for citation\n footer,\n small,\n .small {\n &:before { content: ''; }\n &:after {\n content: '\\00A0 \\2014'; // nbsp, em dash\n }\n }\n}\n\n// Quotes\nblockquote:before,\nblockquote:after {\n content: \"\";\n}\n\n// Addresses\naddress {\n margin-bottom: @line-height-computed;\n font-style: normal;\n line-height: @line-height-base;\n}\n", + "//\n// Code (inline and block)\n// --------------------------------------------------\n\n\n// Inline and block code styles\ncode,\nkbd,\npre,\nsamp {\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// User input typically entered via keyboard\nkbd {\n padding: 2px 4px;\n font-size: 90%;\n color: @kbd-color;\n background-color: @kbd-bg;\n border-radius: @border-radius-small;\n box-shadow: inset 0 -1px 0 rgba(0,0,0,.25);\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 // 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-radius: 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", + "//\n// Grid system\n// --------------------------------------------------\n\n\n// Container widths\n//\n// Set the container width, and override it for fixed navbars in media queries.\n\n.container {\n .container-fixed();\n\n @media (min-width: @screen-sm-min) {\n width: @container-sm;\n }\n @media (min-width: @screen-md-min) {\n width: @container-md;\n }\n @media (min-width: @screen-lg-min) {\n width: @container-lg;\n }\n}\n\n\n// Fluid container\n//\n// Utilizes the mixin meant for fixed width containers, but without any defined\n// width for fluid, full width layouts.\n\n.container-fluid {\n .container-fixed();\n}\n\n\n// Row\n//\n// Rows contain and clear the floats of your columns.\n\n.row {\n .make-row();\n}\n\n\n// Columns\n//\n// Common styles for small and large grid columns\n\n.make-grid-columns();\n\n\n// Extra small grid\n//\n// Columns, offsets, pushes, and pulls for extra small devices like\n// smartphones.\n\n.make-grid(xs);\n\n\n// Small grid\n//\n// Columns, offsets, pushes, and pulls for the small device range, from phones\n// to tablets.\n\n@media (min-width: @screen-sm-min) {\n .make-grid(sm);\n}\n\n\n// Medium grid\n//\n// Columns, offsets, pushes, and pulls for the desktop device range.\n\n@media (min-width: @screen-md-min) {\n .make-grid(md);\n}\n\n\n// Large grid\n//\n// Columns, offsets, pushes, and pulls for the large desktop device range.\n\n@media (min-width: @screen-lg-min) {\n .make-grid(lg);\n}\n", + "//\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,\n > 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 > tr {\n > th,\n > td {\n border-bottom-width: 2px;\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 > tr:nth-child(odd) {\n > td,\n > th {\n background-color: @table-bg-accent;\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 > tr:hover {\n > td,\n > th {\n background-color: @table-bg-hover;\n }\n }\n}\n\n\n// Table cell sizing\n//\n// Reset default table behavior\n\ntable col[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9/10 (see https://github.com/twbs/bootstrap/issues/11623)\n float: none;\n display: table-column;\n}\ntable {\n td,\n th {\n &[class*=\"col-\"] {\n position: static; // Prevent border hiding in Firefox and IE9/10 (see https://github.com/twbs/bootstrap/issues/11623)\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// Generate the contextual variants\n.table-row-variant(active; @table-bg-active);\n.table-row-variant(success; @state-success-bg);\n.table-row-variant(info; @state-info-bg);\n.table-row-variant(warning; @state-warning-bg);\n.table-row-variant(danger; @state-danger-bg);\n\n\n// Responsive tables\n//\n// Wrap your tables in `.table-responsive` 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-xs-max) {\n .table-responsive {\n width: 100%;\n margin-bottom: (@line-height-computed * 0.75);\n overflow-y: hidden;\n overflow-x: scroll;\n -ms-overflow-style: -ms-autohiding-scrollbar;\n border: 1px solid @table-border-color;\n -webkit-overflow-scrolling: touch;\n\n // Tighten up spacing\n > .table {\n margin-bottom: 0;\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 }\n\n // Only nuke the last row's bottom-border in `tbody` and `tfoot` since\n // chances are there will be only one `tr` in a `thead` and that would\n // remove the border altogether.\n > tbody,\n > tfoot {\n > tr:last-child {\n > th,\n > td {\n border-bottom: 0;\n }\n }\n }\n\n }\n }\n}\n", + "//\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 // Chrome and Firefox set a `min-width: -webkit-min-content;` on fieldsets,\n // so we reset that to ensure it behaves more like a standard block element.\n // See https://github.com/twbs/bootstrap/issues/12359.\n min-width: 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// While most of our form styles require extra classes, some basic normalization\n// is required to ensure optimum display with or without those classes to better\n// address browser inconsistencies.\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 file controls to match text inputs\ninput[type=\"file\"] {\n display: block;\n}\n\n// Make range inputs behave like textual form controls\ninput[type=\"range\"] {\n display: block;\n width: 100%;\n}\n\n// Make multiple select elements height not fixed\nselect[multiple],\nselect[size] {\n height: auto;\n}\n\n// Focus for file, radio, and checkbox\ninput[type=\"file\"]:focus,\ninput[type=\"radio\"]:focus,\ninput[type=\"checkbox\"]:focus {\n .tab-focus();\n}\n\n// Adjust output element\noutput {\n display: block;\n padding-top: (@padding-base-vertical + 1);\n font-size: @font-size-base;\n line-height: @line-height-base;\n color: @input-color;\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 background-color: @input-bg;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\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 // Placeholder\n .placeholder();\n\n // Disabled and read-only inputs\n //\n // HTML5 says that controls under a fieldset > legend:first-child won't be\n // disabled if the fieldset is disabled. Due to implementation difficulty, we\n // 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 opacity: 1; // iOS fix for unreadable disabled content\n }\n\n // Reset height for `textarea`s\n textarea& {\n height: auto;\n }\n}\n\n\n// Search inputs in iOS\n//\n// This overrides the extra rounded corners on search inputs in iOS so that our\n// `.form-control` class can properly style them. Note that this cannot simply\n// be added to `.form-control` as it's not specific enough. For details, see\n// https://github.com/twbs/bootstrap/issues/11586.\n\ninput[type=\"search\"] {\n -webkit-appearance: none;\n}\n\n\n// Special styles for iOS date input\n//\n// In Mobile Safari, date inputs require a pixel line-height that matches the\n// given height of the input.\n\ninput[type=\"date\"] {\n line-height: @input-height-base;\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 label {\n display: inline;\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\n// Form control sizing\n//\n// Build on `.form-control` with modifier classes to decrease or increase the\n// height and font-size of form controls.\n\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.has-feedback {\n // Enable absolute positioning\n position: relative;\n\n // Ensure icons don't overlap text\n .form-control {\n padding-right: (@input-height-base * 1.25);\n }\n\n // Feedback icon (requires .glyphicon classes)\n .form-control-feedback {\n position: absolute;\n top: (@line-height-computed + 5); // Height of the `label` and its margin\n right: 0;\n display: block;\n width: @input-height-base;\n height: @input-height-base;\n line-height: @input-height-base;\n text-align: center;\n }\n}\n\n// Feedback states\n.has-success {\n .form-control-validation(@state-success-text; @state-success-text; @state-success-bg);\n}\n.has-warning {\n .form-control-validation(@state-warning-text; @state-warning-text; @state-warning-bg);\n}\n.has-error {\n .form-control-validation(@state-danger-text; @state-danger-text; @state-danger-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}\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-sm-min) {\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 width: auto; // Prevent labels from stacking above inputs in `.form-group`\n vertical-align: middle;\n }\n // Input groups need that 100% width though\n .input-group > .form-control {\n width: 100%;\n }\n\n .control-label {\n margin-bottom: 0;\n vertical-align: middle;\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 vertical-align: middle;\n }\n .radio input[type=\"radio\"],\n .checkbox input[type=\"checkbox\"] {\n float: none;\n margin-left: 0;\n }\n\n // Validation states\n //\n // Reposition the icon because it's now within a grid column and columns have\n // `position: relative;` on them. Also accounts for the grid gutter padding.\n .has-feedback .form-control-feedback {\n top: 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 // Account for padding we're adding to ensure the alignment and of help text\n // and other content below items\n .radio,\n .checkbox {\n min-height: (@line-height-computed + (@padding-base-vertical + 1));\n }\n\n // Make form groups behave like rows\n .form-group {\n .make-row();\n }\n\n .form-control-static {\n padding-top: (@padding-base-vertical + 1);\n }\n\n // Only right align form labels here when the columns stop stacking\n @media (min-width: @screen-sm-min) {\n .control-label {\n text-align: right;\n }\n }\n\n // Validation states\n //\n // Reposition the icon because it's now within a grid column and columns have\n // `position: relative;` on them. Also accounts for the grid gutter padding.\n .has-feedback .form-control-feedback {\n top: 0;\n right: (@grid-gutter-width / 2);\n }\n}\n", + "//\n// Buttons\n// --------------------------------------------------\n\n\n// Base styles\n// --------------------------------------------------\n\n.btn {\n display: inline-block;\n margin-bottom: 0; // For input.btn\n font-weight: @btn-font-weight;\n text-align: center;\n vertical-align: middle;\n cursor: pointer;\n background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid transparent;\n white-space: nowrap;\n .button-size(@padding-base-vertical; @padding-base-horizontal; @font-size-base; @line-height-base; @border-radius-base);\n .user-select(none);\n\n &,\n &:active,\n &.active {\n &:focus {\n .tab-focus();\n }\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// 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// 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// 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\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 // 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 .button-size(@padding-xs-vertical; @padding-xs-horizontal; @font-size-small; @line-height-small; @border-radius-small);\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", + "//\n// Button groups\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 margin-left: -5px; // Offset the first child's margin\n &:extend(.clearfix all);\n\n .btn-group,\n .input-group {\n float: left;\n }\n > .btn,\n > .btn-group,\n > .input-group {\n margin-left: 5px;\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 { &: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 .box-shadow(inset 0 3px 5px rgba(0,0,0,.125));\n\n // Show no shadow for `.btn-link` since it has no other button styles.\n &.btn-link {\n .box-shadow(none);\n }\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 > .btn-group > .btn {\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 &:extend(.clearfix all);\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:not(:last-child) {\n > .btn:last-child,\n > .dropdown-toggle {\n .border-bottom-radius(0);\n }\n}\n.btn-group-vertical > .btn-group:last-child:not(:first-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 > .btn-group {\n float: none;\n display: table-cell;\n width: 1%;\n }\n > .btn-group .btn {\n width: 100%;\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", + "//\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", + "//\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// Star\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#@{icon-font-svg-id}') 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 -moz-osx-font-smoothing: grayscale;\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-lock { &:before { content: \"\\e033\"; } }\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-bookmark { &:before { content: \"\\e044\"; } }\n.glyphicon-print { &:before { content: \"\\e045\"; } }\n.glyphicon-camera { &:before { content: \"\\e046\"; } }\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-fire { &:before { content: \"\\e104\"; } }\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-calendar { &:before { content: \"\\e109\"; } }\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-bell { &:before { content: \"\\e123\"; } }\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-wrench { &:before { content: \"\\e136\"; } }\n.glyphicon-tasks { &:before { content: \"\\e137\"; } }\n.glyphicon-filter { &:before { content: \"\\e138\"; } }\n.glyphicon-briefcase { &:before { content: \"\\e139\"; } }\n.glyphicon-fullscreen { &:before { content: \"\\e140\"; } }\n.glyphicon-dashboard { &:before { content: \"\\e141\"; } }\n.glyphicon-paperclip { &:before { content: \"\\e142\"; } }\n.glyphicon-heart-empty { &:before { content: \"\\e143\"; } }\n.glyphicon-link { &:before { content: \"\\e144\"; } }\n.glyphicon-phone { &:before { content: \"\\e145\"; } }\n.glyphicon-pushpin { &:before { content: \"\\e146\"; } }\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", + "//\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;\n border-right: @caret-width-base solid transparent;\n border-left: @caret-width-base solid transparent;\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 //\n // Deprecated as of 3.1.0 in favor of `.dropdown-menu-[dir]`\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// Menu positioning\n//\n// Add extra class to `.dropdown-menu` to flip the alignment of the dropdown\n// menu with the parent.\n.dropdown-menu-right {\n left: auto; // Reset the default from `.dropdown-menu`\n right: 0;\n}\n// With v3, we enabled auto-flipping if you have a dropdown within a right\n// aligned nav component. To enable the undoing of that, we provide an override\n// to restore the default dropdown menu alignment.\n//\n// This is only for left-aligning a dropdown menu within a `.navbar-right` or\n// `.pull-right` nav component.\n.dropdown-menu-left {\n left: 0;\n right: auto;\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 border-top: 0;\n border-bottom: @caret-width-base solid;\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 .dropdown-menu-right();\n }\n // Necessary for overrides of the default right aligned menu.\n // Will remove come v4 in all likelihood.\n .dropdown-menu-left {\n .dropdown-menu-left();\n }\n }\n}\n\n", + "//\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 &[class*=\"col-\"] {\n float: none;\n padding-left: 0;\n padding-right: 0;\n }\n\n .form-control {\n // Ensure that the input is always above the *appended* addon button for\n // proper border colors.\n position: relative;\n z-index: 2;\n\n // IE9 fubars the placeholder attribute in text inputs and the arrows on\n // select elements in input groups. To fix it, we float the input. Details:\n // https://github.com/twbs/bootstrap/issues/11561#issuecomment-28936855\n float: left;\n\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 color: @input-color;\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 > .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-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-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 // Jankily prevent input button groups from wrapping with `white-space` and\n // `font-size` in combination with `inline-block` on buttons.\n font-size: 0;\n white-space: nowrap;\n\n // Negative margin for spacing, position for bringing hovered/focused/actived\n // element above the siblings.\n > .btn {\n position: relative;\n + .btn {\n margin-left: -1px;\n }\n // Bring the \"active\" button to the front\n &:hover,\n &:focus,\n &:active {\n z-index: 2;\n }\n }\n\n // Negative margin to only have a 1px border between the two\n &:first-child {\n > .btn,\n > .btn-group {\n margin-right: -1px;\n }\n }\n &:last-child {\n > .btn,\n > .btn-group {\n margin-left: -1px;\n }\n }\n}\n", + "//\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 &:extend(.clearfix all);\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 // Nav dividers (deprecated with v3.0.1)\n //\n // This should have been removed in v3 with the dropping of `.nav-list`, but\n // we missed it. We don't currently support this anywhere, but in the interest\n // of maintaining backward compatibility in case you use it, it's deprecated.\n .nav-divider {\n .nav-divider();\n }\n\n // Prevent IE8 from misplacing imgs\n //\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 its :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: @nav-pills-border-radius;\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 margin-bottom: 5px;\n }\n }\n\n > .dropdown .dropdown-menu {\n top: auto;\n left: auto;\n }\n\n @media (min-width: @screen-sm-min) {\n > li {\n display: table-cell;\n width: 1%;\n > a {\n margin-bottom: 0;\n }\n }\n }\n}\n\n// Move borders to anchors instead of bottom of list\n//\n// Mixin for adding on top the shared `.nav-justified` styles for our tabs\n.nav-tabs-justified {\n border-bottom: 0;\n\n > li > a {\n // Override margin from .nav-tabs\n margin-right: 0;\n border-radius: @border-radius-base;\n }\n\n > .active > a,\n > .active > a:hover,\n > .active > a:focus {\n border: 1px solid @nav-tabs-justified-link-border-color;\n }\n\n @media (min-width: @screen-sm-min) {\n > li > a {\n border-bottom: 1px solid @nav-tabs-justified-link-border-color;\n border-radius: @border-radius-base @border-radius-base 0 0;\n }\n > .active > a,\n > .active > a:hover,\n > .active > a:focus {\n border-bottom-color: @nav-tabs-justified-active-link-border-color;\n }\n }\n}\n\n\n// Tabbable tabs\n// -------------------------\n\n// Hide tabbable panes to start, show them when `.active`\n.tab-content {\n > .tab-pane {\n display: none;\n }\n > .active {\n display: block;\n }\n}\n\n\n// Dropdowns\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", + "//\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 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 &:extend(.clearfix all);\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 &:extend(.clearfix all);\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: @navbar-collapse-max-height;\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 &:extend(.clearfix all);\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 // Undo the collapse side padding for navbars with containers to ensure\n // alignment of right-aligned contents.\n .navbar-fixed-top &,\n .navbar-static-top &,\n .navbar-fixed-bottom & {\n padding-left: 0;\n padding-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,\n.container-fluid {\n > .navbar-header,\n > .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//\n// Navbar alignment options\n//\n// Display the navbar across the entirety 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 z-index: @zindex-navbar;\n border-width: 0 0 1px;\n\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 z-index: @zindex-navbar-fixed;\n\n // Undo the rounded corners\n @media (min-width: @grid-float-breakpoint) {\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; // override .navbar defaults\n border-width: 1px 0 0;\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 height: @navbar-height;\n\n &:hover,\n &:focus {\n text-decoration: none;\n }\n\n @media (min-width: @grid-float-breakpoint) {\n .navbar > .container &,\n .navbar > .container-fluid & {\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 background-image: none; // Reset unusual Firefox-on-Android default style; see https://github.com/necolas/normalize.css/issues/214\n border: 1px solid transparent;\n border-radius: @border-radius-base;\n\n // We remove the `outline` here, but later compensate by attaching `:hover`\n // styles to `:focus`.\n &:focus {\n outline: none;\n }\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 its 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: @grid-float-breakpoint-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-padding-vertical;\n padding-bottom: @navbar-padding-vertical;\n }\n }\n\n &.navbar-right:last-child {\n margin-right: -@navbar-padding-horizontal;\n }\n }\n}\n\n\n// Component alignment\n//\n// Repurpose the pull utilities as their own navbar utilities to avoid specificity\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: @grid-float-breakpoint-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 // Outdent the form if last child to line up with content down the page\n &.navbar-right:last-child {\n margin-right: -@navbar-padding-horizontal;\n }\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\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 &.btn-sm {\n .navbar-vertical-align(@input-height-small);\n }\n &.btn-xs {\n .navbar-vertical-align(22);\n }\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 .navbar-vertical-align(@line-height-computed);\n\n @media (min-width: @grid-float-breakpoint) {\n float: left;\n margin-left: @navbar-padding-horizontal;\n margin-right: @navbar-padding-horizontal;\n\n // Outdent the form if last child to line up with content down the page\n &.navbar-right:last-child {\n margin-right: 0;\n }\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: @navbar-default-border;\n }\n\n // Dropdown menu items\n .navbar-nav {\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 }\n }\n\n @media (max-width: @grid-float-breakpoint-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\n @media (max-width: @grid-float-breakpoint-max) {\n // Dropdowns get custom display\n .open .dropdown-menu {\n > .dropdown-header {\n border-color: @navbar-inverse-border;\n }\n .divider {\n background-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", + "//\n// Utility classes\n// --------------------------------------------------\n\n\n// Floats\n// -------------------------\n\n.clearfix {\n .clearfix();\n}\n.center-block {\n .center-block();\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// Note: Deprecated .hide in favor of .hidden or .sr-only (as appropriate) in v3.0.1\n.hide {\n display: none !important;\n}\n.show {\n display: block !important;\n}\n.invisible {\n visibility: hidden;\n}\n.text-hide {\n .text-hide();\n}\n\n\n// Hide from screenreaders and browsers\n//\n// Credit: HTML5 Boilerplate\n\n.hidden {\n display: none !important;\n visibility: hidden !important;\n}\n\n\n// For Affix plugin\n// -------------------------\n\n.affix {\n position: fixed;\n}\n", + "//\n// Breadcrumbs\n// --------------------------------------------------\n\n\n.breadcrumb {\n padding: @breadcrumb-padding-vertical @breadcrumb-padding-horizontal;\n margin-bottom: @line-height-computed;\n list-style: none;\n background-color: @breadcrumb-bg;\n border-radius: @border-radius-base;\n\n > li {\n display: inline-block;\n\n + li:before {\n content: \"@{breadcrumb-separator}\\00a0\"; // Unicode space added since inline-block means non-collapsing white-space\n padding: 0 5px;\n color: @breadcrumb-color;\n }\n }\n\n > .active {\n color: @breadcrumb-active-color;\n }\n}\n", + "//\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 color: @pagination-color;\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 color: @pagination-hover-color;\n background-color: @pagination-hover-bg;\n border-color: @pagination-hover-border;\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-border;\n cursor: default;\n }\n }\n\n > .disabled {\n > span,\n > span:hover,\n > span:focus,\n > a,\n > a:hover,\n > a:focus {\n color: @pagination-disabled-color;\n background-color: @pagination-disabled-bg;\n border-color: @pagination-disabled-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", + "//\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 &:extend(.clearfix all);\n li {\n display: inline;\n > a,\n > span {\n display: inline-block;\n padding: 5px 14px;\n background-color: @pager-bg;\n border: 1px solid @pager-border;\n border-radius: @pager-border-radius;\n }\n\n > a:hover,\n > a:focus {\n text-decoration: none;\n background-color: @pager-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: @pager-bg;\n cursor: not-allowed;\n }\n }\n\n}\n", + "//\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 // Quick fix for labels in buttons\n .btn & {\n position: relative;\n top: -1px;\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", + "//\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 // Quick fix for badges in buttons\n .btn & {\n position: relative;\n top: -1px;\n }\n .btn-xs & {\n top: 0;\n padding: 1px 5px;\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// 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", + "//\n// Jumbotron\n// --------------------------------------------------\n\n\n.jumbotron {\n padding: @jumbotron-padding;\n margin-bottom: @jumbotron-padding;\n color: @jumbotron-color;\n background-color: @jumbotron-bg;\n\n h1,\n .h1 {\n color: @jumbotron-heading-color;\n }\n p {\n margin-bottom: (@jumbotron-padding / 2);\n font-size: @jumbotron-font-size;\n font-weight: 200;\n }\n\n .container & {\n border-radius: @border-radius-large; // Only round corners at higher resolutions if contained in a container\n }\n\n .container {\n max-width: 100%;\n }\n\n @media screen and (min-width: @screen-sm-min) {\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 .h1 {\n font-size: (@font-size-base * 4.5);\n }\n }\n}\n", + "//\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 @headings-color\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", + "//\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// 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 line-height: @line-height-computed;\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();\n background-size: 40px 40px;\n}\n\n// Call animation for the active one\n.progress.active .progress-bar {\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", + "// 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", + "//\n// List groups\n// --------------------------------------------------\n\n\n// Base class\n//\n// Easily usable on
        ,
          , or
          .\n\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\n// Individual list items\n//\n// Use on `li`s or `div`s within the `.list-group` parent.\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\n\n// Linked list items\n//\n// Use anchor elements instead of `li`s or `div`s to create linked list items.\n// Includes an extra `.active` modifier class for showing selected items.\n\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 // 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: @list-group-active-text-color;\n }\n }\n}\n\n\n// Contextual variants\n//\n// Add modifier classes to change text and background color on individual items.\n// Organizationally, this must come after the `:hover` states.\n\n.list-group-item-variant(success; @state-success-bg; @state-success-text);\n.list-group-item-variant(info; @state-info-bg; @state-info-text);\n.list-group-item-variant(warning; @state-warning-bg; @state-warning-text);\n.list-group-item-variant(danger; @state-danger-bg; @state-danger-text);\n\n\n// Custom content options\n//\n// Extra classes for creating well-formatted content within `.list-group-item`s.\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", + "//\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: @panel-body-padding;\n &:extend(.clearfix all);\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 > .dropdown .dropdown-toggle {\n color: inherit;\n }\n}\n\n// Within heading, strip any `h*` tag of its 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 color: inherit;\n\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// 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 border-radius: 0;\n }\n\n // Add border top radius for first one\n &:first-child {\n .list-group-item:first-child {\n border-top: 0;\n .border-top-radius((@panel-border-radius - 1));\n }\n }\n // Add border bottom radius for last one\n &:last-child {\n .list-group-item:last-child {\n border-bottom: 0;\n .border-bottom-radius((@panel-border-radius - 1));\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 > .table-responsive > .table {\n margin-bottom: 0;\n }\n // Add border top radius for first one\n > .table:first-child,\n > .table-responsive:first-child > .table:first-child {\n .border-top-radius((@panel-border-radius - 1));\n\n > thead:first-child,\n > tbody:first-child {\n > tr:first-child {\n td:first-child,\n th:first-child {\n border-top-left-radius: (@panel-border-radius - 1);\n }\n td:last-child,\n th:last-child {\n border-top-right-radius: (@panel-border-radius - 1);\n }\n }\n }\n }\n // Add border bottom radius for last one\n > .table:last-child,\n > .table-responsive:last-child > .table:last-child {\n .border-bottom-radius((@panel-border-radius - 1));\n\n > tbody:last-child,\n > tfoot:last-child {\n > tr:last-child {\n td:first-child,\n th:first-child {\n border-bottom-left-radius: (@panel-border-radius - 1);\n }\n td:last-child,\n th:last-child {\n border-bottom-right-radius: (@panel-border-radius - 1);\n }\n }\n }\n }\n > .panel-body + .table,\n > .panel-body + .table-responsive {\n border-top: 1px solid @table-border-color;\n }\n > .table > tbody:first-child > tr:first-child th,\n > .table > tbody:first-child > tr:first-child td {\n border-top: 0;\n }\n > .table-bordered,\n > .table-responsive > .table-bordered {\n border: 0;\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 }\n > thead,\n > tbody {\n > tr:first-child {\n > td,\n > th {\n border-bottom: 0;\n }\n }\n }\n > tbody,\n > tfoot {\n > tr:last-child {\n > td,\n > th {\n border-bottom: 0;\n }\n }\n }\n }\n > .table-responsive {\n border: 0;\n margin-bottom: 0;\n }\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 margin-bottom: @line-height-computed;\n\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\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-info {\n .panel-variant(@panel-info-border; @panel-info-text; @panel-info-heading-bg; @panel-info-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", + "//\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 @well-border;\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", + "//\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", + "//\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// 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;\n -webkit-overflow-scrolling: touch;\n\n // Prevent Chrome on Windows from adding a focus outline. For details, see\n // https://github.com/twbs/bootstrap/pull/10951.\n outline: 0;\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 position: relative;\n width: auto;\n margin: 10px;\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;\n background-color: @modal-backdrop-bg;\n // Fade for backdrop\n &.fade { .opacity(0); }\n &.in { .opacity(@modal-backdrop-opacity); }\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 &:extend(.clearfix all); // 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 (min-width: @screen-sm-min) {\n // Automatically set modal's width for larger viewports\n .modal-dialog {\n width: @modal-md;\n margin: 30px auto;\n }\n .modal-content {\n .box-shadow(0 5px 15px rgba(0,0,0,.5));\n }\n\n // Modal sizes\n .modal-sm { width: @modal-sm; }\n}\n\n@media (min-width: @screen-md-min) {\n .modal-lg { width: @modal-lg; }\n}\n", + "//\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(@tooltip-opacity); }\n &.top { margin-top: -3px; padding: @tooltip-arrow-width 0; }\n &.right { margin-left: 3px; padding: 0 @tooltip-arrow-width; }\n &.bottom { margin-top: 3px; padding: @tooltip-arrow-width 0; }\n &.left { margin-left: -3px; padding: 0 @tooltip-arrow-width; }\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: @tooltip-arrow-width;\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: @tooltip-arrow-width;\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: @tooltip-arrow-width;\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: @tooltip-arrow-width;\n border-width: 0 @tooltip-arrow-width @tooltip-arrow-width;\n border-bottom-color: @tooltip-arrow-color;\n }\n}\n", + "//\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: -@popover-arrow-width; }\n &.right { margin-left: @popover-arrow-width; }\n &.bottom { margin-top: @popover-arrow-width; }\n &.left { margin-left: -@popover-arrow-width; }\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", + "//\n// Responsive: Utility classes\n// --------------------------------------------------\n\n\n// IE10 in Windows (Phone) 8\n//\n// Support for responsive views via media queries is kind of borked in IE10, for\n// Surface/desktop in split view and for Windows Phone 8. This particular fix\n// must be accompanied by a snippet of JavaScript to sniff the user agent and\n// apply some conditional CSS to *only* the Surface/desktop Windows 8. Look at\n// our Getting Started page for more information on this bug.\n//\n// For more information, see the following:\n//\n// Issue: https://github.com/twbs/bootstrap/issues/10497\n// Docs: http://getbootstrap.com/getting-started/#browsers\n// Source: http://timkadlec.com/2012/10/ie10-snap-mode-and-responsive-design/\n\n@-ms-viewport {\n width: device-width;\n}\n\n\n// Visibility utilities\n.visible-xs,\n.visible-sm,\n.visible-md,\n.visible-lg {\n .responsive-invisibility();\n}\n\n.visible-xs {\n @media (max-width: @screen-xs-max) {\n .responsive-visibility();\n }\n}\n.visible-sm {\n @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n .responsive-visibility();\n }\n}\n.visible-md {\n @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n .responsive-visibility();\n }\n}\n.visible-lg {\n @media (min-width: @screen-lg-min) {\n .responsive-visibility();\n }\n}\n\n.hidden-xs {\n @media (max-width: @screen-xs-max) {\n .responsive-invisibility();\n }\n}\n.hidden-sm {\n @media (min-width: @screen-sm-min) and (max-width: @screen-sm-max) {\n .responsive-invisibility();\n }\n}\n.hidden-md {\n @media (min-width: @screen-md-min) and (max-width: @screen-md-max) {\n .responsive-invisibility();\n }\n}\n.hidden-lg {\n @media (min-width: @screen-lg-min) {\n .responsive-invisibility();\n }\n}\n\n\n// Print utilities\n//\n// Media queries are placed on the inside to be mixin-friendly.\n\n.visible-print {\n .responsive-invisibility();\n\n @media print {\n .responsive-visibility();\n }\n}\n\n.hidden-print {\n @media print {\n .responsive-invisibility();\n }\n}\n" + ] +} diff --git a/pear-modules/pear-process/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/fonts/glyphicons-halflings-regular.svg b/pear-modules/pear-process/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/fonts/glyphicons-halflings-regular.svg index e3e2dc739dd851f2d7d291be032e30b909e3e95f..865226d57117a861642f53012ac06865b9eeacf6 100644 --- a/pear-modules/pear-process/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/fonts/glyphicons-halflings-regular.svg +++ b/pear-modules/pear-process/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/fonts/glyphicons-halflings-regular.svg @@ -1,229 +1,410 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pear-modules/pear-process/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/js/bootstrap.js b/pear-modules/pear-process/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/js/bootstrap.js index 8ae571b6da5be9c7dcd95ba25896ae39e1917445..0b67f7f8a538abd15d75464dc986cc19d84c9651 100644 --- a/pear-modules/pear-process/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/js/bootstrap.js +++ b/pear-modules/pear-process/src/main/resources/static/editor-app/libs/bootstrap_3.1.1/js/bootstrap.js @@ -4,7 +4,9 @@ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) */ -if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript requires jQuery') } +if (typeof jQuery === 'undefined') { + throw new Error('Bootstrap\'s JavaScript requires jQuery') +} /* ======================================================================== * Bootstrap: transition.js v3.1.1 @@ -16,42 +18,46 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re +function ($) { - 'use strict'; + 'use strict'; - // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/) - // ============================================================ + // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/) + // ============================================================ - function transitionEnd() { - var el = document.createElement('bootstrap') + function transitionEnd() { + var el = document.createElement('bootstrap') - var transEndEventNames = { - 'WebkitTransition' : 'webkitTransitionEnd', - 'MozTransition' : 'transitionend', - 'OTransition' : 'oTransitionEnd otransitionend', - 'transition' : 'transitionend' - } + var transEndEventNames = { + 'WebkitTransition': 'webkitTransitionEnd', + 'MozTransition': 'transitionend', + 'OTransition': 'oTransitionEnd otransitionend', + 'transition': 'transitionend' + } - for (var name in transEndEventNames) { - if (el.style[name] !== undefined) { - return { end: transEndEventNames[name] } - } - } + for (var name in transEndEventNames) { + if (el.style[name] !== undefined) { + return {end: transEndEventNames[name]} + } + } - return false // explicit for ie8 ( ._.) - } + return false // explicit for ie8 ( ._.) + } - // http://blog.alexmaccaw.com/css-transitions - $.fn.emulateTransitionEnd = function (duration) { - var called = false, $el = this - $(this).one($.support.transition.end, function () { called = true }) - var callback = function () { if (!called) $($el).trigger($.support.transition.end) } - setTimeout(callback, duration) - return this - } + // http://blog.alexmaccaw.com/css-transitions + $.fn.emulateTransitionEnd = function (duration) { + var called = false, $el = this + $(this).one($.support.transition.end, function () { + called = true + }) + var callback = function () { + if (!called) $($el).trigger($.support.transition.end) + } + setTimeout(callback, duration) + return this + } - $(function () { - $.support.transition = transitionEnd() - }) + $(function () { + $.support.transition = transitionEnd() + }) }(jQuery); @@ -65,82 +71,82 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re +function ($) { - 'use strict'; + 'use strict'; - // ALERT CLASS DEFINITION - // ====================== + // ALERT CLASS DEFINITION + // ====================== - var dismiss = '[data-dismiss="alert"]' - var Alert = function (el) { - $(el).on('click', dismiss, this.close) - } + var dismiss = '[data-dismiss="alert"]' + var Alert = function (el) { + $(el).on('click', dismiss, this.close) + } - Alert.prototype.close = function (e) { - var $this = $(this) - var selector = $this.attr('data-target') + Alert.prototype.close = function (e) { + var $this = $(this) + var selector = $this.attr('data-target') - if (!selector) { - selector = $this.attr('href') - selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 - } + if (!selector) { + selector = $this.attr('href') + selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7 + } - var $parent = $(selector) + var $parent = $(selector) - if (e) e.preventDefault() + if (e) e.preventDefault() - if (!$parent.length) { - $parent = $this.hasClass('alert') ? $this : $this.parent() - } + if (!$parent.length) { + $parent = $this.hasClass('alert') ? $this : $this.parent() + } - $parent.trigger(e = $.Event('close.bs.alert')) + $parent.trigger(e = $.Event('close.bs.alert')) - if (e.isDefaultPrevented()) return + if (e.isDefaultPrevented()) return - $parent.removeClass('in') + $parent.removeClass('in') - function removeElement() { - $parent.trigger('closed.bs.alert').remove() - } + function removeElement() { + $parent.trigger('closed.bs.alert').remove() + } - $.support.transition && $parent.hasClass('fade') ? - $parent - .one($.support.transition.end, removeElement) - .emulateTransitionEnd(150) : - removeElement() - } + $.support.transition && $parent.hasClass('fade') ? + $parent + .one($.support.transition.end, removeElement) + .emulateTransitionEnd(150) : + removeElement() + } - // ALERT PLUGIN DEFINITION - // ======================= + // ALERT PLUGIN DEFINITION + // ======================= - var old = $.fn.alert + var old = $.fn.alert - $.fn.alert = function (option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.alert') + $.fn.alert = function (option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.alert') - if (!data) $this.data('bs.alert', (data = new Alert(this))) - if (typeof option == 'string') data[option].call($this) - }) - } + if (!data) $this.data('bs.alert', (data = new Alert(this))) + if (typeof option == 'string') data[option].call($this) + }) + } - $.fn.alert.Constructor = Alert + $.fn.alert.Constructor = Alert - // ALERT NO CONFLICT - // ================= + // ALERT NO CONFLICT + // ================= - $.fn.alert.noConflict = function () { - $.fn.alert = old - return this - } + $.fn.alert.noConflict = function () { + $.fn.alert = old + return this + } - // ALERT DATA-API - // ============== + // ALERT DATA-API + // ============== - $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close) + $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close) }(jQuery); @@ -154,101 +160,101 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re +function ($) { - 'use strict'; + 'use strict'; - // BUTTON PUBLIC CLASS DEFINITION - // ============================== + // BUTTON PUBLIC CLASS DEFINITION + // ============================== - var Button = function (element, options) { - this.$element = $(element) - this.options = $.extend({}, Button.DEFAULTS, options) - this.isLoading = false - } + var Button = function (element, options) { + this.$element = $(element) + this.options = $.extend({}, Button.DEFAULTS, options) + this.isLoading = false + } - Button.DEFAULTS = { - loadingText: 'loading...' - } + Button.DEFAULTS = { + loadingText: 'loading...' + } - Button.prototype.setState = function (state) { - var d = 'disabled' - var $el = this.$element - var val = $el.is('input') ? 'val' : 'html' - var data = $el.data() + Button.prototype.setState = function (state) { + var d = 'disabled' + var $el = this.$element + var val = $el.is('input') ? 'val' : 'html' + var data = $el.data() - state = state + 'Text' + state = state + 'Text' - if (!data.resetText) $el.data('resetText', $el[val]()) + if (!data.resetText) $el.data('resetText', $el[val]()) - $el[val](data[state] || this.options[state]) + $el[val](data[state] || this.options[state]) - // push to event loop to allow forms to submit - setTimeout($.proxy(function () { - if (state == 'loadingText') { - this.isLoading = true - $el.addClass(d).attr(d, d) - } else if (this.isLoading) { - this.isLoading = false - $el.removeClass(d).removeAttr(d) - } - }, this), 0) - } + // push to event loop to allow forms to submit + setTimeout($.proxy(function () { + if (state == 'loadingText') { + this.isLoading = true + $el.addClass(d).attr(d, d) + } else if (this.isLoading) { + this.isLoading = false + $el.removeClass(d).removeAttr(d) + } + }, this), 0) + } - Button.prototype.toggle = function () { - var changed = true - var $parent = this.$element.closest('[data-toggle="buttons"]') + Button.prototype.toggle = function () { + var changed = true + var $parent = this.$element.closest('[data-toggle="buttons"]') + + if ($parent.length) { + var $input = this.$element.find('input') + if ($input.prop('type') == 'radio') { + if ($input.prop('checked') && this.$element.hasClass('active')) changed = false + else $parent.find('.active').removeClass('active') + } + if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change') + } - if ($parent.length) { - var $input = this.$element.find('input') - if ($input.prop('type') == 'radio') { - if ($input.prop('checked') && this.$element.hasClass('active')) changed = false - else $parent.find('.active').removeClass('active') - } - if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change') + if (changed) this.$element.toggleClass('active') } - if (changed) this.$element.toggleClass('active') - } + // BUTTON PLUGIN DEFINITION + // ======================== - // BUTTON PLUGIN DEFINITION - // ======================== + var old = $.fn.button - var old = $.fn.button + $.fn.button = function (option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.button') + var options = typeof option == 'object' && option - $.fn.button = function (option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.button') - var options = typeof option == 'object' && option + if (!data) $this.data('bs.button', (data = new Button(this, options))) - if (!data) $this.data('bs.button', (data = new Button(this, options))) - - if (option == 'toggle') data.toggle() - else if (option) data.setState(option) - }) - } + if (option == 'toggle') data.toggle() + else if (option) data.setState(option) + }) + } - $.fn.button.Constructor = Button + $.fn.button.Constructor = Button - // BUTTON NO CONFLICT - // ================== + // BUTTON NO CONFLICT + // ================== - $.fn.button.noConflict = function () { - $.fn.button = old - return this - } + $.fn.button.noConflict = function () { + $.fn.button = old + return this + } - // BUTTON DATA-API - // =============== + // BUTTON DATA-API + // =============== - $(document).on('click.bs.button.data-api', '[data-toggle^=button]', function (e) { - var $btn = $(e.target) - if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') - $btn.button('toggle') - e.preventDefault() - }) + $(document).on('click.bs.button.data-api', '[data-toggle^=button]', function (e) { + var $btn = $(e.target) + if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn') + $btn.button('toggle') + e.preventDefault() + }) }(jQuery); @@ -262,199 +268,203 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re +function ($) { - 'use strict'; - - // CAROUSEL CLASS DEFINITION - // ========================= + 'use strict'; + + // CAROUSEL CLASS DEFINITION + // ========================= + + var Carousel = function (element, options) { + this.$element = $(element) + this.$indicators = this.$element.find('.carousel-indicators') + this.options = options + this.paused = + this.sliding = + this.interval = + this.$active = + this.$items = null + + this.options.pause == 'hover' && this.$element + .on('mouseenter', $.proxy(this.pause, this)) + .on('mouseleave', $.proxy(this.cycle, this)) + } - var Carousel = function (element, options) { - this.$element = $(element) - this.$indicators = this.$element.find('.carousel-indicators') - this.options = options - this.paused = - this.sliding = - this.interval = - this.$active = - this.$items = null + Carousel.DEFAULTS = { + interval: 5000, + pause: 'hover', + wrap: true + } - this.options.pause == 'hover' && this.$element - .on('mouseenter', $.proxy(this.pause, this)) - .on('mouseleave', $.proxy(this.cycle, this)) - } + Carousel.prototype.cycle = function (e) { + e || (this.paused = false) - Carousel.DEFAULTS = { - interval: 5000, - pause: 'hover', - wrap: true - } + this.interval && clearInterval(this.interval) - Carousel.prototype.cycle = function (e) { - e || (this.paused = false) + this.options.interval + && !this.paused + && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) - this.interval && clearInterval(this.interval) + return this + } - this.options.interval - && !this.paused - && (this.interval = setInterval($.proxy(this.next, this), this.options.interval)) + Carousel.prototype.getActiveIndex = function () { + this.$active = this.$element.find('.item.active') + this.$items = this.$active.parent().children() - return this - } + return this.$items.index(this.$active) + } - Carousel.prototype.getActiveIndex = function () { - this.$active = this.$element.find('.item.active') - this.$items = this.$active.parent().children() + Carousel.prototype.to = function (pos) { + var that = this + var activeIndex = this.getActiveIndex() - return this.$items.index(this.$active) - } + if (pos > (this.$items.length - 1) || pos < 0) return - Carousel.prototype.to = function (pos) { - var that = this - var activeIndex = this.getActiveIndex() + if (this.sliding) return this.$element.one('slid.bs.carousel', function () { + that.to(pos) + }) + if (activeIndex == pos) return this.pause().cycle() - if (pos > (this.$items.length - 1) || pos < 0) return + return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos])) + } - if (this.sliding) return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) - if (activeIndex == pos) return this.pause().cycle() + Carousel.prototype.pause = function (e) { + e || (this.paused = true) - return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos])) - } + if (this.$element.find('.next, .prev').length && $.support.transition) { + this.$element.trigger($.support.transition.end) + this.cycle(true) + } - Carousel.prototype.pause = function (e) { - e || (this.paused = true) + this.interval = clearInterval(this.interval) - if (this.$element.find('.next, .prev').length && $.support.transition) { - this.$element.trigger($.support.transition.end) - this.cycle(true) + return this } - this.interval = clearInterval(this.interval) - - return this - } + Carousel.prototype.next = function () { + if (this.sliding) return + return this.slide('next') + } - Carousel.prototype.next = function () { - if (this.sliding) return - return this.slide('next') - } + Carousel.prototype.prev = function () { + if (this.sliding) return + return this.slide('prev') + } - Carousel.prototype.prev = function () { - if (this.sliding) return - return this.slide('prev') - } + Carousel.prototype.slide = function (type, next) { + var $active = this.$element.find('.item.active') + var $next = next || $active[type]() + var isCycling = this.interval + var direction = type == 'next' ? 'left' : 'right' + var fallback = type == 'next' ? 'first' : 'last' + var that = this + + if (!$next.length) { + if (!this.options.wrap) return + $next = this.$element.find('.item')[fallback]() + } - Carousel.prototype.slide = function (type, next) { - var $active = this.$element.find('.item.active') - var $next = next || $active[type]() - var isCycling = this.interval - var direction = type == 'next' ? 'left' : 'right' - var fallback = type == 'next' ? 'first' : 'last' - var that = this + if ($next.hasClass('active')) return this.sliding = false - if (!$next.length) { - if (!this.options.wrap) return - $next = this.$element.find('.item')[fallback]() - } + var e = $.Event('slide.bs.carousel', {relatedTarget: $next[0], direction: direction}) + this.$element.trigger(e) + if (e.isDefaultPrevented()) return - if ($next.hasClass('active')) return this.sliding = false + this.sliding = true - var e = $.Event('slide.bs.carousel', { relatedTarget: $next[0], direction: direction }) - this.$element.trigger(e) - if (e.isDefaultPrevented()) return + isCycling && this.pause() - this.sliding = true + if (this.$indicators.length) { + this.$indicators.find('.active').removeClass('active') + this.$element.one('slid.bs.carousel', function () { + var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()]) + $nextIndicator && $nextIndicator.addClass('active') + }) + } - isCycling && this.pause() + if ($.support.transition && this.$element.hasClass('slide')) { + $next.addClass(type) + $next[0].offsetWidth // force reflow + $active.addClass(direction) + $next.addClass(direction) + $active + .one($.support.transition.end, function () { + $next.removeClass([type, direction].join(' ')).addClass('active') + $active.removeClass(['active', direction].join(' ')) + that.sliding = false + setTimeout(function () { + that.$element.trigger('slid.bs.carousel') + }, 0) + }) + .emulateTransitionEnd($active.css('transition-duration').slice(0, -1) * 1000) + } else { + $active.removeClass('active') + $next.addClass('active') + this.sliding = false + this.$element.trigger('slid.bs.carousel') + } - if (this.$indicators.length) { - this.$indicators.find('.active').removeClass('active') - this.$element.one('slid.bs.carousel', function () { - var $nextIndicator = $(that.$indicators.children()[that.getActiveIndex()]) - $nextIndicator && $nextIndicator.addClass('active') - }) - } + isCycling && this.cycle() - if ($.support.transition && this.$element.hasClass('slide')) { - $next.addClass(type) - $next[0].offsetWidth // force reflow - $active.addClass(direction) - $next.addClass(direction) - $active - .one($.support.transition.end, function () { - $next.removeClass([type, direction].join(' ')).addClass('active') - $active.removeClass(['active', direction].join(' ')) - that.sliding = false - setTimeout(function () { that.$element.trigger('slid.bs.carousel') }, 0) - }) - .emulateTransitionEnd($active.css('transition-duration').slice(0, -1) * 1000) - } else { - $active.removeClass('active') - $next.addClass('active') - this.sliding = false - this.$element.trigger('slid.bs.carousel') + return this } - isCycling && this.cycle() - - return this - } + // CAROUSEL PLUGIN DEFINITION + // ========================== - // CAROUSEL PLUGIN DEFINITION - // ========================== + var old = $.fn.carousel - var old = $.fn.carousel + $.fn.carousel = function (option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.carousel') + var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option) + var action = typeof option == 'string' ? option : options.slide - $.fn.carousel = function (option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.carousel') - var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option) - var action = typeof option == 'string' ? option : options.slide - - if (!data) $this.data('bs.carousel', (data = new Carousel(this, options))) - if (typeof option == 'number') data.to(option) - else if (action) data[action]() - else if (options.interval) data.pause().cycle() - }) - } + if (!data) $this.data('bs.carousel', (data = new Carousel(this, options))) + if (typeof option == 'number') data.to(option) + else if (action) data[action]() + else if (options.interval) data.pause().cycle() + }) + } - $.fn.carousel.Constructor = Carousel + $.fn.carousel.Constructor = Carousel - // CAROUSEL NO CONFLICT - // ==================== + // CAROUSEL NO CONFLICT + // ==================== - $.fn.carousel.noConflict = function () { - $.fn.carousel = old - return this - } + $.fn.carousel.noConflict = function () { + $.fn.carousel = old + return this + } - // CAROUSEL DATA-API - // ================= + // CAROUSEL DATA-API + // ================= - $(document).on('click.bs.carousel.data-api', '[data-slide], [data-slide-to]', function (e) { - var $this = $(this), href - var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7 - var options = $.extend({}, $target.data(), $this.data()) - var slideIndex = $this.attr('data-slide-to') - if (slideIndex) options.interval = false + $(document).on('click.bs.carousel.data-api', '[data-slide], [data-slide-to]', function (e) { + var $this = $(this), href + var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) //strip for ie7 + var options = $.extend({}, $target.data(), $this.data()) + var slideIndex = $this.attr('data-slide-to') + if (slideIndex) options.interval = false - $target.carousel(options) + $target.carousel(options) - if (slideIndex = $this.attr('data-slide-to')) { - $target.data('bs.carousel').to(slideIndex) - } + if (slideIndex = $this.attr('data-slide-to')) { + $target.data('bs.carousel').to(slideIndex) + } - e.preventDefault() - }) + e.preventDefault() + }) - $(window).on('load', function () { - $('[data-ride="carousel"]').each(function () { - var $carousel = $(this) - $carousel.carousel($carousel.data()) + $(window).on('load', function () { + $('[data-ride="carousel"]').each(function () { + var $carousel = $(this) + $carousel.carousel($carousel.data()) + }) }) - }) }(jQuery); @@ -468,164 +478,164 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re +function ($) { - 'use strict'; + 'use strict'; - // COLLAPSE PUBLIC CLASS DEFINITION - // ================================ + // COLLAPSE PUBLIC CLASS DEFINITION + // ================================ - var Collapse = function (element, options) { - this.$element = $(element) - this.options = $.extend({}, Collapse.DEFAULTS, options) - this.transitioning = null + var Collapse = function (element, options) { + this.$element = $(element) + this.options = $.extend({}, Collapse.DEFAULTS, options) + this.transitioning = null - if (this.options.parent) this.$parent = $(this.options.parent) - if (this.options.toggle) this.toggle() - } + if (this.options.parent) this.$parent = $(this.options.parent) + if (this.options.toggle) this.toggle() + } - Collapse.DEFAULTS = { - toggle: true - } + Collapse.DEFAULTS = { + toggle: true + } - Collapse.prototype.dimension = function () { - var hasWidth = this.$element.hasClass('width') - return hasWidth ? 'width' : 'height' - } + Collapse.prototype.dimension = function () { + var hasWidth = this.$element.hasClass('width') + return hasWidth ? 'width' : 'height' + } - Collapse.prototype.show = function () { - if (this.transitioning || this.$element.hasClass('in')) return + Collapse.prototype.show = function () { + if (this.transitioning || this.$element.hasClass('in')) return - var startEvent = $.Event('show.bs.collapse') - this.$element.trigger(startEvent) - if (startEvent.isDefaultPrevented()) return + var startEvent = $.Event('show.bs.collapse') + this.$element.trigger(startEvent) + if (startEvent.isDefaultPrevented()) return - var actives = this.$parent && this.$parent.find('> .panel > .in') + var actives = this.$parent && this.$parent.find('> .panel > .in') - if (actives && actives.length) { - var hasData = actives.data('bs.collapse') - if (hasData && hasData.transitioning) return - actives.collapse('hide') - hasData || actives.data('bs.collapse', null) - } + if (actives && actives.length) { + var hasData = actives.data('bs.collapse') + if (hasData && hasData.transitioning) return + actives.collapse('hide') + hasData || actives.data('bs.collapse', null) + } - var dimension = this.dimension() + var dimension = this.dimension() - this.$element - .removeClass('collapse') - .addClass('collapsing') - [dimension](0) + this.$element + .removeClass('collapse') + .addClass('collapsing') + [dimension](0) - this.transitioning = 1 + this.transitioning = 1 - var complete = function () { - this.$element - .removeClass('collapsing') - .addClass('collapse in') - [dimension]('auto') - this.transitioning = 0 - this.$element.trigger('shown.bs.collapse') - } + var complete = function () { + this.$element + .removeClass('collapsing') + .addClass('collapse in') + [dimension]('auto') + this.transitioning = 0 + this.$element.trigger('shown.bs.collapse') + } - if (!$.support.transition) return complete.call(this) + if (!$.support.transition) return complete.call(this) - var scrollSize = $.camelCase(['scroll', dimension].join('-')) + var scrollSize = $.camelCase(['scroll', dimension].join('-')) - this.$element - .one($.support.transition.end, $.proxy(complete, this)) - .emulateTransitionEnd(350) - [dimension](this.$element[0][scrollSize]) - } + this.$element + .one($.support.transition.end, $.proxy(complete, this)) + .emulateTransitionEnd(350) + [dimension](this.$element[0][scrollSize]) + } - Collapse.prototype.hide = function () { - if (this.transitioning || !this.$element.hasClass('in')) return + Collapse.prototype.hide = function () { + if (this.transitioning || !this.$element.hasClass('in')) return - var startEvent = $.Event('hide.bs.collapse') - this.$element.trigger(startEvent) - if (startEvent.isDefaultPrevented()) return + var startEvent = $.Event('hide.bs.collapse') + this.$element.trigger(startEvent) + if (startEvent.isDefaultPrevented()) return - var dimension = this.dimension() + var dimension = this.dimension() - this.$element - [dimension](this.$element[dimension]()) - [0].offsetHeight + this.$element + [dimension](this.$element[dimension]()) + [0].offsetHeight - this.$element - .addClass('collapsing') - .removeClass('collapse') - .removeClass('in') + this.$element + .addClass('collapsing') + .removeClass('collapse') + .removeClass('in') - this.transitioning = 1 + this.transitioning = 1 - var complete = function () { - this.transitioning = 0 - this.$element - .trigger('hidden.bs.collapse') - .removeClass('collapsing') - .addClass('collapse') - } + var complete = function () { + this.transitioning = 0 + this.$element + .trigger('hidden.bs.collapse') + .removeClass('collapsing') + .addClass('collapse') + } - if (!$.support.transition) return complete.call(this) + if (!$.support.transition) return complete.call(this) - this.$element - [dimension](0) - .one($.support.transition.end, $.proxy(complete, this)) - .emulateTransitionEnd(350) - } + this.$element + [dimension](0) + .one($.support.transition.end, $.proxy(complete, this)) + .emulateTransitionEnd(350) + } - Collapse.prototype.toggle = function () { - this[this.$element.hasClass('in') ? 'hide' : 'show']() - } + Collapse.prototype.toggle = function () { + this[this.$element.hasClass('in') ? 'hide' : 'show']() + } - // COLLAPSE PLUGIN DEFINITION - // ========================== + // COLLAPSE PLUGIN DEFINITION + // ========================== - var old = $.fn.collapse + var old = $.fn.collapse - $.fn.collapse = function (option) { - return this.each(function () { - var $this = $(this) - var data = $this.data('bs.collapse') - var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) + $.fn.collapse = function (option) { + return this.each(function () { + var $this = $(this) + var data = $this.data('bs.collapse') + var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option) - if (!data && options.toggle && option == 'show') option = !option - if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) - if (typeof option == 'string') data[option]() - }) - } + if (!data && options.toggle && option == 'show') option = !option + if (!data) $this.data('bs.collapse', (data = new Collapse(this, options))) + if (typeof option == 'string') data[option]() + }) + } - $.fn.collapse.Constructor = Collapse + $.fn.collapse.Constructor = Collapse - // COLLAPSE NO CONFLICT - // ==================== + // COLLAPSE NO CONFLICT + // ==================== - $.fn.collapse.noConflict = function () { - $.fn.collapse = old - return this - } + $.fn.collapse.noConflict = function () { + $.fn.collapse = old + return this + } - // COLLAPSE DATA-API - // ================= + // COLLAPSE DATA-API + // ================= - $(document).on('click.bs.collapse.data-api', '[data-toggle=collapse]', function (e) { - var $this = $(this), href - var target = $this.attr('data-target') - || e.preventDefault() - || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 - var $target = $(target) - var data = $target.data('bs.collapse') - var option = data ? 'toggle' : $this.data() - var parent = $this.attr('data-parent') - var $parent = parent && $(parent) + $(document).on('click.bs.collapse.data-api', '[data-toggle=collapse]', function (e) { + var $this = $(this), href + var target = $this.attr('data-target') + || e.preventDefault() + || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') //strip for ie7 + var $target = $(target) + var data = $target.data('bs.collapse') + var option = data ? 'toggle' : $this.data() + var parent = $this.attr('data-parent') + var $parent = parent && $(parent) - if (!data || !data.transitioning) { - if ($parent) $parent.find('[data-toggle=collapse][data-parent="' + parent + '"]').not($this).addClass('collapsed') - $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed') - } + if (!data || !data.transitioning) { + if ($parent) $parent.find('[data-toggle=collapse][data-parent="' + parent + '"]').not($this).addClass('collapsed') + $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed') + } - $target.collapse(option) - }) + $target.collapse(option) + }) }(jQuery); @@ -639,141 +649,143 @@ if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript re +function ($) { - 'use strict'; + 'use strict'; - // DROPDOWN CLASS DEFINITION - // ========================= + // DROPDOWN CLASS DEFINITION + // ========================= - var backdrop = '.dropdown-backdrop' - var toggle = '[data-toggle=dropdown]' - var Dropdown = function (element) { - $(element).on('click.bs.dropdown', this.toggle) - } + var backdrop = '.dropdown-backdrop' + var toggle = '[data-toggle=dropdown]' + var Dropdown = function (element) { + $(element).on('click.bs.dropdown', this.toggle) + } - Dropdown.prototype.toggle = function (e) { - var $this = $(this) + Dropdown.prototype.toggle = function (e) { + var $this = $(this) - if ($this.is('.disabled, :disabled')) return + if ($this.is('.disabled, :disabled')) return - var $parent = getParent($this) - var isActive = $parent.hasClass('open') + var $parent = getParent($this) + var isActive = $parent.hasClass('open') - clearMenus() + clearMenus() - if (!isActive) { - if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) { - // if mobile we use a backdrop because click events don't delegate - $('