diff --git a/docs/_coverpage.md b/docs/_coverpage.md
index c073743..b51b6db 100644
--- a/docs/_coverpage.md
+++ b/docs/_coverpage.md
@@ -1,6 +1,6 @@

-v2.0.2@Huoyo
+v2.0.3@Huoyo
> koTime是一个springboot方法调用链路追踪和运行时长统计工具
@@ -9,4 +9,4 @@
[Gitee](https://gitee.com/huoyo/ko-time)
-[文档教程](v202/introduce)
+[文档教程](v203/introduce)
diff --git a/docs/_navbar.md b/docs/_navbar.md
index de79452..5d61d3f 100644
--- a/docs/_navbar.md
+++ b/docs/_navbar.md
@@ -1,5 +1,6 @@
* 其他版本教程
+ * [V2.0.3](v203/getstart)
* [V2.0.2](v202/getstart)
* [V2.0.1](v201/getstart)
* [V2.0.0及以下](v200/getstart)
diff --git a/docs/v202/getstart.md b/docs/v202/getstart.md
index 3ac48c1..debc641 100644
--- a/docs/v202/getstart.md
+++ b/docs/v202/getstart.md
@@ -11,7 +11,6 @@
2.0.2
-
```
## 配置
diff --git a/docs/v203/_sidebar.md b/docs/v203/_sidebar.md
new file mode 100644
index 0000000..cde90a5
--- /dev/null
+++ b/docs/v203/_sidebar.md
@@ -0,0 +1,5 @@
+* [简介](v203/introduce)
+* [快速上手](v203/getstart)
+* [UI页面说明](v203/uiguide)
+* [API数据接口](v203/apiintro)
+* [常见问题](v203/questions)
\ No newline at end of file
diff --git a/docs/v203/apiintro.md b/docs/v203/apiintro.md
new file mode 100644
index 0000000..9e1bb41
--- /dev/null
+++ b/docs/v203/apiintro.md
@@ -0,0 +1,282 @@
+
+## 获取接口方法列表
+
+* 接口名
+
+>`GET` /koTime/getApis
+
+* 返回示例
+
+```json
+[
+ {
+ "id":"com.example.demo.controller.IndexController.test1",
+ "name":"IndexController.test1",
+ "className":"com.example.demo.controller.IndexController",
+ "methodName":"test1",
+ "value":2001.38,
+ "avgRunTime":2001.38,
+ "maxRunTime":2001.9,
+ "minRunTime":2001.19,
+ "methodType":"Controller",
+ "exceptionNum":0,
+ "children":[
+
+ ],
+ "exceptions":[
+
+ ]
+ },
+ {
+ "id":"com.example.demo.controller.IndexController.test2",
+ "name":"IndexController.test1",
+ "className":"com.example.demo.controller.IndexController",
+ "methodName":"test1",
+ "value":2001.38,
+ "avgRunTime":2001.38,
+ "maxRunTime":2001.9,
+ "minRunTime":2001.19,
+ "methodType":"Controller",
+ "exceptionNum":0,
+ "children":[
+
+ ],
+ "exceptions":[
+
+ ]
+ }
+]
+```
+
+
+## 获取方法列表调用链路
+
+* 接口名
+
+>`GET` /koTime/getTree?methodName=每一个方法的id
+
+* 返回示例
+```json
+{
+ "id":"com.example.demo.controller.IndexController.test1",
+ "name":"IndexController.test1",
+ "className":"com.example.demo.controller.IndexController",
+ "methodName":"test1",
+ "value":2001.38,
+ "avgRunTime":2001.38,
+ "maxRunTime":2001.9,
+ "minRunTime":2001.19,
+ "methodType":"Controller",
+ "exceptionNum":0,
+ "children":[
+ {
+ "id":"com.example.demo.service.impl.IndexServiceImpl.getParents",
+ "name":"IndexServiceImpl.getParents",
+ "className":"com.example.demo.service.impl.IndexServiceImpl",
+ "methodName":"getParents",
+ "value":0.47,
+ "avgRunTime":0.47,
+ "maxRunTime":0.59,
+ "minRunTime":0.43,
+ "methodType":"Service",
+ "exceptionNum":1,
+ "children":[
+ {
+ "id":"com.example.demo.service.impl.IndexServiceImpl.index2",
+ "name":"IndexServiceImpl.index2",
+ "className":"com.example.demo.service.impl.IndexServiceImpl",
+ "methodName":"index2",
+ "value":0.35,
+ "avgRunTime":0.35,
+ "maxRunTime":0.4,
+ "minRunTime":0.32,
+ "methodType":"Service",
+ "exceptionNum":0,
+ "children":[
+
+ ],
+ "exceptions":[
+
+ ]
+ }
+ ],
+ "exceptions":[
+ {
+ "id":"java.lang.RuntimeExceptionRuntimeException获取信息失败",
+ "name":"RuntimeException",
+ "className":"java.lang.RuntimeException",
+ "message":"获取信息失败",
+ "location":91,
+ "methodName":null,
+ "occurClassName":null
+ }
+ ]
+ },
+ {
+ "id":"com.example.demo.service.impl.IndexServiceImpl.getUsers",
+ "name":"IndexServiceImpl.getUsers",
+ "className":"com.example.demo.service.impl.IndexServiceImpl",
+ "methodName":"getUsers",
+ "value":1000.91,
+ "avgRunTime":1000.91,
+ "maxRunTime":1006.25,
+ "minRunTime":1000.79,
+ "methodType":"Service",
+ "exceptionNum":1,
+ "children":[
+ {
+ "id":"com.example.demo.service.impl.IndexServiceImpl.index1",
+ "name":"IndexServiceImpl.index1",
+ "className":"com.example.demo.service.impl.IndexServiceImpl",
+ "methodName":"index1",
+ "value":0.42,
+ "avgRunTime":0.42,
+ "maxRunTime":3.81,
+ "minRunTime":0.37,
+ "methodType":"Service",
+ "exceptionNum":0,
+ "children":[
+ {
+ "id":"com.example.demo.service.impl.IndexServiceImpl.test2",
+ "name":"IndexServiceImpl.test2",
+ "className":"com.example.demo.service.impl.IndexServiceImpl",
+ "methodName":"test2",
+ "value":0.01,
+ "avgRunTime":0.01,
+ "maxRunTime":0.02,
+ "minRunTime":"0.0",
+ "methodType":"Service",
+ "exceptionNum":0,
+ "children":[
+
+ ],
+ "exceptions":[
+
+ ]
+ },
+ {
+ "id":"com.example.demo.service.impl.IndexServiceImpl.test1",
+ "name":"IndexServiceImpl.test1",
+ "className":"com.example.demo.service.impl.IndexServiceImpl",
+ "methodName":"test1",
+ "value":0.04,
+ "avgRunTime":0.04,
+ "maxRunTime":0.08,
+ "minRunTime":0.03,
+ "methodType":"Service",
+ "exceptionNum":0,
+ "children":[
+
+ ],
+ "exceptions":[
+
+ ]
+ }
+ ],
+ "exceptions":[
+
+ ]
+ }
+ ],
+ "exceptions":[
+ {
+ "id":"java.lang.RuntimeExceptionRuntimeException认证失败",
+ "name":"RuntimeException",
+ "className":"java.lang.RuntimeException",
+ "message":"认证失败",
+ "location":82,
+ "methodName":null,
+ "occurClassName":null
+ }
+ ]
+ }
+ ],
+ "exceptions":[
+
+ ]
+}
+```
+
+## 获取异常列表
+
+* 接口名
+
+>`GET` /koTime/getExceptions
+
+* 返回示例
+
+```json
+[
+ {
+ "id":"java.lang.RuntimeExceptionRuntimeException认证失败",
+ "name":"RuntimeException",
+ "className":"java.lang.RuntimeException",
+ "message":"认证失败",
+ "value":82
+ },
+ {
+ "id":"java.lang.RuntimeExceptionRuntimeException获取信息失败",
+ "name":"RuntimeException",
+ "className":"java.lang.RuntimeException",
+ "message":"获取信息失败",
+ "value":91
+ }
+]
+```
+
+## 获取异常详情
+
+* 接口名
+
+> `GET` /koTime/getMethodsByExceptionId?exceptionId=xx
+
+* 返回示例
+```json
+[
+ {
+ "id":"java.lang.RuntimeExceptionRuntimeException获取信息失败",
+ "name":"RuntimeException",
+ "className":"java.lang.RuntimeException",
+ "message":"获取信息失败",
+ "location":91,
+ "methodName":"getParents",
+ "occurClassName":"com.example.demo.service.impl.IndexServiceImpl"
+ }
+]
+```
+
+## 获取当前配置信息
+
+* 接口名
+
+>`GET` /koTime/getConfig
+
+* 返回示例
+
+```json
+{
+ "logLanguage":"chinese",
+ "enable":true,
+ "logEnable":false,
+ "threshold":"800.0",
+ "exceptionEnable":true,
+ "dataSaver":"memory"
+}
+```
+
+## 更新当前配置信息
+
+* 接口名
+
+>`POST` /koTime/updateConfig
+
+* 参数示例
+
+```json
+{
+ "enable":true,
+ "logEnable":false,
+ "threshold":"800.0",
+ "exceptionEnable":true
+}
+```
\ No newline at end of file
diff --git a/docs/v203/apis.png b/docs/v203/apis.png
new file mode 100644
index 0000000..e308d33
Binary files /dev/null and b/docs/v203/apis.png differ
diff --git a/docs/v203/ff.png b/docs/v203/ff.png
new file mode 100644
index 0000000..c43f229
Binary files /dev/null and b/docs/v203/ff.png differ
diff --git a/docs/v203/getstart.md b/docs/v203/getstart.md
new file mode 100644
index 0000000..761a9cf
--- /dev/null
+++ b/docs/v203/getstart.md
@@ -0,0 +1,66 @@
+
+## 引入依赖
+
+在pom.xml文件中引入
+
+
+```
+
+ cn.langpy
+ ko-time
+ 2.0.3
+
+
+```
+
+## 配置
+
+在`application.properties`文件中进行配置
+
+* 必填配置
+
+>
+> ko-time.pointcut=`execution(public * com.huoyo..*.*(..))` # 需要监测的切面范围,参考aop的@pointcut 或者左侧常见问题
+>
+
+
+* 可选配置(以下配置一般不用设置)
+
+>
+> ko-time.enable=true # 是否开启koTime,默认开启,当为false时,关闭koTime
+> ko-time.log-enable=false # 是否开启控制输出,默认false
+> ko-time.log-language=chinese # 控制台输出语言(english/chinese)默认chinese
+> ko-time.threshold=800.0 # 时间阈值,用于前端展示,大于阈值显示红色,小于阈值显示绿色,默认800
+> ko-time.context-path=http://localhost:80 # 前端页面调用接口的上下文环境,无法自动获取时可手动配置 v2.0.1开始支持
+> ko-time.exception-enable=true # 是否开启异常检测,默认为false,开启后会对方法内部抛出的异常进行统计 v2.0.0开始支持
+> ko-time.auth-enable=true # 是否开启认证,默认为false,开启后需要登录才能访问调用链路 v2.0.2开始支持
+> ko-time.user-name=xxxx # 登录用户 v2.0.2开始支持
+> ko-time.password=xxxx # 登录密码 v2.0.2开始支持
+>
+
+## 访问
+
+> 注意:
+> 1.引入了上面的依赖和配置以后,确认项目中是否有aop相关的包,koTime使用了@Aspect注解,未引入的自行引入,如aspectj或者spring-boot-starter-aop
+> 2.做完前面的步骤,koTime的集成已经完毕,无需进行其他配置
+
+
+
+* 启动项目访问 `/koTime` 路径即可
+
+> 建议使用谷歌浏览器或者Edge浏览器,IE是不可能支持的
+
+如果项目自定义的contextpath,访问如`http://localhost:8080/xxx服务/koTime`
+
+如:application.properties中定义了 `server.servlet.context-path=/myservice`,那么访问路径为`http://localhost:8080/myservice/koTime`
+
+如果页面能正常显示,但是无法获取方法链路,可配置`ko-time.context-path=http://localhost:8080/myservice`
+
+
+---
+
+**为了让作者不要偷懒,督促他好好维护和开发,我准备用金钱对他进行鞭笞**
+
+
+
+
diff --git a/docs/v203/introduce.md b/docs/v203/introduce.md
new file mode 100644
index 0000000..e4a75c1
--- /dev/null
+++ b/docs/v203/introduce.md
@@ -0,0 +1,64 @@
+
+## 简介
+koTime是一个springboot项目性能分析工具,通过追踪方法调用链路以及对应的运行时长快速定位性能瓶颈
+
+## 预览
+
+http://huoyo.gitee.io/ko-time/example
+
+
+## 优点
+
+> * 实时监听方法,统计运行时长
+> * web展示方法调用链路,瓶颈可视化追踪
+
+
+
+
+## 版本说明
+
+> V1.0:基本功能
+
+> V1.1:接口统计
+
+> V1.2:不可用,错误版本
+
+> V1.3:添加日志、时间阈值可配置
+
+> V1.4:添加koTime.pointcut配置
+
+> V1.5:剔除lombok
+
+> V1.6:兼容thymeleaf
+
+> V1.7:修复未调用接口时No value present异
+
+> V1.8:支持Mybatis的Mapper监测、新增最大/最小运行时间、修复小数位数过长页面边界溢出的bug
+
+> V1.9:过度版本
+
+> V2.0.0:添加异常监测,开放数据接口,修复与swagger冲突bug,添加配置动态更新功能以及重构数据存储机制
+
+> V2.0.1:移除freemarker与thymeleaf;
+ 移除spring.profiles.active=koTime配置;
+ 优化方法链路获取机制(移除getAllStackTraces());
+ 替换layui;
+ 优化配置方式;
+ 优化页面显示
+
+> V2.0.2:新增登录认证;
+ 优化页面加载;
+ 修复方法循环调用栈溢出的bug
+
+> V2.0.3:优化页面方法节点拖拽;
+
+## 作者
+
+> Huoyo/Zhang Chang
+
+---
+
+**为了让作者不要偷懒,督促他好好维护和开发,我准备用金钱对他进行鞭笞**
+
+
+
diff --git a/docs/v203/kotime.png b/docs/v203/kotime.png
new file mode 100644
index 0000000..f939889
Binary files /dev/null and b/docs/v203/kotime.png differ
diff --git a/docs/v203/pay.jpg b/docs/v203/pay.jpg
new file mode 100644
index 0000000..a5fa50e
Binary files /dev/null and b/docs/v203/pay.jpg differ
diff --git a/docs/v203/pz.png b/docs/v203/pz.png
new file mode 100644
index 0000000..993cc13
Binary files /dev/null and b/docs/v203/pz.png differ
diff --git a/docs/v203/questions.md b/docs/v203/questions.md
new file mode 100644
index 0000000..73bcfc3
--- /dev/null
+++ b/docs/v203/questions.md
@@ -0,0 +1,94 @@
+## 额外依赖引入
+
+koTime使用了@Aspect注解,未引入 aop相关包的自行引入,如aspectj或者spring-boot-starter-aop
+
+
+## pointcut写法参考
+
+pointcut直接引用了aop中的写法,下面简要提供几个写法:
+
+假设项目的包路径为:
+
+```
+com.huoyo.demo
+ |-controller
+ |-service
+ |-mapper
+ |-others
+ |-other1
+ |-other2
+ |-Test.java
+
+```
+
+想要切`cn.langpy.demo`下面的所有方法(包括子包中的),可以写:
+
+> `execution(public * com.huoyo.demo..*.*(..))` #切记,是两个点.
+
+
+只想要切`cn.langpy.demo.controller`下面的类的所有方法(不包括子包的),可以写:
+
+> `execution(public * com.huoyo.demo.controller.*.*(..))` #切记,是一个点.
+
+只想要切`cn.langpy.demo.others`下面的类的所有方法(不包括other1和other2下面的),可以写:
+
+> `execution(public * com.huoyo.demo.others.*.*(..))`
+
+只想要切`cn.langpy.demo.others`下面的类的所有方法(包括other1和other2),可以写:
+
+> `execution(public * com.huoyo.demo.others..*.*(..))`
+
+更多写法请详细参考aop
+
+## 是否支持前后端分离项目
+
+支持!
+
+## 如何与shiro集成
+
+koTime没有做相关方面的限制,在shiro的配置中将相关路径放开即可,如:
+
+```Java
+ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
+/*设置过滤*/
+Map filterChainDefinitionMap = new LinkedHashMap();
+/*authc:所有url都必须认证通过才可以访问;*/
+/*anon:所有url都都可以匿名访问*/
+filterChainDefinitionMap.put("/koTime", "anon");
+filterChainDefinitionMap.put("/koTime/**", "anon");
+shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
+
+```
+
+## 运行时间计算
+
+运行时间分了三个指标:**平均运行时间、最大运行时间、最小运行时间**
+
+平均运行时间会将方法下每一次的运行时间与之前的求平均
+
+
+## 数据是否会保存
+
+目前暂不支持数据的存储,也就是每一次项目重启之后,以往的统计数据都归0
+
+## 集成是否需要复制资源文件
+
+不需要复制 static和template 等资源文件,引入依赖时已自动集成
+
+## 能正常启动但是页面样式不对
+
+打开f12查看静态资源路径加载是否正确,如果不正确,手动配置属性`ko-time.context-path=http://ip:port/contextPath`
+
+## V2.0.1开始更改了配置,V2.0.0的配置方式是否可用
+
+V2.0.1开始,两种配置均生效,建议使用新的配置方式
+
+## 问题咨询
+
+访问[koTime开源地址](https://gitee.com/huoyo/ko-time)进行咨询
+
+---
+
+**我觉得作者列的问题太少了,不能满足我,我准备用金钱对他进行鞭笞,并备注上本大爷的要求**
+
+
diff --git a/docs/v203/test3.png b/docs/v203/test3.png
new file mode 100644
index 0000000..456086b
Binary files /dev/null and b/docs/v203/test3.png differ
diff --git a/docs/v203/uiguide.md b/docs/v203/uiguide.md
new file mode 100644
index 0000000..23e8588
--- /dev/null
+++ b/docs/v203/uiguide.md
@@ -0,0 +1,46 @@
+
+
+## 首页面板
+
+首页有六个统计指标,分别是
+
+`总接口数`、`延迟响应接口数`、`正常响应接口数`、`平均响应`、`最大响应`、`最小响应`
+
+
+接口是否延迟取决于`ko-time.threshold`的配置,大于该阈值即表示延迟,显示为红色,如下图
+
+
+
+
+## 接口列表
+
+该列表展示的是监测到被请求过的接口,按照其平均响应时间倒序排列,超过`koTime.time.threshold`的接口显示红色,如下图:
+
+
+
+
+
+点击每一个接口后会显示该接口的方法调用链路、各个方法的运行时间以及该方法是否发生了异常,方法节点可拖动
+
+
+
+## 异常列表
+
+异常列表以异常为切入点,并显示每个异常发生的位置
+
+
+
+
+## 配置面板
+
+配置面板有四项配置,可在不重启系统的情况下进行配置
+
+`开启koTime监测` :该开关对应`ko-time.enable`,默认开启,当不需要koTime时可选择关闭
+
+`开启异常监测` :该开关对应`ko-time.exception-enable`,默认关闭,当需要时可选择开启
+
+`开启控制台日志` :该开关对应`ko-time.log-enable`,默认关闭,当需要时可选择开启,即可在控制台打印日志
+
+`方法运行时间阈值` :该开关对应`ko-time.threshold`,默认800ms,可调整,调整后接口列表和方法节点的颜色将以新的阈值变化
+
+
\ No newline at end of file
diff --git a/docs/v203/yc.png b/docs/v203/yc.png
new file mode 100644
index 0000000..5cb9007
Binary files /dev/null and b/docs/v203/yc.png differ
diff --git a/docs/v203/zl.png b/docs/v203/zl.png
new file mode 100644
index 0000000..6a980a3
Binary files /dev/null and b/docs/v203/zl.png differ
diff --git a/src/main/resources/static/graph.js b/src/main/resources/static/graph.js
deleted file mode 100644
index 82f58e5..0000000
--- a/src/main/resources/static/graph.js
+++ /dev/null
@@ -1 +0,0 @@
-function MetricFlow(domId,options){let styleDom=document.getElementsByTagName("style")[0];if(styleDom!=undefined){styleDom.innerHTML+='.ko-node{position:absolute;background-color:#5f665f;border:2px solid #4b804b;border-radius:5px;width:auto;}.ko-node .ko-node-title{padding-left:17px;padding-right:10px;background-color:#4b804b;color:white;}.ko-node .ko-node-body{list-style:none;margin-top:5px;}.ko-node li{padding-right:10px;margin-left:-23px;color:white;border-bottom:1px solid lightslategray;padding-bottom:2px;font-size:10px;}'}else{let style=document.createElement('style');style.type='text/css';style.rel='stylesheet';style.appendChild(document.createTextNode(".ko-node{position:absolute;background-color:#5f665f;border:2px solid #4b804b;border-radius:5px;width:auto;}.ko-node .ko-node-title{padding-left:17px;padding-right:10px;background-color:#4b804b;color:white;}.ko-node .ko-node-body{list-style:none;margin-top:5px;}.ko-node li{padding-right:10px;margin-left:-23px;color:white;border-bottom:1px solid lightslategray;padding-bottom:2px;font-size:10px;}"));let head=document.getElementsByTagName('head')[0];head.appendChild(style)};let o=new Object();o.allNodes=new Map();o.back=document.getElementById(domId);o.back.className='ko-node-back';let backWidth=Number(o.back.getAttribute("width").replace("px","").replace("%",""))*2;let backHeight=Number(o.back.getAttribute("height").replace("px","").replace("%",""))*1.5;o.back.innerHTML='\n ';o.svgBack=document.getElementById("svgBack");o.nodesBack=document.getElementById("methods");o.points=document.getElementById("points");o.relations=document.getElementById("relations");o.createNode=function(param,x,y){if(o.allNodes.get(param['id'])!=undefined){let node=document.getElementById(param['id']);return node};let nodeText="";let liText='';let liTextTemp='LiText';for(let index in param.data){let liBackColor=param.data[index]['background-color']||'#5f665f';liText+=liTextTemp.replace('LiText',param.data[index]['name']).replace('liBackColor',liBackColor)};let titleColor=param['title']['color']||'white';let titleBackColor=param['title']['background-color']||'#4b804b';let nodeBackgroundColor=param['background-color']||'#5f665f';let nodeBorderColor=param['border-color']||'#4b804b';nodeText=nodeText.replace('nodeBorderColor',nodeBorderColor).replace('nodeBackgroundColor',nodeBackgroundColor).replace('titleColor',titleColor).replace('titleBackColor',titleBackColor).replace('dataTitle',param['title']['name']).replace('idValue',param['id']).replace('topValue',(param['y']||y)).replace('leftValue',(param['x']||x)).replace('liBody',liText);o.nodesBack.innerHTML+=nodeText;let node=document.getElementById(param['id']);node.setAttribute('x',(param['x']||x));node.setAttribute('y',(param['y']||y));node.setAttribute('width',node.offsetWidth);node.setAttribute('height',node.offsetHeight);let nodeObject=new Map();nodeObject.set("ins",new Array());nodeObject.set("outs",new Array());nodeObject.set("node",node);o.allNodes.set(node.id,nodeObject);return node};o.createSimLink=function(source,target){let sourceTop=Number(source.getAttribute("y"));let sourceLeft=Number(source.getAttribute("x"));var sourceWidth=Number(source.getAttribute("width"));var sourceHeight=Number(source.getAttribute("height"));let targetTop=Number(target.getAttribute("y"));let targetLeft=Number(target.getAttribute("x"));var targetHeight=Number(target.getAttribute("height"));o.points.innerHTML+="";o.points.innerHTML+="";startX=(sourceLeft+sourceWidth)+2;startY=(sourceTop+sourceHeight/2-4);endX=targetLeft-14;endY=(targetTop+targetHeight/2-4);o.relations.innerHTML+=""};o.createLink=function(source,target){let sourceOuts=o.allNodes.get(source.id).get("outs");let targetIns=o.allNodes.get(target.id).get("ins");if(sourceOuts.indexOf("line"+source.id+target.id)>-1){return};let sourceTop=Number(source.getAttribute("y"));let sourceLeft=Number(source.getAttribute("x"));var sourceWidth=Number(source.getAttribute("width"));var sourceHeight=Number(source.getAttribute("height"));let targetTop=Number(target.getAttribute("y"));let targetLeft=Number(target.getAttribute("x"));var targetHeight=Number(target.getAttribute("height"));o.points.innerHTML+="";o.points.innerHTML+="";startX=(sourceLeft+sourceWidth)+2;startY=(sourceTop+sourceHeight/2-4);endX=targetLeft-14;endY=(targetTop+targetHeight/2-4);o.relations.innerHTML+="";sourceOuts.push('line-'+source.id+'-'+target.id);targetIns.push('line-'+source.id+'-'+target.id)};function getMouseTarget(eventElement){let clssName=eventElement.getAttribute('class');if(clssName=='ko-node'){return eventElement}else if(clssName=='ko-node-li'){return eventElement.parentNode.parentNode}else if(clssName=='ko-node-title'){return eventElement.parentNode}else if(clssName=='ko-node-body'){return eventElement.parentNode}else{return eventElement}};function reDrawNodeLines(node){let objectData=o.allNodes.get(node.id);if(objectData==undefined){return};let inIds=objectData.get("ins");for(let index in inIds){let lineId=inIds[index];let lineIdSplit=lineId.split('-');let sourceId=lineIdSplit[1];let targetId=lineIdSplit[2];if(document.getElementById(lineId)!=undefined){document.getElementById(lineId).remove();document.getElementById('pointstart'+sourceId+targetId).remove();document.getElementById('pointend'+sourceId+targetId).remove();o.createSimLink(document.getElementById(sourceId),node)}};let outIds=o.allNodes.get(node.id).get("outs");for(let index in outIds){let lineId=outIds[index];let lineIdSplit=lineId.split('-');let sourceId=lineIdSplit[1];let targetId=lineIdSplit[2];if(document.getElementById(lineId)!=undefined){document.getElementById(lineId).remove();document.getElementById('pointstart'+sourceId+targetId).remove();document.getElementById('pointend'+sourceId+targetId).remove();o.createSimLink(node,document.getElementById(targetId))}}};o.reDrawLines=function(){o.allNodes.forEach(function(nodeData,nodeId){reDrawNodeLines(document.getElementById(nodeId))})};o.moveNode;o.moveNodeX=0;o.moveNodeY=0;o.back.onmousedown=function(e){let mouseTarget=getMouseTarget(e.target);let clssName=mouseTarget.getAttribute('class');o.moveNodeX=e.clientX;o.moveNodeY=e.clientY;if(clssName=='ko-node'){o.moveNode=mouseTarget;o.moveNode.style.cursor='move';o.moveNode.onmousemove=nodeMove;o.moveNode.onmouseup=nodeMoveClose}};o.svgBack.onmousedown=function(e){let mouseTarget=getMouseTarget(e.target);let clssName=mouseTarget.getAttribute('class');o.moveNodeX=e.clientX;o.moveNodeY=e.clientY;if(clssName=='ko-node'){o.moveNode=mouseTarget;o.moveNode.style.cursor='move';o.moveNode.onmousemove=nodeMove;o.moveNode.onmouseup=nodeMoveClose}else{o.moveNode=mouseTarget;o.moveNode.style.cursor='move';o.moveNode.onmousemove=backMove;o.moveNode.onmouseup=nodeMoveClose}};function nodeMove(e){e=e||window.event;let offsetX=o.moveNodeX-e.clientX;let offsetY=o.moveNodeY-e.clientY;o.moveNodeX=e.clientX;o.moveNodeY=e.clientY;o.moveNode.style.top=(o.moveNode.offsetTop-offsetY)+"px";o.moveNode.style.left=(o.moveNode.offsetLeft-offsetX)+"px";o.moveNode.setAttribute('x',(o.moveNode.offsetLeft-offsetX));o.moveNode.setAttribute('y',(o.moveNode.offsetTop-offsetY));reDrawNodeLines(o.moveNode)};function backMove(e){e=e||window.event;let offsetX=o.moveNodeX-e.clientX;let offsetY=o.moveNodeY-e.clientY;o.moveNodeX=e.clientX;o.moveNodeY=e.clientY;o.allNodes.forEach(function(nodeData,nodeId){let moveNode=document.getElementById(nodeId);moveNode.style.top=(moveNode.offsetTop-offsetY)+"px";moveNode.style.left=(moveNode.offsetLeft-offsetX)+"px";moveNode.setAttribute('x',(moveNode.offsetLeft-offsetX));moveNode.setAttribute('y',(moveNode.offsetTop-offsetY));reDrawNodeLines(moveNode)})};function nodeMove(e){e=e||window.event;let offsetX=o.moveNodeX-e.clientX;let offsetY=o.moveNodeY-e.clientY;o.moveNodeX=e.clientX;o.moveNodeY=e.clientY;o.moveNode.style.top=(o.moveNode.offsetTop-offsetY)+"px";o.moveNode.style.left=(o.moveNode.offsetLeft-offsetX)+"px";o.moveNode.setAttribute('x',(o.moveNode.offsetLeft-offsetX));o.moveNode.setAttribute('y',(o.moveNode.offsetTop-offsetY));reDrawNodeLines(o.moveNode)};function nodeMoveClose(e){o.moveNode.style.cursor='default';o.moveNode.onmouseup=null;o.moveNode.onmousemove=null;o.moveNodeX=null;o.moveNodeY=null};o.back.onmousemove=function(e){var nx=e.clientX;var ny=e.clientY;var nl=nx-(o.moveNodeX-o.l);var nt=ny-(o.moveNodeY-o.t);if(o.isDragNode==true){o.moveNode.style.left=nl+'px';o.moveNode.style.top=nt+'px';o.reDrawLines(o.moveNode)}else if(o.isDragBack==true){o.allNodes.forEach(function(value,nodeKey){let pmoveNode=document.getElementById(nodeKey);let nl=nx-o.moveNodeX;let nt=ny-o.moveNodeY;if(nl>10){pmoveNode.style.left=Number(pmoveNode.style.left.replace('px',''))+10+'px'}else if(nl<-10){pmoveNode.style.left=Number(pmoveNode.style.left.replace('px',''))-10+'px'};if(nt>6){pmoveNode.style.top=Number(pmoveNode.style.top.replace('px',''))+10+'px'}else if(nt<-6){pmoveNode.style.top=Number(pmoveNode.style.top.replace('px',''))-10+'px'}});o.reDrawLines()}};o.back.onmouseup=function(e){o.isDragNode=false;o.isDragBack=false;if((o.moveNode!=undefined)&&(o.moveNode.hasOwnProperty("style")==true)&&(o.moveNode.style.hasOwnProperty("cursor")==true)){o.moveNode.style.cursor='default'}};return o};
\ No newline at end of file