From b4c43a2138a228de29c15d663cde1f6d81cf9ac9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=ED=98=84=EC=84=B1=ED=95=84?= Date: Sun, 7 Jan 2024 17:34:19 +0900 Subject: [PATCH] =?UTF-8?q?=EC=8B=9C=EB=82=98=EB=A6=AC=EC=98=A4=20?= =?UTF-8?q?=EA=B4=80=EB=A6=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/ApiScenarioMgmtController.java | 61 + .../client/dto/ApiScenarioDTO.java | 44 + .../client/entity/ApiScenario.java | 64 + .../client/mapper/ApiScenarioMapper.java | 21 + .../repository/ApiScenarioRepository.java | 13 + .../service/ApiScenarioMgmtService.java | 49 + .../exception/PortalErrorController.java | 13 + src/main/resources/static/css/custom.css | 407 +- src/main/resources/static/js/APIScenario.js | 285 + .../static/js/APIScenarioExecutor.js | 111 + src/main/resources/static/js/APITester.js | 305 +- .../static/plugins/drawflow/drawflow.js | 1953 ++ .../static/plugins/drawflow/drawflow.min.css | 1 + .../static/plugins/drawflow/drawflow.min.js | 1 + .../static/plugins/drawflow/drawflow.style.js | 1 + .../images/ui-icons_444444_256x240.png | Bin 0 -> 7142 bytes .../images/ui-icons_555555_256x240.png | Bin 0 -> 7126 bytes .../images/ui-icons_777620_256x240.png | Bin 0 -> 4670 bytes .../images/ui-icons_777777_256x240.png | Bin 0 -> 7163 bytes .../images/ui-icons_cc0000_256x240.png | Bin 0 -> 4670 bytes .../images/ui-icons_ffffff_256x240.png | Bin 0 -> 6539 bytes .../static/plugins/jquery-ui/index.html | 503 + .../static/plugins/jquery-ui/jquery-ui.css | 1315 ++ .../static/plugins/jquery-ui/jquery-ui.js | 19062 ++++++++++++++++ .../plugins/jquery-ui/jquery-ui.min.css | 7 + .../static/plugins/jquery-ui/jquery-ui.min.js | 6 + .../plugins/jquery-ui/jquery-ui.structure.css | 886 + .../jquery-ui/jquery-ui.structure.min.css | 5 + .../plugins/jquery-ui/jquery-ui.theme.css | 446 + .../plugins/jquery-ui/jquery-ui.theme.min.css | 5 + .../static/plugins/jquery-ui/package.json | 74 + 31 files changed, 25435 insertions(+), 203 deletions(-) create mode 100644 src/main/java/com/eactive/httpmockserver/client/controller/ApiScenarioMgmtController.java create mode 100644 src/main/java/com/eactive/httpmockserver/client/dto/ApiScenarioDTO.java create mode 100644 src/main/java/com/eactive/httpmockserver/client/entity/ApiScenario.java create mode 100644 src/main/java/com/eactive/httpmockserver/client/mapper/ApiScenarioMapper.java create mode 100644 src/main/java/com/eactive/httpmockserver/client/repository/ApiScenarioRepository.java create mode 100644 src/main/java/com/eactive/httpmockserver/client/service/ApiScenarioMgmtService.java create mode 100644 src/main/resources/static/js/APIScenario.js create mode 100644 src/main/resources/static/js/APIScenarioExecutor.js create mode 100644 src/main/resources/static/plugins/drawflow/drawflow.js create mode 100644 src/main/resources/static/plugins/drawflow/drawflow.min.css create mode 100644 src/main/resources/static/plugins/drawflow/drawflow.min.js create mode 100644 src/main/resources/static/plugins/drawflow/drawflow.style.js create mode 100644 src/main/resources/static/plugins/jquery-ui/images/ui-icons_444444_256x240.png create mode 100644 src/main/resources/static/plugins/jquery-ui/images/ui-icons_555555_256x240.png create mode 100644 src/main/resources/static/plugins/jquery-ui/images/ui-icons_777620_256x240.png create mode 100644 src/main/resources/static/plugins/jquery-ui/images/ui-icons_777777_256x240.png create mode 100644 src/main/resources/static/plugins/jquery-ui/images/ui-icons_cc0000_256x240.png create mode 100644 src/main/resources/static/plugins/jquery-ui/images/ui-icons_ffffff_256x240.png create mode 100644 src/main/resources/static/plugins/jquery-ui/index.html create mode 100644 src/main/resources/static/plugins/jquery-ui/jquery-ui.css create mode 100644 src/main/resources/static/plugins/jquery-ui/jquery-ui.js create mode 100644 src/main/resources/static/plugins/jquery-ui/jquery-ui.min.css create mode 100644 src/main/resources/static/plugins/jquery-ui/jquery-ui.min.js create mode 100644 src/main/resources/static/plugins/jquery-ui/jquery-ui.structure.css create mode 100644 src/main/resources/static/plugins/jquery-ui/jquery-ui.structure.min.css create mode 100644 src/main/resources/static/plugins/jquery-ui/jquery-ui.theme.css create mode 100644 src/main/resources/static/plugins/jquery-ui/jquery-ui.theme.min.css create mode 100644 src/main/resources/static/plugins/jquery-ui/package.json diff --git a/src/main/java/com/eactive/httpmockserver/client/controller/ApiScenarioMgmtController.java b/src/main/java/com/eactive/httpmockserver/client/controller/ApiScenarioMgmtController.java new file mode 100644 index 0000000..40bdec7 --- /dev/null +++ b/src/main/java/com/eactive/httpmockserver/client/controller/ApiScenarioMgmtController.java @@ -0,0 +1,61 @@ +package com.eactive.httpmockserver.client.controller; + +import com.eactive.httpmockserver.client.dto.ApiScenarioDTO; +import com.eactive.httpmockserver.client.entity.ApiScenario; +import com.eactive.httpmockserver.client.mapper.ApiScenarioMapper; +import com.eactive.httpmockserver.client.service.ApiScenarioMgmtService; +import com.eactive.httpmockserver.common.util.SecurityUtil; +import com.eactive.httpmockserver.user.entity.StaffUser; +import com.eactive.httpmockserver.user.service.UserService; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/mgmt/api_scenario") +public class ApiScenarioMgmtController { + + private final ApiScenarioMgmtService apiScenarioMgmtService; + + private final ApiScenarioMapper apiScenarioMapper; + + private final UserService userService; + + public ApiScenarioMgmtController(ApiScenarioMgmtService apiScenarioMgmtService, ApiScenarioMapper apiScenarioMapper, UserService userService) { + this.apiScenarioMgmtService = apiScenarioMgmtService; + this.apiScenarioMapper = apiScenarioMapper; + this.userService = userService; + } + + @GetMapping("/list.do") + public ResponseEntity> listScenarios() { + List scenarios = apiScenarioMgmtService.findAll(); + return ResponseEntity.ok(apiScenarioMapper.toDtoList(scenarios)); + } + + @PostMapping("/create.do") + public ResponseEntity createScenario(@RequestBody ApiScenarioDTO apiScenarioDto) { + ApiScenario apiScenario = apiScenarioMapper.map(apiScenarioDto); + StaffUser user = userService.findByEsntlId(SecurityUtil.getCurrentUserEsntlId()); + apiScenario.setOwner(user); + ApiScenario createdScenario = apiScenarioMgmtService.createApiScenario(apiScenario); + return new ResponseEntity<>(apiScenarioMapper.map(createdScenario), HttpStatus.CREATED); + } + + + @PutMapping("/update.do") + public ResponseEntity updateScenario(@RequestBody ApiScenarioDTO apiScenarioDto) { + ApiScenario updatedApiScenario = apiScenarioMapper.map(apiScenarioDto); + ApiScenario updatedScenario = apiScenarioMgmtService.updateApiScenario(apiScenarioDto.getId(), updatedApiScenario); + return ResponseEntity.ok(apiScenarioMapper.map(updatedScenario)); + } + + @PostMapping("/delete.do") + public ResponseEntity deleteScenario(@RequestBody ApiScenarioDTO apiScenarioDto) { + apiScenarioMgmtService.deleteApiScenario(apiScenarioDto.getId()); + return ResponseEntity.ok().build(); + } + +} diff --git a/src/main/java/com/eactive/httpmockserver/client/dto/ApiScenarioDTO.java b/src/main/java/com/eactive/httpmockserver/client/dto/ApiScenarioDTO.java new file mode 100644 index 0000000..fb30449 --- /dev/null +++ b/src/main/java/com/eactive/httpmockserver/client/dto/ApiScenarioDTO.java @@ -0,0 +1,44 @@ +package com.eactive.httpmockserver.client.dto; + +public class ApiScenarioDTO { + + private String id; + + private String name; + + private String description; + + private String scenario; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getScenario() { + return scenario; + } + + public void setScenario(String scenario) { + this.scenario = scenario; + } +} diff --git a/src/main/java/com/eactive/httpmockserver/client/entity/ApiScenario.java b/src/main/java/com/eactive/httpmockserver/client/entity/ApiScenario.java new file mode 100644 index 0000000..17b95f9 --- /dev/null +++ b/src/main/java/com/eactive/httpmockserver/client/entity/ApiScenario.java @@ -0,0 +1,64 @@ +package com.eactive.httpmockserver.client.entity; + +import com.eactive.httpmockserver.user.entity.StaffUser; + +import javax.persistence.*; + +@Entity +@Table(name = "API_SCENARIO") +public class ApiScenario { + + @Id + private String id; //uuid + + private String name; + + private String description; + + @ManyToOne + @JoinColumn(name = "USER_ID") + private StaffUser owner; + + @Lob + private String scenario; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getScenario() { + return scenario; + } + + public void setScenario(String scenario) { + this.scenario = scenario; + } + + public StaffUser getOwner() { + return owner; + } + + public void setOwner(StaffUser owner) { + this.owner = owner; + } +} diff --git a/src/main/java/com/eactive/httpmockserver/client/mapper/ApiScenarioMapper.java b/src/main/java/com/eactive/httpmockserver/client/mapper/ApiScenarioMapper.java new file mode 100644 index 0000000..377de1d --- /dev/null +++ b/src/main/java/com/eactive/httpmockserver/client/mapper/ApiScenarioMapper.java @@ -0,0 +1,21 @@ +package com.eactive.httpmockserver.client.mapper; + +import com.eactive.httpmockserver.client.dto.ApiScenarioDTO; +import com.eactive.httpmockserver.client.entity.ApiScenario; +import org.mapstruct.Mapper; +import org.mapstruct.ReportingPolicy; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Mapper(componentModel = "spring", + unmappedTargetPolicy = ReportingPolicy.IGNORE) +@Component +public interface ApiScenarioMapper { + + ApiScenario map(ApiScenarioDTO dto); + + ApiScenarioDTO map(ApiScenario scenario); + + List toDtoList(List scenarios); +} diff --git a/src/main/java/com/eactive/httpmockserver/client/repository/ApiScenarioRepository.java b/src/main/java/com/eactive/httpmockserver/client/repository/ApiScenarioRepository.java new file mode 100644 index 0000000..b2816a0 --- /dev/null +++ b/src/main/java/com/eactive/httpmockserver/client/repository/ApiScenarioRepository.java @@ -0,0 +1,13 @@ +package com.eactive.httpmockserver.client.repository; + +import com.eactive.httpmockserver.client.entity.ApiScenario; +import com.eactive.httpmockserver.user.entity.StaffUser; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; + +import java.util.List; + +public interface ApiScenarioRepository extends JpaRepository, JpaSpecificationExecutor { + + List findAllByOwner(StaffUser owner); +} diff --git a/src/main/java/com/eactive/httpmockserver/client/service/ApiScenarioMgmtService.java b/src/main/java/com/eactive/httpmockserver/client/service/ApiScenarioMgmtService.java new file mode 100644 index 0000000..d09675d --- /dev/null +++ b/src/main/java/com/eactive/httpmockserver/client/service/ApiScenarioMgmtService.java @@ -0,0 +1,49 @@ +package com.eactive.httpmockserver.client.service; + +import com.eactive.httpmockserver.client.entity.ApiScenario; +import com.eactive.httpmockserver.client.repository.ApiScenarioRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.transaction.Transactional; +import java.util.List; +import java.util.UUID; + +@Service +@Transactional +public class ApiScenarioMgmtService { + + @Autowired + ApiScenarioRepository apiScenarioRepository; + + + public List findAll() { + return apiScenarioRepository.findAll(); + } + + public ApiScenario createApiScenario(ApiScenario apiScenario) { + apiScenario.setId(UUID.randomUUID().toString()); + return apiScenarioRepository.save(apiScenario); + } + + + public ApiScenario updateApiScenario(String id, ApiScenario updatedApiScenario) { + return apiScenarioRepository.findById(id) + .map(apiScenario -> { + apiScenario.setName(updatedApiScenario.getName()); + apiScenario.setDescription(updatedApiScenario.getDescription()); + apiScenario.setScenario(updatedApiScenario.getScenario()); + return apiScenarioRepository.save(apiScenario); + }).orElseGet(() -> { + // If the ApiScenario with the given id doesn't exist, create a new one + updatedApiScenario.setId(id); + return apiScenarioRepository.save(updatedApiScenario); + }); + } + + // Delete operation + public void deleteApiScenario(String id) { + apiScenarioRepository.deleteById(id); + } + +} diff --git a/src/main/java/com/eactive/httpmockserver/common/exception/PortalErrorController.java b/src/main/java/com/eactive/httpmockserver/common/exception/PortalErrorController.java index 3f1636c..e69ff24 100644 --- a/src/main/java/com/eactive/httpmockserver/common/exception/PortalErrorController.java +++ b/src/main/java/com/eactive/httpmockserver/common/exception/PortalErrorController.java @@ -4,6 +4,7 @@ import org.springframework.boot.web.servlet.error.ErrorController; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; import javax.servlet.RequestDispatcher; import javax.servlet.http.HttpServletRequest; @@ -23,4 +24,16 @@ public class PortalErrorController implements ErrorController { return "redirect:/"; } + @PostMapping("/error") + public String handleErrorPost(HttpServletRequest request, ModelMap model) { + Object status = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE); + + if (status != null) { + model.addAttribute("status", status); + return "error"; + } + + return "redirect:/"; + } + } diff --git a/src/main/resources/static/css/custom.css b/src/main/resources/static/css/custom.css index c88306a..6738901 100644 --- a/src/main/resources/static/css/custom.css +++ b/src/main/resources/static/css/custom.css @@ -6,6 +6,13 @@ body { font-weight: bold; } +:root { + --border-color: #cacaca; + --background-color: #ffffff; + + --background-box-title: #f7f7f7; +} + a { color: #000 !important; text-decoration: none !important; @@ -52,6 +59,7 @@ a.btn.btn-primary { color: #fff !important; text-decoration: none !important; } + .btn-primary { background-color: #39077A; border-color: #39077A; @@ -63,7 +71,7 @@ a.btn.btn-primary { } .list-group-item.active > a { - color : #fff !important; + color: #fff !important; } .btn-primary:hover, .btn-primary:focus, .btn-primary:active, .btn-primary.active, .open .dropdown-toggle.btn-primary { @@ -525,7 +533,7 @@ a.btn.btn-primary { display: block; position: relative; min-width: 1170px; - background-color : #D4ECF1; + background-color: #D4ECF1; } .pt-masthead h1 { @@ -638,13 +646,13 @@ a.btn.btn-primary { } } -@media (max-width: 849px){ +@media (max-width: 849px) { .hide { display: none !important; } } -@media (min-width: 850px){ +@media (min-width: 850px) { .main_menu { display: none !important; } @@ -680,23 +688,19 @@ a.btn.btn-primary { font-weight: 600 } -@media (min-width: 768px) { - .pt-links { - top: 5rem; - display: block !important; - height: calc(100vh - 7rem); - padding-left: .25rem; - margin-left: -.25rem; - overflow-y: auto - } +.pt-links { + top: 5rem; + display: block !important; + height: calc(100vh - 7rem); + padding-left: .25rem; + margin-left: -.25rem; + overflow-y: auto } -@media (max-width: 767.98px) { - .pt-links > ul { - padding: 1.5rem .75rem; - background-color: #f8f9fa; - border-bottom: 1px solid #e9ecef - } +.pt-links > ul { + /*padding: 1.5rem .75rem;*/ + background-color: #f8f9fa; + border-bottom: 1px solid #e9ecef } .pt-links a { @@ -756,6 +760,123 @@ a.btn.btn-primary { color: rgba(0, 0, 0, 0.85) } +.full-screen { + background-color: #ffffff; + position: fixed; /* Fixed position to cover the whole screen */ + top: 0; + left: 0; + width: 100vw; /* Full viewport width */ + height: 100vh; /* Full viewport height */ + z-index: 9999; /* High z-index to be on top of other content */ + overflow: auto; /* Add scroll for overflowing content */ +} + +.api-tester-layout { + display: flex; + flex-direction: column; + overflow: hidden; +} + +.api-tester-layout .tester { + display: flex; +} + +.api-scenario, .api-catalog, .api-tester { + transition: transform 0.5s ease; /* Add transition to each child */ + min-height: 100px; /* Adjust as needed */ +} + +.api-catalog { + flex: 0 0 200px; /* Fixed width, not flexible */ + /*order: 1; !* Keep the catalog in the middle *!*/ +} + +.api-scenario { + flex: 1; /* Flexible size */ + display: flex; +} + +.api-scenario-toolbar { + margin: 5px; +} + +.api-scenario .api-scenario-sidebar { + width: 200px; +} + +.tester-toolbar { + height: 40px; + background: rgba(0, 0, 0, .03); + padding: 5px; +} + +.api-scenario .api-scenario-view { + display: flex; + flex: 1; + flex-direction: column; + padding: 5px; + width: calc(100vw - 400px); +} + +.api-scenario .api-scenario-content { + flex: 1; + padding: 5px; + display: flex; + flex-direction: column; +} + +.api-scenario .api-scenario-content .api-scenario-editor { + flex: 1; + padding: 5px; + display: flex; + flex-direction: column; +} + +.scenario_editor { + flex: 1; + display: flex; + flex-direction: row; +} + +.hidden { + display: none; +} + +.fullHeight { + height: 100%; +} + +.halfHeight { + height: 50%; +} + +.api-scenario-output { + flex: 1; + display: flex; + flex-direction: column; + padding: 5px; +} + +.api-scenario-output-header { + height: 50px; + border: 1px solid grey; + padding: 5px; +} + +.api-scenario-output-body { + flex: 1; + height: 50px; + border: 1px solid grey; + padding: 5px; +} + + +.api-tester { + flex: 1; /* Flexible size */ + order: 2; /* Positions to the right of .api-catalog */ +} + + @media (min-width: 768px) { .pt-layout { display: grid; @@ -1452,13 +1573,14 @@ footer div.foot_info span { letter-spacing: .2px; } -@media(max-width: 1459px){ - .header{ +@media (max-width: 1459px) { + .header { max-width: 100% !important; } } -@media(min-width: 1460px){ - .header{ + +@media (min-width: 1460px) { + .header { max-width: 1460px !important; } } @@ -1467,7 +1589,7 @@ footer div.foot_info span { overflow: hidden; } -@media(max-width: 1919px){ +@media (max-width: 1919px) { .figure_img { width: 100%; @@ -1477,7 +1599,8 @@ footer div.foot_info span { object-position: center; } } -@media(min-width: 1920px){ + +@media (min-width: 1920px) { .figure_img { width: 1900px; display: block; @@ -1589,7 +1712,10 @@ footer div.foot_info span { .CodeMirror-fullscreen { position: fixed !important; - top: 0; left: 0; right: 0; bottom: 0; + top: 0; + left: 0; + right: 0; + bottom: 0; height: auto !important; z-index: 1000; } @@ -1615,17 +1741,17 @@ footer div.foot_info span { } .dev { - background-color : #f74140 !important; - color : white !important; + background-color: #f74140 !important; + color: white !important; } .prod { - background-color : #49cc90 !important; - color : white !important; + background-color: #49cc90 !important; + color: white !important; } .current { - color : #39077A !important; + color: #39077A !important; } .reset-button { @@ -1641,4 +1767,223 @@ footer div.foot_info span { /* Style the icon */ display: inline-block; margin-right: 5px; /* Adjust this value as per your requirement */ +} + +#drawflow { + position: relative; + width: calc(100vw - 440px); + height: calc(100vh - 520px); + background: var(--background-color); + background-size: 25px 25px; + background-image: linear-gradient(to right, #f1f1f1 1px, transparent 1px), linear-gradient(to bottom, #f1f1f1 1px, transparent 1px); + overflow: auto; +} + +.drag-drawflow { + line-height: 50px; + border-bottom: 1px solid var(--border-color); + padding-left: 20px; + cursor: move; + user-select: none; +} + +.drawflow .drawflow-node { + background: var(--background-color); + /*border: 1px solid var(--border-color);*/ + -webkit-box-shadow: 0 2px 15px 2px var(--border-color); + box-shadow: 0 2px 15px 2px var(--border-color); + /*padding: 0px;*/ + /*width: 200px;*/ +} + +.drawflow .drawflow-node.selected { + background: white; + border: 1px solid #4ea9ff; + -webkit-box-shadow: 0 2px 20px 2px #4ea9ff; + box-shadow: 0 2px 20px 2px #4ea9ff; +} + +.drawflow .drawflow-node.start { + width: 100px; /* or any size */ + height: 100px; /* should be the same as width for a perfect diamond */ + border-radius: 50%; +} + +.drawflow .drawflow-node.api { + padding: 0; +} + +.drawflow .drawflow-node.api .output { + right: 10px; +} + +.drawflow .drawflow-node.api .input { + left: -10px; + background: white; +} + +.drawflow .drawflow-node.selected .title-box { + color: #22598c; +} + +.drawflow .connection .main-path { + stroke: #4ea9ff; + stroke-width: 3px; +} + +/*.drawflow .drawflow-node .input, .drawflow .drawflow-node .output {*/ +/* height: 15px;*/ +/* width: 15px;*/ +/* border: 2px solid var(--border-color);*/ +/*}*/ + +.drawflow .drawflow-node .input:hover, .drawflow .drawflow-node .output:hover { + background: #4ea9ff; +} + +/*.drawflow .drawflow-node .output {*/ +/* right: 10px;*/ +/*}*/ + +/*.drawflow .drawflow-node .input {*/ +/* left: -10px;*/ +/* background: white;*/ +/*}*/ + +.drawflow > .drawflow-delete { + border: 2px solid #43b993; + background: white; + color: #43b993; + -webkit-box-shadow: 0 2px 20px 2px #43b993; + box-shadow: 0 2px 20px 2px #43b993; +} + +.drawflow-delete { + border: 2px solid #4ea9ff; + background: white; + color: #4ea9ff; + -webkit-box-shadow: 0 2px 20px 2px #4ea9ff; + box-shadow: 0 2px 20px 2px #4ea9ff; +} + +.drawflow-node .title-box { + height: 50px; + line-height: 50px; + background: var(--background-box-title); + border-bottom: 1px solid #e9e9e9; + border-radius: 4px 4px 0px 0px; + padding-left: 10px; +} + +.drawflow .title-box svg { + position: initial; +} + +.drawflow-node .box { + padding: 10px 20px 20px 20px; + font-size: 14px; + color: #555555; + +} + +.drawflow-node .box p { + margin-top: 5px; + margin-bottom: 5px; +} + + +.drawflow-node input, .drawflow-node select, .drawflow-node textarea { + border-radius: 4px; + border: 1px solid var(--border-color); + height: 30px; + line-height: 30px; + font-size: 16px; + width: 158px; + color: #555555; +} + +.drawflow-node textarea { + height: 100px; +} + + +.drawflow .connection .point { + stroke: var(--border-color); + stroke-width: 2; + fill: white; + +} + +.drawflow .connection .point.selected, .drawflow .connection .point:hover { + fill: #4ea9ff; +} + +.btn-export { + float: right; + position: absolute; + top: 10px; + right: 10px; + color: white; + font-weight: bold; + border: 1px solid #0e5ba3; + background: #4ea9ff; + padding: 5px 10px; + border-radius: 4px; + cursor: pointer; + z-index: 5; +} + +.btn-clear { + float: right; + position: absolute; + top: 10px; + right: 85px; + color: white; + font-weight: bold; + border: 1px solid #96015b; + background: #e3195a; + padding: 5px 10px; + border-radius: 4px; + cursor: pointer; + z-index: 5; +} + +.btn-lock { + float: right; + position: absolute; + bottom: 10px; + right: 140px; + display: flex; + font-size: 24px; + color: white; + padding: 5px 10px; + background: #555555; + border-radius: 4px; + border-right: 1px solid var(--border-color); + z-index: 5; + cursor: pointer; +} + +.bar-zoom { + float: right; + position: absolute; + bottom: 10px; + right: 10px; + display: flex; + font-size: 24px; + color: white; + padding: 5px 10px; + background: #555555; + border-radius: 4px; + border-right: 1px solid var(--border-color); + z-index: 5; +} + +.bar-zoom svg { + cursor: pointer; + padding-left: 20px; +} + +.bar-zoom svg:nth-child(1) { + padding-left: 20px; } \ No newline at end of file diff --git a/src/main/resources/static/js/APIScenario.js b/src/main/resources/static/js/APIScenario.js new file mode 100644 index 0000000..abf7ddc --- /dev/null +++ b/src/main/resources/static/js/APIScenario.js @@ -0,0 +1,285 @@ +require.config({paths: {'vs': '/plugins/vs'}}); + +class APIScenario { + + constructor() { + this.scenarioList = []; + this.scenarioTab = []; + this.currentIndex = -1; + this.currentScenario = null; + } + + init() { + console.log('init'); + this.loadScenarioList(); + require(['vs/editor/editor.main'], () => { + this.outputEditor = monaco.editor.create(document.getElementById('output'), { + value: '', + language: 'text/plain', + theme: 'vs-light', + automaticLayout: true + }); + }); + this.bindEvents(); + + let id = document.getElementById('drawflow'); + this.editor = new Drawflow(id); + this.editor.reroute = true; + this.editor.reroute_fix_curvature = true; + this.editor.force_first_input = true; + this.editor.start(); + let start = ` +
+
Start
+
+ `; + this.editor.on('connectionCreated', (connection) => { + console.log('Connection created'); + console.log(connection); + }); + this.showOutput = true; + + this.editor.addNode('Start', 0, 1, 100, 100, 'start', {}, start); + + } + + loadScenarioList() { + const me = this; + this.currentAjaxRequest = $.ajax({ + url: '/mgmt/api_scenario/list.do', + type: 'GET', + contentType: 'application/json', + success: function (data) { + me.scenarioList = data; + }, + error: function (response, textStatus, errorThrown) { + me.hideLoadingOverlay(); + $('.toast-body').text(response.responseJSON.error); + $('.toast').toast('show'); + }, + complete: function () { + me.renderScenarioList(); + me.hideLoadingOverlay(); + } + }); + } + + getScenarioList() { + return this.scenarioList; + } + + openScenario(event) { + event.preventDefault(); + let scenarioId = $(event.target).closest('li').data('id'); + let scenario = this.getScenario(scenarioId); + this.openTab(scenario); + } + + openTab(scenario) { + console.log('openTab'); + console.log(scenario); + this.currentScenario = scenario; + let openTab = this.scenarioTab.find((tab) => tab.id === scenario.id); + if (openTab) { + this.currentIndex = this.scenarioTab.indexOf(openTab); + //$(`#api_scenario_tab_${id}`).tab('show'); // API request 탭 활성화 + } else { + this.scenarioTab.push(scenario); + this.renderScenarioTab(scenario); + } + } + + renderScenarioTab(scenario) { + this.renderTabHeader(scenario); + this.renderTabContent(scenario); + } + + renderTabHeader(scenario) { + console.log('renderTabHeader'); + + } + + renderTabContent(scenario) { + console.log('renderTabContent') + + } + + getScenario(scenarioId) { + return this.getScenarioList().find((scenario) => scenario.id === scenarioId); + + } + + showLoadingOverlay() { + $("#loading-overlay").show(); + } + + hideLoadingOverlay() { + $("#loading-overlay").hide(); + } + + showNewScenarioModal() { + $('#new_scenario_modal').find('input').val(''); + $('#new_scenario_modal').modal('show'); + } + + saveScenario() { + const name = $('#new_scenario_name').val(); + const me = this; + me.showLoadingOverlay(); + this.currentAjaxRequest = $.ajax({ + url: '/mgmt/api_scenario/create.do', + type: 'POST', + contentType: 'application/json', + data: JSON.stringify({name: name, scenario: "", description: ""}), + error: function (response, textStatus, errorThrown) { + me.hideLoadingOverlay(); + $('.toast-body').text(response.responseJSON.error); + $('.toast').toast('show'); + }, + complete: function () { + me.loadScenarioList(); + me.hideLoadingOverlay(); + $('#new_scenario_modal').modal('hide'); + } + }); + } + + removeScenario(scenarioId) { + + } + + toggleOutput() { + // Define your selectors as constants for easy changes and better readability + const scenarioContentSelector = '.api-scenario-content'; + const scenarioOutputSelector = '.api-scenario-output'; + const scenarioOutputBodySelector = '.api-scenario-output-body'; + const drawflowSelector = '#drawflow'; + const scenarioEditorSelector = '.scenario_editor'; + + // Ensure parentHeight is a number + let parentHeight = parseInt($(scenarioContentSelector).css('height'), 10); + + // Toggle the showOutput state + this.showOutput = !this.showOutput; + + if (!this.showOutput) { + $(scenarioOutputSelector).css('flex', '0'); + $(scenarioOutputBodySelector).hide(); + + let editorHeight = $(scenarioEditorSelector).css('height'); + $(drawflowSelector).css('height', editorHeight); + $(scenarioOutputSelector).removeClass('halfHeight'); + $(drawflowSelector).removeClass('halfHeight'); + } else { + $(scenarioOutputSelector).css('flex', '1'); + $(scenarioOutputSelector).addClass('halfHeight'); + $(scenarioOutputBodySelector).show(); + $(drawflowSelector).addClass('halfHeight'); + $(drawflowSelector).css('height', parentHeight / 2); + } + + // Adjustments for when parentHeight isn't a valid number + if (isNaN(parentHeight)) { + console.error('parentHeight is not a number. Check the height of the api-scenario-content element.'); + // Fallback or additional error handling can be placed here + } + } + + + resizeEditor() { + //FIXME: 창 크기 변경시 자동으로 editor 크기가 조정되지 않아서, 0으로 강제 변경후 다시 layout() 호출 + this.outputEditor.layout({ + width: 0 + }); + this.outputEditor.layout({}); + + } + + runScript() { + let graph = APIScenarioExecutor.extractGraphFromStart(this.editor.export().drawflow.Home.data); + this.executor = new APIScenarioExecutor(graph); + this.outputEditor.setValue(JSON.stringify(graph, null, 4)); + } + + runScenarioAll() { + if (!this.executor) { + this.runScript(); + } + this.executor.executeAll(); + } + + + runScenarioStep() { + if (!this.executor) { + this.runScript(); + } + this.executor.executeCurrentNode(); + this.executor.moveToNextNode(); + } + + resetScenario() { + + } + + pauseScenario() { + + } + + stopScenario() { + + } + + bindEvents() { + const events = [ + {type: 'click', selector: '.open_scenario', action: this.openScenario.bind(this)}, + {type: 'click', selector: '.export', action: this.runScript.bind(this)}, + {type: 'click', selector: '.toggle_output', action: this.toggleOutput.bind(this)}, + {type: 'click', selector: '.run_scenario_step', action: this.runScenarioStep.bind(this)}, + {type: 'click', selector: '.run_scenario_all', action: this.runScenarioAll.bind(this)}, + {type: 'click', selector: '.reset_scenario', action: this.resetScenario.bind(this)}, + {type: 'click', selector: '.pause_scenario', action: this.pauseScenario.bind(this)}, + {type: 'click', selector: '.stop_scenario', action: this.stopScenario.bind(this)}, + {type: 'click', selector: '#new_scenario', action: this.showNewScenarioModal.bind(this)}, + {type: 'click', selector: '.save_scenario', action: this.saveScenario.bind(this)}, + ]; + + for (let event of events) { + $(document).on(event.type, event.selector, event.action); + } + + window.addEventListener('resize', this.resizeEditor.bind(this)); + var me = this; + + $('#drawflow').droppable({ + drop: function (event, ui) { + const x = ui.offset.left - $(this).offset().left; + const y = ui.offset.top - $(this).offset().top; + + const dataset = ui.draggable[0].dataset; + var node = `
API
${dataset.name}
`; + + me.editor.addNode(dataset.name, 1, 1, x, y, dataset.nodeType, dataset, node); + } + }); + } + + scenarioListTemplate(scenario) { + return ` +
  • + ${scenario.name} +
    + + +
    +
  • + `; + } + + renderScenarioList() { + let scenarioList = this.getScenarioList(); + let scenarioListHtml = scenarioList.map((scenario) => this.scenarioListTemplate(scenario)).join(''); + $('.api-scenario-list').html(scenarioListHtml); + } + + +} \ No newline at end of file diff --git a/src/main/resources/static/js/APIScenarioExecutor.js b/src/main/resources/static/js/APIScenarioExecutor.js new file mode 100644 index 0000000..b0902b9 --- /dev/null +++ b/src/main/resources/static/js/APIScenarioExecutor.js @@ -0,0 +1,111 @@ +class APIScenarioExecutor { + constructor(graph) { + this.graph = graph; // The graph data + this.currentNodeId = this.findStartNodeId(); // Initialize at the 'start' node + this.apiClient = new APIClient(); + this.visitedNodes = new Set(); // Keep track of visited nodes + } + + // Helper method to find the start node ID + findStartNodeId() { + for (let nodeId in this.graph) { + if (this.graph[nodeId].class === 'start') { + return nodeId; + } + } + return null; // Return null if no start node is found + } + + // Method to execute the current node's API request if it's an 'api' node + executeCurrentNode() { + console.log(this.currentNodeId) + if(!this.currentNodeId) { + console.log('No current node to execute.'); + return; + } + + const currentNode = this.graph[this.currentNodeId]; + if (currentNode && currentNode.class === 'api') { + // get API model with currentNode.id + //this.apiClient.sendAPIRequest(currentNode); + console.log(`Executing API request for node: ${currentNode.id} - ${currentNode.name}`); + } else { + console.log('Current node is not an API node or does not exist.'); + } + this.visitedNodes.add(this.currentNodeId); // Mark this node as visited + + } + + // Method to move to the next node + moveToNextNode() { + const currentNode = this.graph[this.currentNodeId]; + console.log(currentNode); + + if (currentNode && currentNode.connections.length > 0) { + // Find the next unvisited node + const nextNode = currentNode.connections.find(nodeId => !this.visitedNodes.has(nodeId)); + if (nextNode) { + this.currentNodeId = nextNode; + console.log(`Moved to node: ${this.currentNodeId}`); + } else { + console.log('No more unvisited connections to move to.'); + this.currentNodeId = null; // No more nodes to visit + } + } else { + console.log('Current node has no connections or does not exist.'); + this.currentNodeId = null; // No more nodes to visit + } + } + + // Method to execute the entire scenario from start to end + executeAll() { + while (this.currentNodeId) { + console.log(this.currentNodeId) + this.executeCurrentNode(); + this.moveToNextNode(); + } + console.log('Completed execution of all API nodes.'); + } + + static extractGraphFromStart(homeData) { + console.log(homeData) + let graph = {}; + + // Helper function to recursively build the graph + function buildGraph(nodeId) { + const node = homeData[nodeId]; + if (!node || graph[nodeId]) { + // If the node doesn't exist or has already been visited, stop the recursion + return; + } + + // Initialize the node in the graph + graph[nodeId] = { + id: node.id, + name: node.name, + class: node.class, + connections: [] + }; + + // If the node has outputs, recursively add connected nodes + if (node.outputs) { + Object.values(node.outputs).forEach(output => { + output.connections.forEach(connection => { + graph[nodeId].connections.push(connection.node); + buildGraph(connection.node); // Recurse + }); + }); + } + } + + // Find the start node + for (let nodeId in homeData) { + if (homeData[nodeId].class === 'start') { + buildGraph(nodeId); // Start building the graph from the 'start' node + break; // Assuming there's only one start node + } + } + + return graph; + } +} \ No newline at end of file diff --git a/src/main/resources/static/js/APITester.js b/src/main/resources/static/js/APITester.js index 6dc77b6..993d3df 100644 --- a/src/main/resources/static/js/APITester.js +++ b/src/main/resources/static/js/APITester.js @@ -3,7 +3,6 @@ require.config({paths: {'vs': '/plugins/vs'}}); class APITester { - constructor() { this.servers = []; this.apiTabTitleTarget = '#apiRequestTabTitle'; @@ -16,9 +15,9 @@ class APITester { this.responseEditors = []; //API response body editor this.preRequestEditors = []; this.postRequestEditors = []; - window.globals = {}; - this.globalVariables = window.globals; + this.variables = {}; + this.apiClient = new APIClient(); } renderServers(selectedServer) { @@ -304,7 +303,7 @@ class APITester { collectionTemplate(collection, index) { return ` -
  • +
  • @@ -339,7 +338,7 @@ class APITester { init(servers) { if (servers) { this.servers = servers; - if (this.servers.length === 0){ + if (this.servers.length === 0) { $('.toast-body').text('서버관리에서 서버를 등록해주세요.'); $('.toast').toast('show'); } @@ -357,7 +356,7 @@ class APITester { {selector: '.btn_add_variables', action: this.addVariable.bind(this)}, {selector: '.btn_remove_variable', action: this.removeVariable.bind(this)}, - {selector: '.send', action: this.sendApiRequest.bind(this)}, + {selector: '.send', action: this.handleSendAPIRequest.bind(this)}, {selector: '.save', action: this.saveAPIRequest.bind(this)}, {selector: '.save_collection', action: this.addCollection.bind(this)}, {selector: '#cancel-ajax', action: this.cancelAjaxRequest.bind(this)}, @@ -379,16 +378,57 @@ class APITester { $(document).on('click', event.selector, event.action); } - $(document).on('input', '.query_params input', this.handleUIUpdate.bind(this)); - $(document).on('input', '.query_params input', this.buildPath.bind(this)); + $(document).on('input', '.query_params input', this.handleUIUpdate.bind(this)); + $(document).on('input', '.query_params input', this.buildPath.bind(this)); $(document).on('change', '.query_params input', this.handleUIUpdate.bind(this)); $(document).on('change', '.query_params input', this.buildPath.bind(this)); - $(document).on('input', '.path', this.parseParam.bind(this)); + $(document).on('input', '.path', this.parseParam.bind(this)); $(document).on('change', '.request_headers input', this.handleUIUpdate.bind(this)); $(document).on('change', '.variables input', this.handleUIUpdate.bind(this)); $(document).on('change', '.api_request_info select, .api_request_info input', this.handleUIUpdate.bind(this)); $(document).on('change', '.api_request_info select', this.handleUpdateServer.bind(this)); + window.addEventListener('resize', this.resizeEditor.bind(this)); + + + } + + resizeEditor() { + //FIXME: 창 크기 변경시 자동으로 editor 크기가 조정되지 않아서, 0으로 강제 변경후 다시 layout() 호출 + + for (let i = 0; i < this.requestEditors.length; i++) { + this.requestEditors[i].layout({ + width: 0 + }); + } + for (let i = 0; i < this.responseEditors.length; i++) { + this.responseEditors[i].layout({ + width: 0 + }); + } + for (let i = 0; i < this.preRequestEditors.length; i++) { + this.preRequestEditors[i].layout({ + width: 0 + }); + } + for (let i = 0; i < this.postRequestEditors.length; i++) { + this.postRequestEditors[i].layout({ + width: 0 + }); + } + + for (let i = 0; i < this.requestEditors.length; i++) { + this.requestEditors[i].layout({}); + } + for (let i = 0; i < this.responseEditors.length; i++) { + this.responseEditors[i].layout({}); + } + for (let i = 0; i < this.preRequestEditors.length; i++) { + this.preRequestEditors[i].layout({}); + } + for (let i = 0; i < this.postRequestEditors.length; i++) { + this.postRequestEditors[i].layout({}); + } } @@ -547,7 +587,7 @@ class APITester { this.openTab(model.id); let target = $('#api_request_' + model.id); - require(['vs/editor/editor.main'], () => { + require(['vs/editor/editor.main'], () => { let requestBodyEditor = monaco.editor.create(target.find(".request_body")[0], { value: model.requestBody, language: 'json', @@ -555,15 +595,15 @@ class APITester { automaticLayout: true }); me.requestEditors.push(requestBodyEditor); - target.find(".request_body")[0].addEventListener('shown.bs.tab', () => { + target.find(".request_body")[0].addEventListener('shown.bs.tab', () => { me.requestEditors[index].layout(); }); - me.requestEditors[index].onDidChangeModelContent( (e) => { + me.requestEditors[index].onDidChangeModelContent((e) => { model.requestBody = requestBodyEditor.getValue(); }); - target.find('.request_body_type').on('change', () => { + target.find('.request_body_type').on('change', () => { let model = requestBodyEditor.getModel(); monaco.editor.setModelLanguage(model, $(this).val()); }); @@ -583,11 +623,11 @@ class APITester { automaticLayout: true }); me.preRequestEditors.push(preRequestEditor); - target.find(".pre-request")[0].addEventListener('shown.bs.tab', () => { + target.find(".pre-request")[0].addEventListener('shown.bs.tab', () => { me.preRequestEditors[index].layout(); }); - me.preRequestEditors[index].onDidChangeModelContent( (e) => { + me.preRequestEditors[index].onDidChangeModelContent((e) => { model.preRequestScript = preRequestEditor.getValue(); }); @@ -598,37 +638,32 @@ class APITester { automaticLayout: true }); me.postRequestEditors.push(postRequestEditor); - target.find(".post-request")[0].addEventListener('shown.bs.tab', () => { + target.find(".post-request")[0].addEventListener('shown.bs.tab', () => { me.postRequestEditors[index].layout(); }); - me.postRequestEditors[index].onDidChangeModelContent( (e) => { + me.postRequestEditors[index].onDidChangeModelContent((e) => { model.postRequestScript = postRequestEditor.getValue(); }); - - - }); } renderResponse(tabIndex) { - //console.log('renderResponse: ' + tabIndex); + console.log('renderResponse: ' + tabIndex); let model = this.apiRequests[tabIndex]; let target = $('#api_request_' + model.id); target.find('.response_headers').empty(); target.find(".response_status").empty(); - //console.log(model.responseModel); - try { const parsedJson = JSON.parse(model.responseModel.body); const formattedJson = JSON.stringify(parsedJson, null, 2); this.responseEditors[tabIndex].setValue(formattedJson); - } catch(e) { + } catch (e) { this.responseEditors[tabIndex].setValue(model.responseModel.body); } - if(model.responseModel && model.responseModel.headers) { + if (model.responseModel && model.responseModel.headers) { for (let i = 0; i < model.responseModel.headers.length; i++) { target.find('.response_headers').append(this.responseHeaderTemplate(model.responseModel.headers[i], i)); } @@ -640,6 +675,14 @@ class APITester { } + customHelper(event) { + // Create and return the custom helper element + let name = $(event.target).closest('.api_request_sortable').find('.open_api_request').text().trim(); + let apiId = $(event.target).closest('.api_request_sortable').data('id'); + return `
    +
    ${name}
    +
    `; + } renderCollections() { let select = $('#modal_collection'); @@ -654,6 +697,25 @@ class APITester { option.text(this.collections[i].name); select.append(option); } + + $("li .api_request_sortable").draggable({ + helper: this.customHelper, + start: function (event, ui) { + // You can add any additional data or styles you want when dragging starts + $(this).addClass('dragging'); + const apiDetails = { + name: 'API 이름', + method: 'POST', + url: 'http://localhost:8080/api/test' + }; + + }, + stop: function (event, ui) { + // Clean up, e.g., remove styles or data + $(this).removeClass('dragging'); + } + }); + } renderCollection(collection, index) { @@ -661,7 +723,6 @@ class APITester { } openTab(id) { - //console.log('openTab: ' + id); try { $(`#api_request_tab_${id}`).tab('show'); // API request 탭 활성화 } catch (e) { @@ -763,6 +824,7 @@ class APITester { target.find('.variables').empty(); target.find('.variables').append(this.renderVariables(model.variables)); } + parseParam(event) { const tabIndex = $('#apiRequestTabContent').children().index($(event.currentTarget).closest('.api_request')); let model = this.apiRequests[tabIndex]; @@ -785,6 +847,7 @@ class APITester { this.renderQueryParamsView(tabIndex); } } + buildPath(event) { const tabIndex = $('#apiRequestTabContent').children().index($(event.currentTarget).closest('.api_request')); let model = this.apiRequests[tabIndex]; @@ -813,14 +876,13 @@ class APITester { $("#loading-overlay").hide(); } - sendApiRequest(event) { + handleSendAPIRequest(event) { const tabIndex = $('#apiRequestTabContent').children().index($(event.currentTarget).closest('.api_request')); console.log(tabIndex); - const me = this; let model = this.apiRequests[tabIndex]; - if (!model.server){ + if (!model.server) { $('.toast-body').text('서버를 등록해주세요.'); $('.toast').toast('show'); return; @@ -829,53 +891,42 @@ class APITester { let target = $('#api_request_' + model.id); target.find('.response_headers').empty(); this.responseEditors[tabIndex].setValue(''); - let startTime = new Date().getTime(); - - this.showLoadingOverlay(); model.responseModel = {}; + this.showLoadingOverlay(); - let processedRequest = this.executePreRequestScript(model, tabIndex,() => { - processedRequest = this.replacePlaceholdersWithVariables(processedRequest, tabIndex); - this.currentAjaxRequest = $.ajax({ - url: '/mgmt/api/test.do', - type: 'POST', - contentType: 'application/json', - data: JSON.stringify(processedRequest), - success: (data) => { - model.responseModel.status = data.status; - model.responseModel.body = data.body; - model.responseModel.headers = data.headers; - model.responseModel.size = data.size; + let startTime = new Date().getTime(); + this.currentAjaxRequest = this.apiClient.sendAPIRequest(model) + .then(response => { + if (response) { + model.responseModel = response; + let endTime = new Date().getTime(); + model.responseModel.time = endTime - startTime; + } else { + model.responseModel = { + status: 0, + time: 0, + size: 0, + headers: [], + body: '' + }; + } - let response = {}; - response.body = data.body; - response.status = data.status; - response.headers = {}; - response.size = data.size; - _.forEach(data.headers, (header) => { - response.headers[header.key] = header.value; - }); - - - this.executePostRequestScript(model.postRequestScript, tabIndex, response, ()=> { - let endTime = new Date().getTime(); - model.responseModel.time = endTime - startTime; - me.renderResponse(tabIndex); - me.hideLoadingOverlay(); - }); - }, - error: (response, textStatus, errorThrown) => { - me.hideLoadingOverlay(); - $('.toast-body').text(response.responseJSON.error); + this.renderResponse(tabIndex); + this.hideLoadingOverlay(); + }) + .catch(error => { + console.log(error.name) + if (error.name === 'AbortError') { + console.log('Fetch aborted'); + } else { + console.log('error3') + $('.toast-body').text(error); $('.toast').toast('show'); } + this.hideLoadingOverlay(); }); - }); - - } - loadCollections() { const me = this; this.currentAjaxRequest = $.ajax({ @@ -911,9 +962,6 @@ class APITester { type: 'POST', contentType: 'application/json', data: JSON.stringify({name: name}), - success: function (data) { - - }, error: function (response, textStatus, errorThrown) { me.hideLoadingOverlay(); $('.toast-body').text(response.responseJSON.error); @@ -1046,8 +1094,8 @@ class APITester { queryParams: [], variables: [], requestBody: '', - preRequestScript :'', - postRequestScript :'', + preRequestScript: '', + postRequestScript: '', collectionId: collectionId, responseModel: { status: 0, @@ -1088,9 +1136,14 @@ class APITester { cancelAjaxRequest() { if (this.currentAjaxRequest) { - this.currentAjaxRequest.abort(); - this.hideLoadingOverlay(); + try { + + this.currentAjaxRequest.abort(); + } catch (e) { + this.apiClient.abort(); + } } + this.hideLoadingOverlay(); } openApiRequest(event) { @@ -1147,7 +1200,7 @@ class APITester { return api.id === apiId; }); console.log(apiIndex); - if(apiIndex >= 0){ + if (apiIndex >= 0) { this.closeTabWithApiIndex(apiIndex); } const me = this; @@ -1172,7 +1225,7 @@ class APITester { closeTabWithApiIndex(index) { console.log(index); - if (index !== undefined){ + if (index !== undefined) { //console.log('closeTabWithApiIndex: ' + index); const model = this.apiRequests[index]; console.log(model); @@ -1186,103 +1239,11 @@ class APITester { $(`#apiRequestTabTitle li:eq(0) button`).tab('show'); } } + closeTab(event) { const index = $('#apiRequestTabTitle').children().index($(event.currentTarget).closest('.nav-item')); this.closeTabWithApiIndex(index); } - replacePlaceholdersWithVariables(original, index) { - let request = JSON.parse(JSON.stringify(original)); - let mergedVariables = {}; - _.forEach(this.globalVariables, (value, key) => { - mergedVariables[key] = value; - }); - - if (this.variables[index]) { - _.forEach(this.variables[index], (value, key) => { - mergedVariables[key] = value; - }); - } - - _.forEach(mergedVariables, (value, key) => { - const placeholder = `{{${key}}}`; - // Replace in path - request.path = request.path.replace(new RegExp(placeholder, 'g'), value); - - // Replace in requestBody - if (request.requestBody) { - request.requestBody = request.requestBody.replace(new RegExp(placeholder, 'g'), value); - } - - // Replace in headers - if (request.headers) { - request.headers = request.headers.map(header => { - return { - ...header, - key: header.key.replace(new RegExp(placeholder, 'g'), value), - value: header.value.replace(new RegExp(placeholder, 'g'), value) - }; - }); - } - - // Replace in queryParams - if (request.queryParams) { - request.queryParams = request.queryParams.map(queryParam => { - return { - ...queryParam, - key: queryParam.key.replace(new RegExp(placeholder, 'g'), value), - value: queryParam.value.replace(new RegExp(placeholder, 'g'), value) - }; - }); - } - }); - - return request; - } - - executePreRequestScript(model, index, callback) { - let script = model.preRequestScript; - let resultFrame = document.getElementById('preRequest'); - let {headers, method, path, queryParams, requestBody} = model; - window.request = {headers, method, path, queryParams, requestBody}; - this.variables[index] = {}; - model.variables.forEach((item) =>{ - if (item.enabled) { - this.variables[index][item.key] = item.value; - } - }); - - window.preRequestComplete = function(updatedModel) { - callback(updatedModel); - }; - window.temp_variable = this.variables[index]; - - resultFrame.srcdoc = ``; - - return model; - } - - executePostRequestScript(script, index, response, callback) { - let resultFrame = document.getElementById('postRequest'); - window.response = response; - window.parent.temp_variable = this.variables[index]; - window.postRequestComplete = function(updatedModel) { - callback(updatedModel); - }; - window.temp_variable = this.variables[index]; - resultFrame.srcdoc = ``; - } } \ No newline at end of file diff --git a/src/main/resources/static/plugins/drawflow/drawflow.js b/src/main/resources/static/plugins/drawflow/drawflow.js new file mode 100644 index 0000000..9442379 --- /dev/null +++ b/src/main/resources/static/plugins/drawflow/drawflow.js @@ -0,0 +1,1953 @@ +export default class Drawflow { + constructor(container, render = null, parent = null) { + this.events = {}; + this.container = container; + this.precanvas = null; + this.nodeId = 1; + this.ele_selected = null; + this.node_selected = null; + this.drag = false; + this.reroute = false; + this.reroute_fix_curvature = false; + this.curvature = 0.5; + this.reroute_curvature_start_end = 0.5; + this.reroute_curvature = 0.5; + this.reroute_width = 6; + this.drag_point = false; + this.editor_selected = false; + this.connection = false; + this.connection_ele = null; + this.connection_selected = null; + this.canvas_x = 0; + this.canvas_y = 0; + this.pos_x = 0; + this.pos_x_start = 0; + this.pos_y = 0; + this.pos_y_start = 0; + this.mouse_x = 0; + this.mouse_y = 0; + this.line_path = 5; + this.first_click = null; + this.force_first_input = false; + this.draggable_inputs = true; + this.useuuid = false; + this.parent = parent; + + this.noderegister = {}; + this.render = render; + this.drawflow = { "drawflow": { "Home": { "data": {} }}}; + // Configurable options + this.module = 'Home'; + this.editor_mode = 'edit'; + this.zoom = 1; + this.zoom_max = 1.6; + this.zoom_min = 0.5; + this.zoom_value = 0.1; + this.zoom_last_value = 1; + + // Mobile + this.evCache = new Array(); + this.prevDiff = -1; + } + + start () { + // console.info("Start Drawflow!!"); + this.container.classList.add("parent-drawflow"); + this.container.tabIndex = 0; + this.precanvas = document.createElement('div'); + this.precanvas.classList.add("drawflow"); + this.container.appendChild(this.precanvas); + + /* Mouse and Touch Actions */ + this.container.addEventListener('mouseup', this.dragEnd.bind(this)); + this.container.addEventListener('mousemove', this.position.bind(this)); + this.container.addEventListener('mousedown', this.click.bind(this) ); + + this.container.addEventListener('touchend', this.dragEnd.bind(this)); + this.container.addEventListener('touchmove', this.position.bind(this)); + this.container.addEventListener('touchstart', this.click.bind(this)); + + /* Context Menu */ + this.container.addEventListener('contextmenu', this.contextmenu.bind(this)); + /* Delete */ + this.container.addEventListener('keydown', this.key.bind(this)); + + /* Zoom Mouse */ + this.container.addEventListener('wheel', this.zoom_enter.bind(this)); + /* Update data Nodes */ + this.container.addEventListener('input', this.updateNodeValue.bind(this)); + + this.container.addEventListener('dblclick', this.dblclick.bind(this)); + /* Mobile zoom */ + this.container.onpointerdown = this.pointerdown_handler.bind(this); + this.container.onpointermove = this.pointermove_handler.bind(this); + this.container.onpointerup = this.pointerup_handler.bind(this); + this.container.onpointercancel = this.pointerup_handler.bind(this); + this.container.onpointerout = this.pointerup_handler.bind(this); + this.container.onpointerleave = this.pointerup_handler.bind(this); + + this.load(); + } + + /* Mobile zoom */ + pointerdown_handler(ev) { + this.evCache.push(ev); + } + + pointermove_handler(ev) { + for (var i = 0; i < this.evCache.length; i++) { + if (ev.pointerId == this.evCache[i].pointerId) { + this.evCache[i] = ev; + break; + } + } + + if (this.evCache.length == 2) { + // Calculate the distance between the two pointers + var curDiff = Math.abs(this.evCache[0].clientX - this.evCache[1].clientX); + + if (this.prevDiff > 100) { + if (curDiff > this.prevDiff) { + // The distance between the two pointers has increased + + this.zoom_in(); + } + if (curDiff < this.prevDiff) { + // The distance between the two pointers has decreased + this.zoom_out(); + } + } + this.prevDiff = curDiff; + } + } + + pointerup_handler(ev) { + this.remove_event(ev); + if (this.evCache.length < 2) { + this.prevDiff = -1; + } + } + remove_event(ev) { + // Remove this event from the target's cache + for (var i = 0; i < this.evCache.length; i++) { + if (this.evCache[i].pointerId == ev.pointerId) { + this.evCache.splice(i, 1); + break; + } + } + } + /* End Mobile Zoom */ + load() { + for (var key in this.drawflow.drawflow[this.module].data) { + this.addNodeImport(this.drawflow.drawflow[this.module].data[key], this.precanvas); + } + + if(this.reroute) { + for (var key in this.drawflow.drawflow[this.module].data) { + this.addRerouteImport(this.drawflow.drawflow[this.module].data[key]); + } + } + + for (var key in this.drawflow.drawflow[this.module].data) { + this.updateConnectionNodes('node-'+key); + } + + const editor = this.drawflow.drawflow; + let number = 1; + Object.keys(editor).map(function(moduleName, index) { + Object.keys(editor[moduleName].data).map(function(id, index2) { + if(parseInt(id) >= number) { + number = parseInt(id)+1; + } + }); + }); + this.nodeId = number; + } + + removeReouteConnectionSelected(){ + this.dispatch('connectionUnselected', true); + if(this.reroute_fix_curvature) { + this.connection_selected.parentElement.querySelectorAll(".main-path").forEach((item, i) => { + item.classList.remove("selected"); + }); + } + } + + click(e) { + this.dispatch('click', e); + if(this.editor_mode === 'fixed') { + //return false; + e.preventDefault(); + if(e.target.classList[0] === 'parent-drawflow' || e.target.classList[0] === 'drawflow') { + this.ele_selected = e.target.closest(".parent-drawflow"); + } else { + return false; + } + } else if(this.editor_mode === 'view') { + if(e.target.closest(".drawflow") != null || e.target.matches('.parent-drawflow')) { + this.ele_selected = e.target.closest(".parent-drawflow"); + e.preventDefault(); + } + } else { + this.first_click = e.target; + this.ele_selected = e.target; + if(e.button === 0) { + this.contextmenuDel(); + } + + if(e.target.closest(".drawflow_content_node") != null) { + this.ele_selected = e.target.closest(".drawflow_content_node").parentElement; + } + } + switch (this.ele_selected.classList[0]) { + case 'drawflow-node': + if(this.node_selected != null) { + this.node_selected.classList.remove("selected"); + if(this.node_selected != this.ele_selected) { + this.dispatch('nodeUnselected', true); + } + } + if(this.connection_selected != null) { + this.connection_selected.classList.remove("selected"); + this.removeReouteConnectionSelected(); + this.connection_selected = null; + } + if(this.node_selected != this.ele_selected) { + this.dispatch('nodeSelected', this.ele_selected.id.slice(5)); + } + this.node_selected = this.ele_selected; + this.node_selected.classList.add("selected"); + if(!this.draggable_inputs) { + if(e.target.tagName !== 'INPUT' && e.target.tagName !== 'TEXTAREA' && e.target.tagName !== 'SELECT' && e.target.hasAttribute('contenteditable') !== true) { + this.drag = true; + } + } else { + if(e.target.tagName !== 'SELECT') { + this.drag = true; + } + } + break; + case 'output': + this.connection = true; + if(this.node_selected != null) { + this.node_selected.classList.remove("selected"); + this.node_selected = null; + this.dispatch('nodeUnselected', true); + } + if(this.connection_selected != null) { + this.connection_selected.classList.remove("selected"); + this.removeReouteConnectionSelected(); + this.connection_selected = null; + } + this.drawConnection(e.target); + break; + case 'parent-drawflow': + if(this.node_selected != null) { + this.node_selected.classList.remove("selected"); + this.node_selected = null; + this.dispatch('nodeUnselected', true); + } + if(this.connection_selected != null) { + this.connection_selected.classList.remove("selected"); + this.removeReouteConnectionSelected(); + this.connection_selected = null; + } + this.editor_selected = true; + break; + case 'drawflow': + if(this.node_selected != null) { + this.node_selected.classList.remove("selected"); + this.node_selected = null; + this.dispatch('nodeUnselected', true); + } + if(this.connection_selected != null) { + this.connection_selected.classList.remove("selected"); + this.removeReouteConnectionSelected(); + this.connection_selected = null; + } + this.editor_selected = true; + break; + case 'main-path': + if(this.node_selected != null) { + this.node_selected.classList.remove("selected"); + this.node_selected = null; + this.dispatch('nodeUnselected', true); + } + if(this.connection_selected != null) { + this.connection_selected.classList.remove("selected"); + this.removeReouteConnectionSelected(); + this.connection_selected = null; + } + this.connection_selected = this.ele_selected; + this.connection_selected.classList.add("selected"); + const listclassConnection = this.connection_selected.parentElement.classList; + if(listclassConnection.length > 1){ + this.dispatch('connectionSelected', { output_id: listclassConnection[2].slice(14), input_id: listclassConnection[1].slice(13), output_class: listclassConnection[3], input_class: listclassConnection[4] }); + if(this.reroute_fix_curvature) { + this.connection_selected.parentElement.querySelectorAll(".main-path").forEach((item, i) => { + item.classList.add("selected"); + }); + } + } + break; + case 'point': + this.drag_point = true; + this.ele_selected.classList.add("selected"); + break; + case 'drawflow-delete': + if(this.node_selected ) { + this.removeNodeId(this.node_selected.id); + } + + if(this.connection_selected) { + this.removeConnection(); + } + + if(this.node_selected != null) { + this.node_selected.classList.remove("selected"); + this.node_selected = null; + this.dispatch('nodeUnselected', true); + } + if(this.connection_selected != null) { + this.connection_selected.classList.remove("selected"); + this.removeReouteConnectionSelected(); + this.connection_selected = null; + } + + break; + default: + } + if (e.type === "touchstart") { + this.pos_x = e.touches[0].clientX; + this.pos_x_start = e.touches[0].clientX; + this.pos_y = e.touches[0].clientY; + this.pos_y_start = e.touches[0].clientY; + this.mouse_x = e.touches[0].clientX; + this.mouse_y = e.touches[0].clientY; + } else { + this.pos_x = e.clientX; + this.pos_x_start = e.clientX; + this.pos_y = e.clientY; + this.pos_y_start = e.clientY; + } + if (['input','output','main-path'].includes(this.ele_selected.classList[0])) { + e.preventDefault(); + } + this.dispatch('clickEnd', e); + } + + position(e) { + if (e.type === "touchmove") { + var e_pos_x = e.touches[0].clientX; + var e_pos_y = e.touches[0].clientY; + } else { + var e_pos_x = e.clientX; + var e_pos_y = e.clientY; + } + + + if(this.connection) { + this.updateConnection(e_pos_x, e_pos_y); + } + if(this.editor_selected) { + x = this.canvas_x + (-(this.pos_x - e_pos_x)) + y = this.canvas_y + (-(this.pos_y - e_pos_y)) + this.dispatch('translate', { x: x, y: y}); + this.precanvas.style.transform = "translate("+x+"px, "+y+"px) scale("+this.zoom+")"; + } + if(this.drag) { + e.preventDefault(); + var x = (this.pos_x - e_pos_x) * this.precanvas.clientWidth / (this.precanvas.clientWidth * this.zoom); + var y = (this.pos_y - e_pos_y) * this.precanvas.clientHeight / (this.precanvas.clientHeight * this.zoom); + this.pos_x = e_pos_x; + this.pos_y = e_pos_y; + + this.ele_selected.style.top = (this.ele_selected.offsetTop - y) + "px"; + this.ele_selected.style.left = (this.ele_selected.offsetLeft - x) + "px"; + + this.drawflow.drawflow[this.module].data[this.ele_selected.id.slice(5)].pos_x = (this.ele_selected.offsetLeft - x); + this.drawflow.drawflow[this.module].data[this.ele_selected.id.slice(5)].pos_y = (this.ele_selected.offsetTop - y); + + this.updateConnectionNodes(this.ele_selected.id) + } + + if(this.drag_point) { + + var x = (this.pos_x - e_pos_x) * this.precanvas.clientWidth / (this.precanvas.clientWidth * this.zoom); + var y = (this.pos_y - e_pos_y) * this.precanvas.clientHeight / (this.precanvas.clientHeight * this.zoom); + this.pos_x = e_pos_x; + this.pos_y = e_pos_y; + + var pos_x = this.pos_x * ( this.precanvas.clientWidth / (this.precanvas.clientWidth * this.zoom)) - (this.precanvas.getBoundingClientRect().x * ( this.precanvas.clientWidth / (this.precanvas.clientWidth * this.zoom))); + var pos_y = this.pos_y * ( this.precanvas.clientHeight / (this.precanvas.clientHeight * this.zoom)) - (this.precanvas.getBoundingClientRect().y * ( this.precanvas.clientHeight / (this.precanvas.clientHeight * this.zoom))); + + this.ele_selected.setAttributeNS(null, 'cx', pos_x); + this.ele_selected.setAttributeNS(null, 'cy', pos_y); + + const nodeUpdate = this.ele_selected.parentElement.classList[2].slice(9); + const nodeUpdateIn = this.ele_selected.parentElement.classList[1].slice(13); + const output_class = this.ele_selected.parentElement.classList[3]; + const input_class = this.ele_selected.parentElement.classList[4]; + + let numberPointPosition = Array.from(this.ele_selected.parentElement.children).indexOf(this.ele_selected)-1; + + if(this.reroute_fix_curvature) { + const numberMainPath = this.ele_selected.parentElement.querySelectorAll(".main-path").length-1; + numberPointPosition -= numberMainPath; + if(numberPointPosition < 0) { + numberPointPosition = 0; + } + } + + const nodeId = nodeUpdate.slice(5); + const searchConnection = this.drawflow.drawflow[this.module].data[nodeId].outputs[output_class].connections.findIndex(function(item,i) { + return item.node === nodeUpdateIn && item.output === input_class; + }); + + this.drawflow.drawflow[this.module].data[nodeId].outputs[output_class].connections[searchConnection].points[numberPointPosition] = { pos_x: pos_x, pos_y: pos_y }; + + const parentSelected = this.ele_selected.parentElement.classList[2].slice(9); + + this.updateConnectionNodes(parentSelected); + } + + if (e.type === "touchmove") { + this.mouse_x = e_pos_x; + this.mouse_y = e_pos_y; + } + this.dispatch('mouseMove', {x: e_pos_x,y: e_pos_y }); + } + + dragEnd(e) { + if (e.type === "touchend") { + var e_pos_x = this.mouse_x; + var e_pos_y = this.mouse_y; + var ele_last = document.elementFromPoint(e_pos_x, e_pos_y); + } else { + var e_pos_x = e.clientX; + var e_pos_y = e.clientY; + var ele_last = e.target; + } + + if(this.drag) { + if(this.pos_x_start != e_pos_x || this.pos_y_start != e_pos_y) { + this.dispatch('nodeMoved', this.ele_selected.id.slice(5)); + } + } + + if(this.drag_point) { + this.ele_selected.classList.remove("selected"); + if(this.pos_x_start != e_pos_x || this.pos_y_start != e_pos_y) { + this.dispatch('rerouteMoved', this.ele_selected.parentElement.classList[2].slice(14)); + } + } + + if(this.editor_selected) { + this.canvas_x = this.canvas_x + (-(this.pos_x - e_pos_x)); + this.canvas_y = this.canvas_y + (-(this.pos_y - e_pos_y)); + this.editor_selected = false; + } + if(this.connection === true) { + if(ele_last.classList[0] === 'input' || (this.force_first_input && (ele_last.closest(".drawflow_content_node") != null || ele_last.classList[0] === 'drawflow-node'))) { + + if(this.force_first_input && (ele_last.closest(".drawflow_content_node") != null || ele_last.classList[0] === 'drawflow-node')) { + if(ele_last.closest(".drawflow_content_node") != null) { + var input_id = ele_last.closest(".drawflow_content_node").parentElement.id; + } else { + var input_id = ele_last.id; + } + if(Object.keys(this.getNodeFromId(input_id.slice(5)).inputs).length === 0) { + var input_class = false; + } else { + var input_class = "input_1"; + } + + + } else { + // Fix connection; + var input_id = ele_last.parentElement.parentElement.id; + var input_class = ele_last.classList[1]; + } + var output_id = this.ele_selected.parentElement.parentElement.id; + var output_class = this.ele_selected.classList[1]; + + if(output_id !== input_id && input_class !== false) { + + if(this.container.querySelectorAll('.connection.node_in_'+input_id+'.node_out_'+output_id+'.'+output_class+'.'+input_class).length === 0) { + // Conection no exist save connection + + this.connection_ele.classList.add("node_in_"+input_id); + this.connection_ele.classList.add("node_out_"+output_id); + this.connection_ele.classList.add(output_class); + this.connection_ele.classList.add(input_class); + var id_input = input_id.slice(5); + var id_output = output_id.slice(5); + + this.drawflow.drawflow[this.module].data[id_output].outputs[output_class].connections.push( {"node": id_input, "output": input_class}); + this.drawflow.drawflow[this.module].data[id_input].inputs[input_class].connections.push( {"node": id_output, "input": output_class}); + this.updateConnectionNodes('node-'+id_output); + this.updateConnectionNodes('node-'+id_input); + this.dispatch('connectionCreated', { output_id: id_output, input_id: id_input, output_class: output_class, input_class: input_class}); + + } else { + this.dispatch('connectionCancel', true); + this.connection_ele.remove(); + } + + this.connection_ele = null; + } else { + // Connection exists Remove Connection; + this.dispatch('connectionCancel', true); + this.connection_ele.remove(); + this.connection_ele = null; + } + + } else { + // Remove Connection; + this.dispatch('connectionCancel', true); + this.connection_ele.remove(); + this.connection_ele = null; + } + } + + this.drag = false; + this.drag_point = false; + this.connection = false; + this.ele_selected = null; + this.editor_selected = false; + + this.dispatch('mouseUp', e); + } + contextmenu(e) { + this.dispatch('contextmenu', e); + e.preventDefault(); + if(this.editor_mode === 'fixed' || this.editor_mode === 'view') { + return false; + } + if(this.precanvas.getElementsByClassName("drawflow-delete").length) { + this.precanvas.getElementsByClassName("drawflow-delete")[0].remove() + }; + if(this.node_selected || this.connection_selected) { + var deletebox = document.createElement('div'); + deletebox.classList.add("drawflow-delete"); + deletebox.innerHTML = "x"; + if(this.node_selected) { + this.node_selected.appendChild(deletebox); + + } + if(this.connection_selected && (this.connection_selected.parentElement.classList.length > 1)) { + deletebox.style.top = e.clientY * ( this.precanvas.clientHeight / (this.precanvas.clientHeight * this.zoom)) - (this.precanvas.getBoundingClientRect().y * ( this.precanvas.clientHeight / (this.precanvas.clientHeight * this.zoom)) ) + "px"; + deletebox.style.left = e.clientX * ( this.precanvas.clientWidth / (this.precanvas.clientWidth * this.zoom)) - (this.precanvas.getBoundingClientRect().x * ( this.precanvas.clientWidth / (this.precanvas.clientWidth * this.zoom)) ) + "px"; + + this.precanvas.appendChild(deletebox); + + } + + } + + } + contextmenuDel() { + if(this.precanvas.getElementsByClassName("drawflow-delete").length) { + this.precanvas.getElementsByClassName("drawflow-delete")[0].remove() + }; + } + + key(e) { + this.dispatch('keydown', e); + if(this.editor_mode === 'fixed' || this.editor_mode === 'view') { + return false; + } + if (e.key === 'Delete' || (e.key === 'Backspace' && e.metaKey)) { + if(this.node_selected != null) { + if(this.first_click.tagName !== 'INPUT' && this.first_click.tagName !== 'TEXTAREA' && this.first_click.hasAttribute('contenteditable') !== true) { + this.removeNodeId(this.node_selected.id); + } + } + if(this.connection_selected != null) { + this.removeConnection(); + } + } + } + + zoom_enter(event, delta) { + if (event.ctrlKey) { + event.preventDefault() + if(event.deltaY > 0) { + // Zoom Out + this.zoom_out(); + } else { + // Zoom In + this.zoom_in(); + } + } + } + zoom_refresh(){ + this.dispatch('zoom', this.zoom); + this.canvas_x = (this.canvas_x / this.zoom_last_value) * this.zoom; + this.canvas_y = (this.canvas_y / this.zoom_last_value) * this.zoom; + this.zoom_last_value = this.zoom; + this.precanvas.style.transform = "translate("+this.canvas_x+"px, "+this.canvas_y+"px) scale("+this.zoom+")"; + } + zoom_in() { + if(this.zoom < this.zoom_max) { + this.zoom+=this.zoom_value; + this.zoom_refresh(); + } + } + zoom_out() { + if(this.zoom > this.zoom_min) { + this.zoom-=this.zoom_value; + this.zoom_refresh(); + } + } + zoom_reset(){ + if(this.zoom != 1) { + this.zoom = 1; + this.zoom_refresh(); + } + } + + createCurvature(start_pos_x, start_pos_y, end_pos_x, end_pos_y, curvature_value, type) { + var line_x = start_pos_x; + var line_y = start_pos_y; + var x = end_pos_x; + var y = end_pos_y; + var curvature = curvature_value; + //type openclose open close other + switch (type) { + case 'open': + if(start_pos_x >= end_pos_x) { + var hx1 = line_x + Math.abs(x - line_x) * curvature; + var hx2 = x - Math.abs(x - line_x) * (curvature*-1); + } else { + var hx1 = line_x + Math.abs(x - line_x) * curvature; + var hx2 = x - Math.abs(x - line_x) * curvature; + } + return ' M '+ line_x +' '+ line_y +' C '+ hx1 +' '+ line_y +' '+ hx2 +' ' + y +' ' + x +' ' + y; + + break + case 'close': + if(start_pos_x >= end_pos_x) { + var hx1 = line_x + Math.abs(x - line_x) * (curvature*-1); + var hx2 = x - Math.abs(x - line_x) * curvature; + } else { + var hx1 = line_x + Math.abs(x - line_x) * curvature; + var hx2 = x - Math.abs(x - line_x) * curvature; + } + return ' M '+ line_x +' '+ line_y +' C '+ hx1 +' '+ line_y +' '+ hx2 +' ' + y +' ' + x +' ' + y; + break; + case 'other': + if(start_pos_x >= end_pos_x) { + var hx1 = line_x + Math.abs(x - line_x) * (curvature*-1); + var hx2 = x - Math.abs(x - line_x) * (curvature*-1); + } else { + var hx1 = line_x + Math.abs(x - line_x) * curvature; + var hx2 = x - Math.abs(x - line_x) * curvature; + } + return ' M '+ line_x +' '+ line_y +' C '+ hx1 +' '+ line_y +' '+ hx2 +' ' + y +' ' + x +' ' + y; + break; + default: + + var hx1 = line_x + Math.abs(x - line_x) * curvature; + var hx2 = x - Math.abs(x - line_x) * curvature; + + return ' M '+ line_x +' '+ line_y +' C '+ hx1 +' '+ line_y +' '+ hx2 +' ' + y +' ' + x +' ' + y; + } + + } + + drawConnection(ele) { + var connection = document.createElementNS('http://www.w3.org/2000/svg',"svg"); + this.connection_ele = connection; + var path = document.createElementNS('http://www.w3.org/2000/svg',"path"); + path.classList.add("main-path"); + path.setAttributeNS(null, 'd', ''); + // path.innerHTML = 'a'; + connection.classList.add("connection"); + connection.appendChild(path); + this.precanvas.appendChild(connection); + var id_output = ele.parentElement.parentElement.id.slice(5); + var output_class = ele.classList[1]; + this.dispatch('connectionStart', { output_id: id_output, output_class: output_class }); + + } + + updateConnection(eX, eY) { + const precanvas = this.precanvas; + const zoom = this.zoom; + let precanvasWitdhZoom = precanvas.clientWidth / (precanvas.clientWidth * zoom); + precanvasWitdhZoom = precanvasWitdhZoom || 0; + let precanvasHeightZoom = precanvas.clientHeight / (precanvas.clientHeight * zoom); + precanvasHeightZoom = precanvasHeightZoom || 0; + var path = this.connection_ele.children[0]; + + var line_x = this.ele_selected.offsetWidth/2 + (this.ele_selected.getBoundingClientRect().x - precanvas.getBoundingClientRect().x ) * precanvasWitdhZoom; + var line_y = this.ele_selected.offsetHeight/2 + (this.ele_selected.getBoundingClientRect().y - precanvas.getBoundingClientRect().y ) * precanvasHeightZoom; + + var x = eX * ( this.precanvas.clientWidth / (this.precanvas.clientWidth * this.zoom)) - (this.precanvas.getBoundingClientRect().x * ( this.precanvas.clientWidth / (this.precanvas.clientWidth * this.zoom)) ); + var y = eY * ( this.precanvas.clientHeight / (this.precanvas.clientHeight * this.zoom)) - (this.precanvas.getBoundingClientRect().y * ( this.precanvas.clientHeight / (this.precanvas.clientHeight * this.zoom)) ); + + var curvature = this.curvature; + var lineCurve = this.createCurvature(line_x, line_y, x, y, curvature, 'openclose'); + path.setAttributeNS(null, 'd', lineCurve); + + } + + addConnection(id_output, id_input, output_class, input_class) { + var nodeOneModule = this.getModuleFromNodeId(id_output); + var nodeTwoModule = this.getModuleFromNodeId(id_input); + if(nodeOneModule === nodeTwoModule) { + + var dataNode = this.getNodeFromId(id_output); + var exist = false; + for(var checkOutput in dataNode.outputs[output_class].connections){ + var connectionSearch = dataNode.outputs[output_class].connections[checkOutput] + if(connectionSearch.node == id_input && connectionSearch.output == input_class) { + exist = true; + } + } + // Check connection exist + if(exist === false) { + //Create Connection + this.drawflow.drawflow[nodeOneModule].data[id_output].outputs[output_class].connections.push( {"node": id_input.toString(), "output": input_class}); + this.drawflow.drawflow[nodeOneModule].data[id_input].inputs[input_class].connections.push( {"node": id_output.toString(), "input": output_class}); + + if(this.module === nodeOneModule) { + //Draw connection + var connection = document.createElementNS('http://www.w3.org/2000/svg',"svg"); + var path = document.createElementNS('http://www.w3.org/2000/svg',"path"); + path.classList.add("main-path"); + path.setAttributeNS(null, 'd', ''); + // path.innerHTML = 'a'; + connection.classList.add("connection"); + connection.classList.add("node_in_node-"+id_input); + connection.classList.add("node_out_node-"+id_output); + connection.classList.add(output_class); + connection.classList.add(input_class); + connection.appendChild(path); + this.precanvas.appendChild(connection); + this.updateConnectionNodes('node-'+id_output); + this.updateConnectionNodes('node-'+id_input); + } + + this.dispatch('connectionCreated', { output_id: id_output, input_id: id_input, output_class: output_class, input_class: input_class}); + } + } + } + + updateConnectionNodes(id) { + + // Aquí nos quedamos; + const idSearch = 'node_in_'+id; + const idSearchOut = 'node_out_'+id; + var line_path = this.line_path/2; + const container = this.container; + const precanvas = this.precanvas; + const curvature = this.curvature; + const createCurvature = this.createCurvature; + const reroute_curvature = this.reroute_curvature; + const reroute_curvature_start_end = this.reroute_curvature_start_end; + const reroute_fix_curvature = this.reroute_fix_curvature; + const rerouteWidth = this.reroute_width; + const zoom = this.zoom; + let precanvasWitdhZoom = precanvas.clientWidth / (precanvas.clientWidth * zoom); + precanvasWitdhZoom = precanvasWitdhZoom || 0; + let precanvasHeightZoom = precanvas.clientHeight / (precanvas.clientHeight * zoom); + precanvasHeightZoom = precanvasHeightZoom || 0; + + const elemsOut = container.querySelectorAll(`.${idSearchOut}`); + + Object.keys(elemsOut).map(function(item, index) { + if(elemsOut[item].querySelector('.point') === null) { + + var elemtsearchId_out = container.querySelector(`#${id}`); + + var id_search = elemsOut[item].classList[1].replace('node_in_', ''); + var elemtsearchId = container.querySelector(`#${id_search}`); + + var elemtsearch = elemtsearchId.querySelectorAll('.'+elemsOut[item].classList[4])[0] + + var eX = elemtsearch.offsetWidth/2 + (elemtsearch.getBoundingClientRect().x - precanvas.getBoundingClientRect().x ) * precanvasWitdhZoom; + var eY = elemtsearch.offsetHeight/2 + (elemtsearch.getBoundingClientRect().y - precanvas.getBoundingClientRect().y ) * precanvasHeightZoom; + + var elemtsearchOut = elemtsearchId_out.querySelectorAll('.'+elemsOut[item].classList[3])[0] + + var line_x = elemtsearchOut.offsetWidth/2 + (elemtsearchOut.getBoundingClientRect().x - precanvas.getBoundingClientRect().x ) * precanvasWitdhZoom; + var line_y = elemtsearchOut.offsetHeight/2 + (elemtsearchOut.getBoundingClientRect().y - precanvas.getBoundingClientRect().y ) * precanvasHeightZoom; + + var x = eX; + var y = eY; + + const lineCurve = createCurvature(line_x, line_y, x, y, curvature, 'openclose'); + elemsOut[item].children[0].setAttributeNS(null, 'd', lineCurve ); + } else { + const points = elemsOut[item].querySelectorAll('.point'); + let linecurve = ''; + const reoute_fix = []; + points.forEach((item, i) => { + if(i === 0 && ((points.length -1) === 0)) { + + var elemtsearchId_out = container.querySelector(`#${id}`); + var elemtsearch = item; + + var eX = (elemtsearch.getBoundingClientRect().x - precanvas.getBoundingClientRect().x ) * precanvasWitdhZoom + rerouteWidth; + var eY = (elemtsearch.getBoundingClientRect().y - precanvas.getBoundingClientRect().y ) * precanvasHeightZoom + rerouteWidth; + + var elemtsearchOut = elemtsearchId_out.querySelectorAll('.'+item.parentElement.classList[3])[0] + var line_x = elemtsearchOut.offsetWidth/2 + (elemtsearchOut.getBoundingClientRect().x - precanvas.getBoundingClientRect().x ) * precanvasWitdhZoom; + var line_y = elemtsearchOut.offsetHeight/2 + (elemtsearchOut.getBoundingClientRect().y - precanvas.getBoundingClientRect().y ) * precanvasHeightZoom; + var x = eX; + var y = eY; + + var lineCurveSearch = createCurvature(line_x, line_y, x, y, reroute_curvature_start_end, 'open'); + linecurve += lineCurveSearch; + reoute_fix.push(lineCurveSearch); + + var elemtsearchId_out = item; + var id_search = item.parentElement.classList[1].replace('node_in_', ''); + var elemtsearchId = container.querySelector(`#${id_search}`); + var elemtsearch = elemtsearchId.querySelectorAll('.'+item.parentElement.classList[4])[0] + + var elemtsearchIn = elemtsearchId.querySelectorAll('.'+item.parentElement.classList[4])[0] + var eX = elemtsearchIn.offsetWidth/2 + (elemtsearchIn.getBoundingClientRect().x - precanvas.getBoundingClientRect().x ) * precanvasWitdhZoom; + var eY = elemtsearchIn.offsetHeight/2 + (elemtsearchIn.getBoundingClientRect().y - precanvas.getBoundingClientRect().y ) * precanvasHeightZoom; + + + var line_x = (elemtsearchId_out.getBoundingClientRect().x - precanvas.getBoundingClientRect().x ) * precanvasWitdhZoom + rerouteWidth; + var line_y = (elemtsearchId_out.getBoundingClientRect().y - precanvas.getBoundingClientRect().y ) * precanvasHeightZoom + rerouteWidth; + var x = eX; + var y = eY; + + var lineCurveSearch = createCurvature(line_x, line_y, x, y, reroute_curvature_start_end, 'close'); + linecurve += lineCurveSearch; + reoute_fix.push(lineCurveSearch); + + } else if(i === 0) { + + var elemtsearchId_out = container.querySelector(`#${id}`); + var elemtsearch = item; + + var eX = (elemtsearch.getBoundingClientRect().x - precanvas.getBoundingClientRect().x ) * precanvasWitdhZoom + rerouteWidth; + var eY = (elemtsearch.getBoundingClientRect().y - precanvas.getBoundingClientRect().y ) * precanvasHeightZoom + rerouteWidth; + + var elemtsearchOut = elemtsearchId_out.querySelectorAll('.'+item.parentElement.classList[3])[0] + var line_x = elemtsearchOut.offsetWidth/2 + (elemtsearchOut.getBoundingClientRect().x - precanvas.getBoundingClientRect().x ) * precanvasWitdhZoom; + var line_y = elemtsearchOut.offsetHeight/2 + (elemtsearchOut.getBoundingClientRect().y - precanvas.getBoundingClientRect().y ) * precanvasHeightZoom; + + var x = eX; + var y = eY; + + var lineCurveSearch = createCurvature(line_x, line_y, x, y, reroute_curvature_start_end, 'open'); + linecurve += lineCurveSearch; + reoute_fix.push(lineCurveSearch); + + // SECOND + var elemtsearchId_out = item; + var elemtsearch = points[i+1]; + + var eX = (elemtsearch.getBoundingClientRect().x - precanvas.getBoundingClientRect().x ) * precanvasWitdhZoom + rerouteWidth; + var eY = (elemtsearch.getBoundingClientRect().y - precanvas.getBoundingClientRect().y ) * precanvasHeightZoom + rerouteWidth; + var line_x = (elemtsearchId_out.getBoundingClientRect().x - precanvas.getBoundingClientRect().x ) * precanvasWitdhZoom + rerouteWidth; + var line_y = (elemtsearchId_out.getBoundingClientRect().y - precanvas.getBoundingClientRect().y ) * precanvasHeightZoom + rerouteWidth; + var x = eX; + var y = eY; + + var lineCurveSearch = createCurvature(line_x, line_y, x, y, reroute_curvature, 'other'); + linecurve += lineCurveSearch; + reoute_fix.push(lineCurveSearch); + + } else if (i === (points.length -1)) { + + var elemtsearchId_out = item; + + var id_search = item.parentElement.classList[1].replace('node_in_', ''); + var elemtsearchId = container.querySelector(`#${id_search}`); + var elemtsearch = elemtsearchId.querySelectorAll('.'+item.parentElement.classList[4])[0] + + var elemtsearchIn = elemtsearchId.querySelectorAll('.'+item.parentElement.classList[4])[0] + var eX = elemtsearchIn.offsetWidth/2 + (elemtsearchIn.getBoundingClientRect().x - precanvas.getBoundingClientRect().x ) * precanvasWitdhZoom; + var eY = elemtsearchIn.offsetHeight/2 + (elemtsearchIn.getBoundingClientRect().y - precanvas.getBoundingClientRect().y ) * precanvasHeightZoom; + var line_x = (elemtsearchId_out.getBoundingClientRect().x - precanvas.getBoundingClientRect().x ) * (precanvas.clientWidth / (precanvas.clientWidth * zoom)) + rerouteWidth; + var line_y = (elemtsearchId_out.getBoundingClientRect().y - precanvas.getBoundingClientRect().y ) * (precanvas.clientHeight / (precanvas.clientHeight * zoom)) + rerouteWidth; + var x = eX; + var y = eY; + + var lineCurveSearch = createCurvature(line_x, line_y, x, y, reroute_curvature_start_end, 'close'); + linecurve += lineCurveSearch; + reoute_fix.push(lineCurveSearch); + + } else { + var elemtsearchId_out = item; + var elemtsearch = points[i+1]; + + var eX = (elemtsearch.getBoundingClientRect().x - precanvas.getBoundingClientRect().x ) * (precanvas.clientWidth / (precanvas.clientWidth * zoom)) + rerouteWidth; + var eY = (elemtsearch.getBoundingClientRect().y - precanvas.getBoundingClientRect().y ) * (precanvas.clientHeight / (precanvas.clientHeight * zoom)) +rerouteWidth; + var line_x = (elemtsearchId_out.getBoundingClientRect().x - precanvas.getBoundingClientRect().x ) * (precanvas.clientWidth / (precanvas.clientWidth * zoom)) + rerouteWidth; + var line_y = (elemtsearchId_out.getBoundingClientRect().y - precanvas.getBoundingClientRect().y ) * (precanvas.clientHeight / (precanvas.clientHeight * zoom)) + rerouteWidth; + var x = eX; + var y = eY; + + var lineCurveSearch = createCurvature(line_x, line_y, x, y, reroute_curvature, 'other'); + linecurve += lineCurveSearch; + reoute_fix.push(lineCurveSearch); + } + + }); + if(reroute_fix_curvature) { + reoute_fix.forEach((itempath, i) => { + elemsOut[item].children[i].setAttributeNS(null, 'd', itempath); + }); + + } else { + elemsOut[item].children[0].setAttributeNS(null, 'd', linecurve); + } + + } + }) + + const elems = container.querySelectorAll(`.${idSearch}`); + Object.keys(elems).map(function(item, index) { + + if(elems[item].querySelector('.point') === null) { + var elemtsearchId_in = container.querySelector(`#${id}`); + + var id_search = elems[item].classList[2].replace('node_out_', ''); + var elemtsearchId = container.querySelector(`#${id_search}`); + var elemtsearch = elemtsearchId.querySelectorAll('.'+elems[item].classList[3])[0] + + var line_x = elemtsearch.offsetWidth/2 + (elemtsearch.getBoundingClientRect().x - precanvas.getBoundingClientRect().x ) * precanvasWitdhZoom; + var line_y = elemtsearch.offsetHeight/2 + (elemtsearch.getBoundingClientRect().y - precanvas.getBoundingClientRect().y ) * precanvasHeightZoom; + + var elemtsearchId_in = elemtsearchId_in.querySelectorAll('.'+elems[item].classList[4])[0] + var x = elemtsearchId_in.offsetWidth/2 + (elemtsearchId_in.getBoundingClientRect().x - precanvas.getBoundingClientRect().x ) * precanvasWitdhZoom; + var y = elemtsearchId_in.offsetHeight/2 + (elemtsearchId_in.getBoundingClientRect().y - precanvas.getBoundingClientRect().y ) * precanvasHeightZoom; + + const lineCurve = createCurvature(line_x, line_y, x, y, curvature, 'openclose'); + elems[item].children[0].setAttributeNS(null, 'd', lineCurve ); + + } else { + const points = elems[item].querySelectorAll('.point'); + let linecurve = ''; + const reoute_fix = []; + points.forEach((item, i) => { + if(i === 0 && ((points.length -1) === 0)) { + + var elemtsearchId_out = container.querySelector(`#${id}`); + var elemtsearch = item; + + var line_x = (elemtsearch.getBoundingClientRect().x - precanvas.getBoundingClientRect().x ) * precanvasWitdhZoom + rerouteWidth; + var line_y = (elemtsearch.getBoundingClientRect().y - precanvas.getBoundingClientRect().y ) * precanvasHeightZoom +rerouteWidth; + + var elemtsearchIn = elemtsearchId_out.querySelectorAll('.'+item.parentElement.classList[4])[0] + var eX = elemtsearchIn.offsetWidth/2 + (elemtsearchIn.getBoundingClientRect().x - precanvas.getBoundingClientRect().x ) * precanvasWitdhZoom; + var eY = elemtsearchIn.offsetHeight/2 + (elemtsearchIn.getBoundingClientRect().y - precanvas.getBoundingClientRect().y ) * precanvasHeightZoom; + + var x = eX; + var y = eY; + + var lineCurveSearch = createCurvature(line_x, line_y, x, y, reroute_curvature_start_end, 'close'); + linecurve += lineCurveSearch; + reoute_fix.push(lineCurveSearch); + + var elemtsearchId_out = item; + var id_search = item.parentElement.classList[2].replace('node_out_', ''); + var elemtsearchId = container.querySelector(`#${id_search}`); + var elemtsearch = elemtsearchId.querySelectorAll('.'+item.parentElement.classList[3])[0] + + var elemtsearchOut = elemtsearchId.querySelectorAll('.'+item.parentElement.classList[3])[0] + var line_x = elemtsearchOut.offsetWidth/2 + (elemtsearchOut.getBoundingClientRect().x - precanvas.getBoundingClientRect().x ) * precanvasWitdhZoom; + var line_y = elemtsearchOut.offsetHeight/2 + (elemtsearchOut.getBoundingClientRect().y - precanvas.getBoundingClientRect().y ) * precanvasHeightZoom; + + var eX = (elemtsearchId_out.getBoundingClientRect().x - precanvas.getBoundingClientRect().x ) * precanvasWitdhZoom + rerouteWidth; + var eY = (elemtsearchId_out.getBoundingClientRect().y - precanvas.getBoundingClientRect().y ) * precanvasHeightZoom + rerouteWidth; + var x = eX; + var y = eY; + + var lineCurveSearch = createCurvature(line_x, line_y, x, y, reroute_curvature_start_end, 'open'); + linecurve += lineCurveSearch; + reoute_fix.push(lineCurveSearch); + + + } else if(i === 0) { + // FIRST + var elemtsearchId_out = item; + var id_search = item.parentElement.classList[2].replace('node_out_', ''); + var elemtsearchId = container.querySelector(`#${id_search}`); + var elemtsearch = elemtsearchId.querySelectorAll('.'+item.parentElement.classList[3])[0] + var elemtsearchOut = elemtsearchId.querySelectorAll('.'+item.parentElement.classList[3])[0] + var line_x = elemtsearchOut.offsetWidth/2 + (elemtsearchOut.getBoundingClientRect().x - precanvas.getBoundingClientRect().x ) * precanvasWitdhZoom; + var line_y = elemtsearchOut.offsetHeight/2 + (elemtsearchOut.getBoundingClientRect().y - precanvas.getBoundingClientRect().y ) * precanvasHeightZoom; + + var eX = (elemtsearchId_out.getBoundingClientRect().x - precanvas.getBoundingClientRect().x ) * precanvasWitdhZoom + rerouteWidth; + var eY = (elemtsearchId_out.getBoundingClientRect().y - precanvas.getBoundingClientRect().y ) * precanvasHeightZoom + rerouteWidth; + var x = eX; + var y = eY; + + var lineCurveSearch = createCurvature(line_x, line_y, x, y, reroute_curvature_start_end, 'open'); + linecurve += lineCurveSearch; + reoute_fix.push(lineCurveSearch); + + // SECOND + var elemtsearchId_out = item; + var elemtsearch = points[i+1]; + + var eX = (elemtsearch.getBoundingClientRect().x - precanvas.getBoundingClientRect().x ) * precanvasWitdhZoom + rerouteWidth; + var eY = (elemtsearch.getBoundingClientRect().y - precanvas.getBoundingClientRect().y ) * precanvasHeightZoom +rerouteWidth; + var line_x = (elemtsearchId_out.getBoundingClientRect().x - precanvas.getBoundingClientRect().x ) * precanvasWitdhZoom + rerouteWidth; + var line_y = (elemtsearchId_out.getBoundingClientRect().y - precanvas.getBoundingClientRect().y ) * precanvasHeightZoom + rerouteWidth; + var x = eX; + var y = eY; + + var lineCurveSearch = createCurvature(line_x, line_y, x, y, reroute_curvature, 'other'); + linecurve += lineCurveSearch; + reoute_fix.push(lineCurveSearch); + + } else if (i === (points.length -1)) { + + var elemtsearchId_out = item; + + var id_search = item.parentElement.classList[1].replace('node_in_', ''); + var elemtsearchId = container.querySelector(`#${id_search}`); + var elemtsearch = elemtsearchId.querySelectorAll('.'+item.parentElement.classList[4])[0] + + var elemtsearchIn = elemtsearchId.querySelectorAll('.'+item.parentElement.classList[4])[0] + var eX = elemtsearchIn.offsetWidth/2 + (elemtsearchIn.getBoundingClientRect().x - precanvas.getBoundingClientRect().x ) * precanvasWitdhZoom; + var eY = elemtsearchIn.offsetHeight/2 + (elemtsearchIn.getBoundingClientRect().y - precanvas.getBoundingClientRect().y ) * precanvasHeightZoom; + + var line_x = (elemtsearchId_out.getBoundingClientRect().x - precanvas.getBoundingClientRect().x ) * precanvasWitdhZoom + rerouteWidth; + var line_y = (elemtsearchId_out.getBoundingClientRect().y - precanvas.getBoundingClientRect().y ) * precanvasHeightZoom + rerouteWidth; + var x = eX; + var y = eY; + + var lineCurveSearch = createCurvature(line_x, line_y, x, y, reroute_curvature_start_end, 'close'); + linecurve += lineCurveSearch; + reoute_fix.push(lineCurveSearch); + + } else { + + var elemtsearchId_out = item; + var elemtsearch = points[i+1]; + + var eX = (elemtsearch.getBoundingClientRect().x - precanvas.getBoundingClientRect().x ) * precanvasWitdhZoom + rerouteWidth; + var eY = (elemtsearch.getBoundingClientRect().y - precanvas.getBoundingClientRect().y ) * precanvasHeightZoom +rerouteWidth; + var line_x = (elemtsearchId_out.getBoundingClientRect().x - precanvas.getBoundingClientRect().x ) * precanvasWitdhZoom + rerouteWidth; + var line_y = (elemtsearchId_out.getBoundingClientRect().y - precanvas.getBoundingClientRect().y ) * precanvasHeightZoom + rerouteWidth; + var x = eX; + var y = eY; + + var lineCurveSearch = createCurvature(line_x, line_y, x, y, reroute_curvature, 'other'); + linecurve += lineCurveSearch; + reoute_fix.push(lineCurveSearch); + } + + }); + if(reroute_fix_curvature) { + reoute_fix.forEach((itempath, i) => { + elems[item].children[i].setAttributeNS(null, 'd', itempath); + }); + + } else { + elems[item].children[0].setAttributeNS(null, 'd', linecurve); + } + + } + }) + } + + dblclick(e) { + if(this.connection_selected != null && this.reroute) { + this.createReroutePoint(this.connection_selected); + } + + if(e.target.classList[0] === 'point') { + this.removeReroutePoint(e.target); + } + } + + createReroutePoint(ele) { + this.connection_selected.classList.remove("selected"); + const nodeUpdate = this.connection_selected.parentElement.classList[2].slice(9); + const nodeUpdateIn = this.connection_selected.parentElement.classList[1].slice(13); + const output_class = this.connection_selected.parentElement.classList[3]; + const input_class = this.connection_selected.parentElement.classList[4]; + this.connection_selected = null; + const point = document.createElementNS('http://www.w3.org/2000/svg',"circle"); + point.classList.add("point"); + var pos_x = this.pos_x * ( this.precanvas.clientWidth / (this.precanvas.clientWidth * this.zoom)) - (this.precanvas.getBoundingClientRect().x * ( this.precanvas.clientWidth / (this.precanvas.clientWidth * this.zoom))); + var pos_y = this.pos_y * ( this.precanvas.clientHeight / (this.precanvas.clientHeight * this.zoom)) - (this.precanvas.getBoundingClientRect().y * ( this.precanvas.clientHeight / (this.precanvas.clientHeight * this.zoom))); + + point.setAttributeNS(null, 'cx', pos_x); + point.setAttributeNS(null, 'cy', pos_y); + point.setAttributeNS(null, 'r', this.reroute_width); + + let position_add_array_point = 0; + if(this.reroute_fix_curvature) { + + const numberPoints = ele.parentElement.querySelectorAll(".main-path").length; + var path = document.createElementNS('http://www.w3.org/2000/svg',"path"); + path.classList.add("main-path"); + path.setAttributeNS(null, 'd', ''); + + ele.parentElement.insertBefore(path, ele.parentElement.children[numberPoints]); + if(numberPoints === 1) { + ele.parentElement.appendChild(point); + } else { + const search_point = Array.from(ele.parentElement.children).indexOf(ele) + position_add_array_point = search_point; + ele.parentElement.insertBefore(point, ele.parentElement.children[search_point+numberPoints+1]); + } + + } else { + ele.parentElement.appendChild(point); + } + + const nodeId = nodeUpdate.slice(5); + const searchConnection = this.drawflow.drawflow[this.module].data[nodeId].outputs[output_class].connections.findIndex(function(item,i) { + return item.node === nodeUpdateIn && item.output === input_class; + }); + + if(this.drawflow.drawflow[this.module].data[nodeId].outputs[output_class].connections[searchConnection].points === undefined) { + this.drawflow.drawflow[this.module].data[nodeId].outputs[output_class].connections[searchConnection].points = []; + } + + if(this.reroute_fix_curvature) { + + if(position_add_array_point > 0 || this.drawflow.drawflow[this.module].data[nodeId].outputs[output_class].connections[searchConnection].points !== []) { + this.drawflow.drawflow[this.module].data[nodeId].outputs[output_class].connections[searchConnection].points.splice(position_add_array_point, 0, { pos_x: pos_x, pos_y: pos_y }); + } else { + this.drawflow.drawflow[this.module].data[nodeId].outputs[output_class].connections[searchConnection].points.push({ pos_x: pos_x, pos_y: pos_y }); + } + + ele.parentElement.querySelectorAll(".main-path").forEach((item, i) => { + item.classList.remove("selected"); + }); + + } else { + this.drawflow.drawflow[this.module].data[nodeId].outputs[output_class].connections[searchConnection].points.push({ pos_x: pos_x, pos_y: pos_y }); + } + + this.dispatch('addReroute', nodeId); + this.updateConnectionNodes(nodeUpdate); + } + + removeReroutePoint(ele) { + const nodeUpdate = ele.parentElement.classList[2].slice(9) + const nodeUpdateIn = ele.parentElement.classList[1].slice(13); + const output_class = ele.parentElement.classList[3]; + const input_class = ele.parentElement.classList[4]; + + let numberPointPosition = Array.from(ele.parentElement.children).indexOf(ele); + const nodeId = nodeUpdate.slice(5); + const searchConnection = this.drawflow.drawflow[this.module].data[nodeId].outputs[output_class].connections.findIndex(function(item,i) { + return item.node === nodeUpdateIn && item.output === input_class; + }); + + if(this.reroute_fix_curvature) { + const numberMainPath = ele.parentElement.querySelectorAll(".main-path").length + ele.parentElement.children[numberMainPath-1].remove(); + numberPointPosition -= numberMainPath; + if(numberPointPosition < 0) { + numberPointPosition = 0; + } + } else { + numberPointPosition--; + } + this.drawflow.drawflow[this.module].data[nodeId].outputs[output_class].connections[searchConnection].points.splice(numberPointPosition,1); + + ele.remove(); + this.dispatch('removeReroute', nodeId); + this.updateConnectionNodes(nodeUpdate); + } + + registerNode(name, html, props = null, options = null) { + this.noderegister[name] = {html: html, props: props, options: options}; + } + + getNodeFromId(id) { + var moduleName = this.getModuleFromNodeId(id) + return JSON.parse(JSON.stringify(this.drawflow.drawflow[moduleName].data[id])); + } + getNodesFromName(name) { + var nodes = []; + const editor = this.drawflow.drawflow + Object.keys(editor).map(function(moduleName, index) { + for (var node in editor[moduleName].data) { + if(editor[moduleName].data[node].name == name) { + nodes.push(editor[moduleName].data[node].id); + } + } + }); + return nodes; + } + + addNode (name, num_in, num_out, ele_pos_x, ele_pos_y, classoverride, data, html, typenode = false) { + if (this.useuuid) { + var newNodeId = this.getUuid(); + } else { + var newNodeId = this.nodeId; + } + const parent = document.createElement('div'); + parent.classList.add("parent-node"); + + const node = document.createElement('div'); + node.innerHTML = ""; + node.setAttribute("id", "node-"+newNodeId); + node.classList.add("drawflow-node"); + if(classoverride != '') { + node.classList.add(...classoverride.split(' ')); + } + + const inputs = document.createElement('div'); + inputs.classList.add("inputs"); + + const outputs = document.createElement('div'); + outputs.classList.add("outputs"); + + const json_inputs = {} + for(var x = 0; x < num_in; x++) { + const input = document.createElement('div'); + input.classList.add("input"); + input.classList.add("input_"+(x+1)); + json_inputs["input_"+(x+1)] = { "connections": []}; + inputs.appendChild(input); + } + + const json_outputs = {} + for(var x = 0; x < num_out; x++) { + const output = document.createElement('div'); + output.classList.add("output"); + output.classList.add("output_"+(x+1)); + json_outputs["output_"+(x+1)] = { "connections": []}; + outputs.appendChild(output); + } + + const content = document.createElement('div'); + content.classList.add("drawflow_content_node"); + if(typenode === false) { + content.innerHTML = html; + } else if (typenode === true) { + content.appendChild(this.noderegister[html].html.cloneNode(true)); + } else { + if(parseInt(this.render.version) === 3 ) { + //Vue 3 + let wrapper = this.render.h(this.noderegister[html].html, this.noderegister[html].props, this.noderegister[html].options); + wrapper.appContext = this.parent; + this.render.render(wrapper,content); + + } else { + // Vue 2 + let wrapper = new this.render({ + parent: this.parent, + render: h => h(this.noderegister[html].html, { props: this.noderegister[html].props }), + ...this.noderegister[html].options + }).$mount() + // + content.appendChild(wrapper.$el); + } + } + + Object.entries(data).forEach(function (key, value) { + if(typeof key[1] === "object") { + insertObjectkeys(null, key[0], key[0]); + } else { + var elems = content.querySelectorAll('[df-'+key[0]+']'); + for(var i = 0; i < elems.length; i++) { + elems[i].value = key[1]; + if(elems[i].isContentEditable) { + elems[i].innerText = key[1]; + } + } + } + }) + + function insertObjectkeys(object, name, completname) { + if(object === null) { + var object = data[name]; + } else { + var object = object[name] + } + if(object !== null) { + Object.entries(object).forEach(function (key, value) { + if(typeof key[1] === "object") { + insertObjectkeys(object, key[0], completname+'-'+key[0]); + } else { + var elems = content.querySelectorAll('[df-'+completname+'-'+key[0]+']'); + for(var i = 0; i < elems.length; i++) { + elems[i].value = key[1]; + if(elems[i].isContentEditable) { + elems[i].innerText = key[1]; + } + } + } + }); + } + } + node.appendChild(inputs); + node.appendChild(content); + node.appendChild(outputs); + node.style.top = ele_pos_y + "px"; + node.style.left = ele_pos_x + "px"; + parent.appendChild(node); + this.precanvas.appendChild(parent); + var json = { + id: newNodeId, + name: name, + data: data, + class: classoverride, + html: html, + typenode: typenode, + inputs: json_inputs, + outputs: json_outputs, + pos_x: ele_pos_x, + pos_y: ele_pos_y, + } + this.drawflow.drawflow[this.module].data[newNodeId] = json; + this.dispatch('nodeCreated', newNodeId); + if (!this.useuuid) { + this.nodeId++; + } + return newNodeId; + } + + addNodeImport (dataNode, precanvas) { + const parent = document.createElement('div'); + parent.classList.add("parent-node"); + + const node = document.createElement('div'); + node.innerHTML = ""; + node.setAttribute("id", "node-"+dataNode.id); + node.classList.add("drawflow-node"); + if(dataNode.class != '') { + node.classList.add(...dataNode.class.split(' ')); + } + + const inputs = document.createElement('div'); + inputs.classList.add("inputs"); + + const outputs = document.createElement('div'); + outputs.classList.add("outputs"); + + Object.keys(dataNode.inputs).map(function(input_item, index) { + const input = document.createElement('div'); + input.classList.add("input"); + input.classList.add(input_item); + inputs.appendChild(input); + Object.keys(dataNode.inputs[input_item].connections).map(function(output_item, index) { + + var connection = document.createElementNS('http://www.w3.org/2000/svg',"svg"); + var path = document.createElementNS('http://www.w3.org/2000/svg',"path"); + path.classList.add("main-path"); + path.setAttributeNS(null, 'd', ''); + // path.innerHTML = 'a'; + connection.classList.add("connection"); + connection.classList.add("node_in_node-"+dataNode.id); + connection.classList.add("node_out_node-"+dataNode.inputs[input_item].connections[output_item].node); + connection.classList.add(dataNode.inputs[input_item].connections[output_item].input); + connection.classList.add(input_item); + + connection.appendChild(path); + precanvas.appendChild(connection); + + }); + }); + + for(var x = 0; x < Object.keys(dataNode.outputs).length; x++) { + const output = document.createElement('div'); + output.classList.add("output"); + output.classList.add("output_"+(x+1)); + outputs.appendChild(output); + } + + const content = document.createElement('div'); + content.classList.add("drawflow_content_node"); + + if(dataNode.typenode === false) { + content.innerHTML = dataNode.html; + } else if (dataNode.typenode === true) { + content.appendChild(this.noderegister[dataNode.html].html.cloneNode(true)); + } else { + if(parseInt(this.render.version) === 3 ) { + //Vue 3 + let wrapper = this.render.h(this.noderegister[dataNode.html].html, this.noderegister[dataNode.html].props, this.noderegister[dataNode.html].options); + wrapper.appContext = this.parent; + this.render.render(wrapper,content); + + } else { + //Vue 2 + let wrapper = new this.render({ + parent: this.parent, + render: h => h(this.noderegister[dataNode.html].html, { props: this.noderegister[dataNode.html].props }), + ...this.noderegister[dataNode.html].options + }).$mount() + content.appendChild(wrapper.$el); + } + } + + Object.entries(dataNode.data).forEach(function (key, value) { + if(typeof key[1] === "object") { + insertObjectkeys(null, key[0], key[0]); + } else { + var elems = content.querySelectorAll('[df-'+key[0]+']'); + for(var i = 0; i < elems.length; i++) { + elems[i].value = key[1]; + if(elems[i].isContentEditable) { + elems[i].innerText = key[1]; + } + } + } + }) + + function insertObjectkeys(object, name, completname) { + if(object === null) { + var object = dataNode.data[name]; + } else { + var object = object[name] + } + if(object !== null) { + Object.entries(object).forEach(function (key, value) { + if(typeof key[1] === "object") { + insertObjectkeys(object, key[0], completname+'-'+key[0]); + } else { + var elems = content.querySelectorAll('[df-'+completname+'-'+key[0]+']'); + for(var i = 0; i < elems.length; i++) { + elems[i].value = key[1]; + if(elems[i].isContentEditable) { + elems[i].innerText = key[1]; + } + } + } + }); + } + } + node.appendChild(inputs); + node.appendChild(content); + node.appendChild(outputs); + node.style.top = dataNode.pos_y + "px"; + node.style.left = dataNode.pos_x + "px"; + parent.appendChild(node); + this.precanvas.appendChild(parent); + } + + addRerouteImport(dataNode) { + const reroute_width = this.reroute_width + const reroute_fix_curvature = this.reroute_fix_curvature + const container = this.container; + Object.keys(dataNode.outputs).map(function(output_item, index) { + Object.keys(dataNode.outputs[output_item].connections).map(function(input_item, index) { + const points = dataNode.outputs[output_item].connections[input_item].points + if(points !== undefined) { + + points.forEach((item, i) => { + const input_id = dataNode.outputs[output_item].connections[input_item].node; + const input_class = dataNode.outputs[output_item].connections[input_item].output; + const ele = container.querySelector('.connection.node_in_node-'+input_id+'.node_out_node-'+dataNode.id+'.'+output_item+'.'+input_class); + + if(reroute_fix_curvature) { + if(i === 0) { + for (var z = 0; z < points.length; z++) { + var path = document.createElementNS('http://www.w3.org/2000/svg',"path"); + path.classList.add("main-path"); + path.setAttributeNS(null, 'd', ''); + ele.appendChild(path); + + } + } + } + + const point = document.createElementNS('http://www.w3.org/2000/svg',"circle"); + point.classList.add("point"); + var pos_x = item.pos_x; + var pos_y = item.pos_y; + + point.setAttributeNS(null, 'cx', pos_x); + point.setAttributeNS(null, 'cy', pos_y); + point.setAttributeNS(null, 'r', reroute_width); + + ele.appendChild(point); + }); + }; + }); + }); + } + + updateNodeValue(event) { + var attr = event.target.attributes + for (var i = 0; i < attr.length; i++) { + if (attr[i].nodeName.startsWith('df-')) { + var keys = attr[i].nodeName.slice(3).split("-"); + var target = this.drawflow.drawflow[this.module].data[event.target.closest(".drawflow_content_node").parentElement.id.slice(5)].data; + for (var index = 0; index < keys.length - 1; index += 1) { + if (target[keys[index]] == null) { + target[keys[index]] = {}; + } + target = target[keys[index]]; + } + target[keys[keys.length - 1]] = event.target.value; + if(event.target.isContentEditable) { + target[keys[keys.length - 1]] = event.target.innerText; + } + this.dispatch('nodeDataChanged', event.target.closest(".drawflow_content_node").parentElement.id.slice(5)); + } + } + } + + updateNodeDataFromId(id, data) { + var moduleName = this.getModuleFromNodeId(id) + this.drawflow.drawflow[moduleName].data[id].data = data; + if(this.module === moduleName) { + const content = this.container.querySelector('#node-'+id); + + Object.entries(data).forEach(function (key, value) { + if(typeof key[1] === "object") { + insertObjectkeys(null, key[0], key[0]); + } else { + var elems = content.querySelectorAll('[df-'+key[0]+']'); + for(var i = 0; i < elems.length; i++) { + elems[i].value = key[1]; + if(elems[i].isContentEditable) { + elems[i].innerText = key[1]; + } + } + } + }) + + function insertObjectkeys(object, name, completname) { + if(object === null) { + var object = data[name]; + } else { + var object = object[name] + } + if(object !== null) { + Object.entries(object).forEach(function (key, value) { + if(typeof key[1] === "object") { + insertObjectkeys(object, key[0], completname+'-'+key[0]); + } else { + var elems = content.querySelectorAll('[df-'+completname+'-'+key[0]+']'); + for(var i = 0; i < elems.length; i++) { + elems[i].value = key[1]; + if(elems[i].isContentEditable) { + elems[i].innerText = key[1]; + } + } + } + }); + } + } + + } + } + + addNodeInput(id) { + var moduleName = this.getModuleFromNodeId(id) + const infoNode = this.getNodeFromId(id) + const numInputs = Object.keys(infoNode.inputs).length; + if(this.module === moduleName) { + //Draw input + const input = document.createElement('div'); + input.classList.add("input"); + input.classList.add("input_"+(numInputs+1)); + const parent = this.container.querySelector('#node-'+id+' .inputs'); + parent.appendChild(input); + this.updateConnectionNodes('node-'+id); + + } + this.drawflow.drawflow[moduleName].data[id].inputs["input_"+(numInputs+1)] = { "connections": []}; + } + + addNodeOutput(id) { + var moduleName = this.getModuleFromNodeId(id) + const infoNode = this.getNodeFromId(id) + const numOutputs = Object.keys(infoNode.outputs).length; + if(this.module === moduleName) { + //Draw output + const output = document.createElement('div'); + output.classList.add("output"); + output.classList.add("output_"+(numOutputs+1)); + const parent = this.container.querySelector('#node-'+id+' .outputs'); + parent.appendChild(output); + this.updateConnectionNodes('node-'+id); + + } + this.drawflow.drawflow[moduleName].data[id].outputs["output_"+(numOutputs+1)] = { "connections": []}; + } + + removeNodeInput(id, input_class) { + var moduleName = this.getModuleFromNodeId(id) + const infoNode = this.getNodeFromId(id) + if(this.module === moduleName) { + this.container.querySelector('#node-'+id+' .inputs .input.'+input_class).remove(); + } + const removeInputs = []; + Object.keys(infoNode.inputs[input_class].connections).map(function(key, index) { + const id_output = infoNode.inputs[input_class].connections[index].node; + const output_class = infoNode.inputs[input_class].connections[index].input; + removeInputs.push({id_output, id, output_class, input_class}) + }) + // Remove connections + removeInputs.forEach((item, i) => { + this.removeSingleConnection(item.id_output, item.id, item.output_class, item.input_class); + }); + + delete this.drawflow.drawflow[moduleName].data[id].inputs[input_class]; + + // Update connection + const connections = []; + const connectionsInputs = this.drawflow.drawflow[moduleName].data[id].inputs + Object.keys(connectionsInputs).map(function(key, index) { + connections.push(connectionsInputs[key]); + }); + this.drawflow.drawflow[moduleName].data[id].inputs = {}; + const input_class_id = input_class.slice(6); + let nodeUpdates = []; + connections.forEach((item, i) => { + item.connections.forEach((itemx, f) => { + nodeUpdates.push(itemx); + }); + this.drawflow.drawflow[moduleName].data[id].inputs['input_'+ (i+1)] = item; + }); + nodeUpdates = new Set(nodeUpdates.map(e => JSON.stringify(e))); + nodeUpdates = Array.from(nodeUpdates).map(e => JSON.parse(e)); + + if(this.module === moduleName) { + const eles = this.container.querySelectorAll("#node-"+id +" .inputs .input"); + eles.forEach((item, i) => { + const id_class = item.classList[1].slice(6); + if(parseInt(input_class_id) < parseInt(id_class)) { + item.classList.remove('input_'+id_class); + item.classList.add('input_'+(id_class-1)); + } + }); + + } + + nodeUpdates.forEach((itemx, i) => { + this.drawflow.drawflow[moduleName].data[itemx.node].outputs[itemx.input].connections.forEach((itemz, g) => { + if(itemz.node == id) { + const output_id = itemz.output.slice(6); + if(parseInt(input_class_id) < parseInt(output_id)) { + if(this.module === moduleName) { + const ele = this.container.querySelector(".connection.node_in_node-"+id+".node_out_node-"+itemx.node+"."+itemx.input+".input_"+output_id); + ele.classList.remove('input_'+output_id); + ele.classList.add('input_'+(output_id-1)); + } + if(itemz.points) { + this.drawflow.drawflow[moduleName].data[itemx.node].outputs[itemx.input].connections[g] = { node: itemz.node, output: 'input_'+(output_id-1), points: itemz.points } + } else { + this.drawflow.drawflow[moduleName].data[itemx.node].outputs[itemx.input].connections[g] = { node: itemz.node, output: 'input_'+(output_id-1)} + } + } + } + }); + }); + this.updateConnectionNodes('node-'+id); + } + + removeNodeOutput(id, output_class) { + var moduleName = this.getModuleFromNodeId(id) + const infoNode = this.getNodeFromId(id) + if(this.module === moduleName) { + this.container.querySelector('#node-'+id+' .outputs .output.'+output_class).remove(); + } + const removeOutputs = []; + Object.keys(infoNode.outputs[output_class].connections).map(function(key, index) { + const id_input = infoNode.outputs[output_class].connections[index].node; + const input_class = infoNode.outputs[output_class].connections[index].output; + removeOutputs.push({id, id_input, output_class, input_class}) + }) + // Remove connections + removeOutputs.forEach((item, i) => { + this.removeSingleConnection(item.id, item.id_input, item.output_class, item.input_class); + }); + + delete this.drawflow.drawflow[moduleName].data[id].outputs[output_class]; + + // Update connection + const connections = []; + const connectionsOuputs = this.drawflow.drawflow[moduleName].data[id].outputs + Object.keys(connectionsOuputs).map(function(key, index) { + connections.push(connectionsOuputs[key]); + }); + this.drawflow.drawflow[moduleName].data[id].outputs = {}; + const output_class_id = output_class.slice(7); + let nodeUpdates = []; + connections.forEach((item, i) => { + item.connections.forEach((itemx, f) => { + nodeUpdates.push({ node: itemx.node, output: itemx.output }); + }); + this.drawflow.drawflow[moduleName].data[id].outputs['output_'+ (i+1)] = item; + }); + nodeUpdates = new Set(nodeUpdates.map(e => JSON.stringify(e))); + nodeUpdates = Array.from(nodeUpdates).map(e => JSON.parse(e)); + + if(this.module === moduleName) { + const eles = this.container.querySelectorAll("#node-"+id +" .outputs .output"); + eles.forEach((item, i) => { + const id_class = item.classList[1].slice(7); + if(parseInt(output_class_id) < parseInt(id_class)) { + item.classList.remove('output_'+id_class); + item.classList.add('output_'+(id_class-1)); + } + }); + + } + + nodeUpdates.forEach((itemx, i) => { + this.drawflow.drawflow[moduleName].data[itemx.node].inputs[itemx.output].connections.forEach((itemz, g) => { + if(itemz.node == id) { + const input_id = itemz.input.slice(7); + if(parseInt(output_class_id) < parseInt(input_id)) { + if(this.module === moduleName) { + + const ele = this.container.querySelector(".connection.node_in_node-"+itemx.node+".node_out_node-"+id+".output_"+input_id+"."+itemx.output); + ele.classList.remove('output_'+input_id); + ele.classList.remove(itemx.output); + ele.classList.add('output_'+(input_id-1)); + ele.classList.add(itemx.output); + } + if(itemz.points) { + this.drawflow.drawflow[moduleName].data[itemx.node].inputs[itemx.output].connections[g] = { node: itemz.node, input: 'output_'+(input_id-1), points: itemz.points } + } else { + this.drawflow.drawflow[moduleName].data[itemx.node].inputs[itemx.output].connections[g] = { node: itemz.node, input: 'output_'+(input_id-1)} + } + } + } + }); + }); + + this.updateConnectionNodes('node-'+id); + } + + removeNodeId(id) { + this.removeConnectionNodeId(id); + var moduleName = this.getModuleFromNodeId(id.slice(5)) + if(this.module === moduleName) { + this.container.querySelector(`#${id}`).remove(); + } + delete this.drawflow.drawflow[moduleName].data[id.slice(5)]; + this.dispatch('nodeRemoved', id.slice(5)); + } + + removeConnection() { + if(this.connection_selected != null) { + var listclass = this.connection_selected.parentElement.classList; + this.connection_selected.parentElement.remove(); + //console.log(listclass); + var index_out = this.drawflow.drawflow[this.module].data[listclass[2].slice(14)].outputs[listclass[3]].connections.findIndex(function(item,i) { + return item.node === listclass[1].slice(13) && item.output === listclass[4] + }); + this.drawflow.drawflow[this.module].data[listclass[2].slice(14)].outputs[listclass[3]].connections.splice(index_out,1); + + var index_in = this.drawflow.drawflow[this.module].data[listclass[1].slice(13)].inputs[listclass[4]].connections.findIndex(function(item,i) { + return item.node === listclass[2].slice(14) && item.input === listclass[3] + }); + this.drawflow.drawflow[this.module].data[listclass[1].slice(13)].inputs[listclass[4]].connections.splice(index_in,1); + this.dispatch('connectionRemoved', { output_id: listclass[2].slice(14), input_id: listclass[1].slice(13), output_class: listclass[3], input_class: listclass[4] } ); + this.connection_selected = null; + } + } + + removeSingleConnection(id_output, id_input, output_class, input_class) { + var nodeOneModule = this.getModuleFromNodeId(id_output); + var nodeTwoModule = this.getModuleFromNodeId(id_input); + if(nodeOneModule === nodeTwoModule) { + // Check nodes in same module. + + // Check connection exist + var exists = this.drawflow.drawflow[nodeOneModule].data[id_output].outputs[output_class].connections.findIndex(function(item,i) { + return item.node == id_input && item.output === input_class + }); + if(exists > -1) { + + if(this.module === nodeOneModule) { + // In same module with view. + this.container.querySelector('.connection.node_in_node-'+id_input+'.node_out_node-'+id_output+'.'+output_class+'.'+input_class).remove(); + } + + var index_out = this.drawflow.drawflow[nodeOneModule].data[id_output].outputs[output_class].connections.findIndex(function(item,i) { + return item.node == id_input && item.output === input_class + }); + this.drawflow.drawflow[nodeOneModule].data[id_output].outputs[output_class].connections.splice(index_out,1); + + var index_in = this.drawflow.drawflow[nodeOneModule].data[id_input].inputs[input_class].connections.findIndex(function(item,i) { + return item.node == id_output && item.input === output_class + }); + this.drawflow.drawflow[nodeOneModule].data[id_input].inputs[input_class].connections.splice(index_in,1); + + this.dispatch('connectionRemoved', { output_id: id_output, input_id: id_input, output_class: output_class, input_class: input_class}); + return true; + + } else { + return false; + } + } else { + return false; + } + } + + removeConnectionNodeId(id) { + const idSearchIn = 'node_in_'+id; + const idSearchOut = 'node_out_'+id; + + const elemsOut = this.container.querySelectorAll(`.${idSearchOut}`); + for(var i = elemsOut.length-1; i >= 0; i--) { + var listclass = elemsOut[i].classList; + + var index_in = this.drawflow.drawflow[this.module].data[listclass[1].slice(13)].inputs[listclass[4]].connections.findIndex(function(item,i) { + return item.node === listclass[2].slice(14) && item.input === listclass[3] + }); + this.drawflow.drawflow[this.module].data[listclass[1].slice(13)].inputs[listclass[4]].connections.splice(index_in,1); + + var index_out = this.drawflow.drawflow[this.module].data[listclass[2].slice(14)].outputs[listclass[3]].connections.findIndex(function(item,i) { + return item.node === listclass[1].slice(13) && item.output === listclass[4] + }); + this.drawflow.drawflow[this.module].data[listclass[2].slice(14)].outputs[listclass[3]].connections.splice(index_out,1); + + elemsOut[i].remove(); + + this.dispatch('connectionRemoved', { output_id: listclass[2].slice(14), input_id: listclass[1].slice(13), output_class: listclass[3], input_class: listclass[4] } ); + } + + const elemsIn = this.container.querySelectorAll(`.${idSearchIn}`); + for(var i = elemsIn.length-1; i >= 0; i--) { + + var listclass = elemsIn[i].classList; + + var index_out = this.drawflow.drawflow[this.module].data[listclass[2].slice(14)].outputs[listclass[3]].connections.findIndex(function(item,i) { + return item.node === listclass[1].slice(13) && item.output === listclass[4] + }); + this.drawflow.drawflow[this.module].data[listclass[2].slice(14)].outputs[listclass[3]].connections.splice(index_out,1); + + var index_in = this.drawflow.drawflow[this.module].data[listclass[1].slice(13)].inputs[listclass[4]].connections.findIndex(function(item,i) { + return item.node === listclass[2].slice(14) && item.input === listclass[3] + }); + this.drawflow.drawflow[this.module].data[listclass[1].slice(13)].inputs[listclass[4]].connections.splice(index_in,1); + + elemsIn[i].remove(); + + this.dispatch('connectionRemoved', { output_id: listclass[2].slice(14), input_id: listclass[1].slice(13), output_class: listclass[3], input_class: listclass[4] } ); + } + } + + getModuleFromNodeId(id) { + var nameModule; + const editor = this.drawflow.drawflow + Object.keys(editor).map(function(moduleName, index) { + Object.keys(editor[moduleName].data).map(function(node, index2) { + if(node == id) { + nameModule = moduleName; + } + }) + }); + return nameModule; + } + + addModule(name) { + this.drawflow.drawflow[name] = { "data": {} }; + this.dispatch('moduleCreated', name); + } + changeModule(name) { + this.dispatch('moduleChanged', name); + this.module = name; + this.precanvas.innerHTML = ""; + this.canvas_x = 0; + this.canvas_y = 0; + this.pos_x = 0; + this.pos_y = 0; + this.mouse_x = 0; + this.mouse_y = 0; + this.zoom = 1; + this.zoom_last_value = 1; + this.precanvas.style.transform = ''; + this.import(this.drawflow, false); + } + + removeModule(name) { + if(this.module === name) { + this.changeModule('Home'); + } + delete this.drawflow.drawflow[name]; + this.dispatch('moduleRemoved', name); + } + + clearModuleSelected() { + this.precanvas.innerHTML = ""; + this.drawflow.drawflow[this.module] = { "data": {} }; + } + + clear () { + this.precanvas.innerHTML = ""; + this.drawflow = { "drawflow": { "Home": { "data": {} }}}; + } + export () { + const dataExport = JSON.parse(JSON.stringify(this.drawflow)); + this.dispatch('export', dataExport); + return dataExport; + } + + import (data, notifi = true) { + this.clear(); + this.drawflow = JSON.parse(JSON.stringify(data)); + this.load(); + if(notifi) { + this.dispatch('import', 'import'); + } + } + + /* Events */ + on (event, callback) { + // Check if the callback is not a function + if (typeof callback !== 'function') { + console.error(`The listener callback must be a function, the given type is ${typeof callback}`); + return false; + } + // Check if the event is not a string + if (typeof event !== 'string') { + console.error(`The event name must be a string, the given type is ${typeof event}`); + return false; + } + // Check if this event not exists + if (this.events[event] === undefined) { + this.events[event] = { + listeners: [] + } + } + this.events[event].listeners.push(callback); + } + + removeListener (event, callback) { + // Check if this event not exists + + if (!this.events[event]) return false + + const listeners = this.events[event].listeners + const listenerIndex = listeners.indexOf(callback) + const hasListener = listenerIndex > -1 + if (hasListener) listeners.splice(listenerIndex, 1) + } + + dispatch (event, details) { + // Check if this event not exists + if (this.events[event] === undefined) { + // console.error(`This event: ${event} does not exist`); + return false; + } + this.events[event].listeners.forEach((listener) => { + listener(details); + }); + } + + getUuid() { + // http://www.ietf.org/rfc/rfc4122.txt + var s = []; + var hexDigits = "0123456789abcdef"; + for (var i = 0; i < 36; i++) { + s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1); + } + s[14] = "4"; // bits 12-15 of the time_hi_and_version field to 0010 + s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01 + s[8] = s[13] = s[18] = s[23] = "-"; + + var uuid = s.join(""); + return uuid; + } +} diff --git a/src/main/resources/static/plugins/drawflow/drawflow.min.css b/src/main/resources/static/plugins/drawflow/drawflow.min.css new file mode 100644 index 0000000..c9c9442 --- /dev/null +++ b/src/main/resources/static/plugins/drawflow/drawflow.min.css @@ -0,0 +1 @@ +.drawflow,.drawflow .parent-node{position:relative}.parent-drawflow{display:flex;overflow:hidden;touch-action:none;outline:0}.drawflow{width:100%;height:100%;user-select:none;perspective:0}.drawflow .drawflow-node{display:flex;align-items:center;position:absolute;background:#0ff;width:160px;min-height:40px;border-radius:4px;border:2px solid #000;color:#000;z-index:2;padding:15px}.drawflow .drawflow-node.selected{background:red}.drawflow .drawflow-node:hover{cursor:move}.drawflow .drawflow-node .inputs,.drawflow .drawflow-node .outputs{width:0}.drawflow .drawflow-node .drawflow_content_node{width:100%;display:block}.drawflow .drawflow-node .input,.drawflow .drawflow-node .output{position:relative;width:20px;height:20px;background:#fff;border-radius:50%;border:2px solid #000;cursor:crosshair;z-index:1;margin-bottom:5px}.drawflow .drawflow-node .input{left:-27px;top:2px;background:#ff0}.drawflow .drawflow-node .output{right:-3px;top:2px}.drawflow svg{z-index:0;position:absolute;overflow:visible!important}.drawflow .connection{position:absolute;pointer-events:none;aspect-ratio:1/1}.drawflow .connection .main-path{fill:none;stroke-width:5px;stroke:#4682b4;pointer-events:all}.drawflow .connection .main-path:hover{stroke:#1266ab;cursor:pointer}.drawflow .connection .main-path.selected{stroke:#43b993}.drawflow .connection .point{cursor:move;stroke:#000;stroke-width:2;fill:#fff;pointer-events:all}.drawflow .connection .point.selected,.drawflow .connection .point:hover{fill:#1266ab}.drawflow .main-path{fill:none;stroke-width:5px;stroke:#4682b4}.drawflow-delete{position:absolute;display:block;width:30px;height:30px;background:#000;color:#fff;z-index:4;border:2px solid #fff;line-height:30px;font-weight:700;text-align:center;border-radius:50%;font-family:monospace;cursor:pointer}.drawflow>.drawflow-delete{margin-left:-15px;margin-top:15px}.parent-node .drawflow-delete{right:-15px;top:-15px} \ No newline at end of file diff --git a/src/main/resources/static/plugins/drawflow/drawflow.min.js b/src/main/resources/static/plugins/drawflow/drawflow.min.js new file mode 100644 index 0000000..012df79 --- /dev/null +++ b/src/main/resources/static/plugins/drawflow/drawflow.min.js @@ -0,0 +1 @@ +!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.Drawflow=t():e.Drawflow=t()}("undefined"!=typeof self?self:this,(function(){return function(e){var t={};function n(i){if(t[i])return t[i].exports;var s=t[i]={i:i,l:!1,exports:{}};return e[i].call(s.exports,s,s.exports,n),s.l=!0,s.exports}return n.m=e,n.c=t,n.d=function(e,t,i){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:i})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var s in e)n.d(i,s,function(t){return e[t]}.bind(null,s));return i},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t,n){"use strict";n.r(t),n.d(t,"default",(function(){return i}));class i{constructor(e,t=null,n=null){this.events={},this.container=e,this.precanvas=null,this.nodeId=1,this.ele_selected=null,this.node_selected=null,this.drag=!1,this.reroute=!1,this.reroute_fix_curvature=!1,this.curvature=.5,this.reroute_curvature_start_end=.5,this.reroute_curvature=.5,this.reroute_width=6,this.drag_point=!1,this.editor_selected=!1,this.connection=!1,this.connection_ele=null,this.connection_selected=null,this.canvas_x=0,this.canvas_y=0,this.pos_x=0,this.pos_x_start=0,this.pos_y=0,this.pos_y_start=0,this.mouse_x=0,this.mouse_y=0,this.line_path=5,this.first_click=null,this.force_first_input=!1,this.draggable_inputs=!0,this.useuuid=!1,this.parent=n,this.noderegister={},this.render=t,this.drawflow={drawflow:{Home:{data:{}}}},this.module="Home",this.editor_mode="edit",this.zoom=1,this.zoom_max=1.6,this.zoom_min=.5,this.zoom_value=.1,this.zoom_last_value=1,this.evCache=new Array,this.prevDiff=-1}start(){this.container.classList.add("parent-drawflow"),this.container.tabIndex=0,this.precanvas=document.createElement("div"),this.precanvas.classList.add("drawflow"),this.container.appendChild(this.precanvas),this.container.addEventListener("mouseup",this.dragEnd.bind(this)),this.container.addEventListener("mousemove",this.position.bind(this)),this.container.addEventListener("mousedown",this.click.bind(this)),this.container.addEventListener("touchend",this.dragEnd.bind(this)),this.container.addEventListener("touchmove",this.position.bind(this)),this.container.addEventListener("touchstart",this.click.bind(this)),this.container.addEventListener("contextmenu",this.contextmenu.bind(this)),this.container.addEventListener("keydown",this.key.bind(this)),this.container.addEventListener("wheel",this.zoom_enter.bind(this)),this.container.addEventListener("input",this.updateNodeValue.bind(this)),this.container.addEventListener("dblclick",this.dblclick.bind(this)),this.container.onpointerdown=this.pointerdown_handler.bind(this),this.container.onpointermove=this.pointermove_handler.bind(this),this.container.onpointerup=this.pointerup_handler.bind(this),this.container.onpointercancel=this.pointerup_handler.bind(this),this.container.onpointerout=this.pointerup_handler.bind(this),this.container.onpointerleave=this.pointerup_handler.bind(this),this.load()}pointerdown_handler(e){this.evCache.push(e)}pointermove_handler(e){for(var t=0;t100&&(n>this.prevDiff&&this.zoom_in(),n=n&&(n=parseInt(e)+1)}))})),this.nodeId=n}removeReouteConnectionSelected(){this.dispatch("connectionUnselected",!0),this.reroute_fix_curvature&&this.connection_selected.parentElement.querySelectorAll(".main-path").forEach((e,t)=>{e.classList.remove("selected")})}click(e){if(this.dispatch("click",e),"fixed"===this.editor_mode){if(e.preventDefault(),"parent-drawflow"!==e.target.classList[0]&&"drawflow"!==e.target.classList[0])return!1;this.ele_selected=e.target.closest(".parent-drawflow")}else"view"===this.editor_mode?(null!=e.target.closest(".drawflow")||e.target.matches(".parent-drawflow"))&&(this.ele_selected=e.target.closest(".parent-drawflow"),e.preventDefault()):(this.first_click=e.target,this.ele_selected=e.target,0===e.button&&this.contextmenuDel(),null!=e.target.closest(".drawflow_content_node")&&(this.ele_selected=e.target.closest(".drawflow_content_node").parentElement));switch(this.ele_selected.classList[0]){case"drawflow-node":null!=this.node_selected&&(this.node_selected.classList.remove("selected"),this.node_selected!=this.ele_selected&&this.dispatch("nodeUnselected",!0)),null!=this.connection_selected&&(this.connection_selected.classList.remove("selected"),this.removeReouteConnectionSelected(),this.connection_selected=null),this.node_selected!=this.ele_selected&&this.dispatch("nodeSelected",this.ele_selected.id.slice(5)),this.node_selected=this.ele_selected,this.node_selected.classList.add("selected"),this.draggable_inputs?"SELECT"!==e.target.tagName&&(this.drag=!0):"INPUT"!==e.target.tagName&&"TEXTAREA"!==e.target.tagName&&"SELECT"!==e.target.tagName&&!0!==e.target.hasAttribute("contenteditable")&&(this.drag=!0);break;case"output":this.connection=!0,null!=this.node_selected&&(this.node_selected.classList.remove("selected"),this.node_selected=null,this.dispatch("nodeUnselected",!0)),null!=this.connection_selected&&(this.connection_selected.classList.remove("selected"),this.removeReouteConnectionSelected(),this.connection_selected=null),this.drawConnection(e.target);break;case"parent-drawflow":case"drawflow":null!=this.node_selected&&(this.node_selected.classList.remove("selected"),this.node_selected=null,this.dispatch("nodeUnselected",!0)),null!=this.connection_selected&&(this.connection_selected.classList.remove("selected"),this.removeReouteConnectionSelected(),this.connection_selected=null),this.editor_selected=!0;break;case"main-path":null!=this.node_selected&&(this.node_selected.classList.remove("selected"),this.node_selected=null,this.dispatch("nodeUnselected",!0)),null!=this.connection_selected&&(this.connection_selected.classList.remove("selected"),this.removeReouteConnectionSelected(),this.connection_selected=null),this.connection_selected=this.ele_selected,this.connection_selected.classList.add("selected");const t=this.connection_selected.parentElement.classList;t.length>1&&(this.dispatch("connectionSelected",{output_id:t[2].slice(14),input_id:t[1].slice(13),output_class:t[3],input_class:t[4]}),this.reroute_fix_curvature&&this.connection_selected.parentElement.querySelectorAll(".main-path").forEach((e,t)=>{e.classList.add("selected")}));break;case"point":this.drag_point=!0,this.ele_selected.classList.add("selected");break;case"drawflow-delete":this.node_selected&&this.removeNodeId(this.node_selected.id),this.connection_selected&&this.removeConnection(),null!=this.node_selected&&(this.node_selected.classList.remove("selected"),this.node_selected=null,this.dispatch("nodeUnselected",!0)),null!=this.connection_selected&&(this.connection_selected.classList.remove("selected"),this.removeReouteConnectionSelected(),this.connection_selected=null)}"touchstart"===e.type?(this.pos_x=e.touches[0].clientX,this.pos_x_start=e.touches[0].clientX,this.pos_y=e.touches[0].clientY,this.pos_y_start=e.touches[0].clientY,this.mouse_x=e.touches[0].clientX,this.mouse_y=e.touches[0].clientY):(this.pos_x=e.clientX,this.pos_x_start=e.clientX,this.pos_y=e.clientY,this.pos_y_start=e.clientY),["input","output","main-path"].includes(this.ele_selected.classList[0])&&e.preventDefault(),this.dispatch("clickEnd",e)}position(e){if("touchmove"===e.type)var t=e.touches[0].clientX,n=e.touches[0].clientY;else t=e.clientX,n=e.clientY;if(this.connection&&this.updateConnection(t,n),this.editor_selected&&(i=this.canvas_x+-(this.pos_x-t),s=this.canvas_y+-(this.pos_y-n),this.dispatch("translate",{x:i,y:s}),this.precanvas.style.transform="translate("+i+"px, "+s+"px) scale("+this.zoom+")"),this.drag){e.preventDefault();var i=(this.pos_x-t)*this.precanvas.clientWidth/(this.precanvas.clientWidth*this.zoom),s=(this.pos_y-n)*this.precanvas.clientHeight/(this.precanvas.clientHeight*this.zoom);this.pos_x=t,this.pos_y=n,this.ele_selected.style.top=this.ele_selected.offsetTop-s+"px",this.ele_selected.style.left=this.ele_selected.offsetLeft-i+"px",this.drawflow.drawflow[this.module].data[this.ele_selected.id.slice(5)].pos_x=this.ele_selected.offsetLeft-i,this.drawflow.drawflow[this.module].data[this.ele_selected.id.slice(5)].pos_y=this.ele_selected.offsetTop-s,this.updateConnectionNodes(this.ele_selected.id)}if(this.drag_point){i=(this.pos_x-t)*this.precanvas.clientWidth/(this.precanvas.clientWidth*this.zoom),s=(this.pos_y-n)*this.precanvas.clientHeight/(this.precanvas.clientHeight*this.zoom);this.pos_x=t,this.pos_y=n;var o=this.pos_x*(this.precanvas.clientWidth/(this.precanvas.clientWidth*this.zoom))-this.precanvas.getBoundingClientRect().x*(this.precanvas.clientWidth/(this.precanvas.clientWidth*this.zoom)),l=this.pos_y*(this.precanvas.clientHeight/(this.precanvas.clientHeight*this.zoom))-this.precanvas.getBoundingClientRect().y*(this.precanvas.clientHeight/(this.precanvas.clientHeight*this.zoom));this.ele_selected.setAttributeNS(null,"cx",o),this.ele_selected.setAttributeNS(null,"cy",l);const e=this.ele_selected.parentElement.classList[2].slice(9),c=this.ele_selected.parentElement.classList[1].slice(13),d=this.ele_selected.parentElement.classList[3],a=this.ele_selected.parentElement.classList[4];let r=Array.from(this.ele_selected.parentElement.children).indexOf(this.ele_selected)-1;if(this.reroute_fix_curvature){r-=this.ele_selected.parentElement.querySelectorAll(".main-path").length-1,r<0&&(r=0)}const h=e.slice(5),u=this.drawflow.drawflow[this.module].data[h].outputs[d].connections.findIndex((function(e,t){return e.node===c&&e.output===a}));this.drawflow.drawflow[this.module].data[h].outputs[d].connections[u].points[r]={pos_x:o,pos_y:l};const p=this.ele_selected.parentElement.classList[2].slice(9);this.updateConnectionNodes(p)}"touchmove"===e.type&&(this.mouse_x=t,this.mouse_y=n),this.dispatch("mouseMove",{x:t,y:n})}dragEnd(e){if("touchend"===e.type)var t=this.mouse_x,n=this.mouse_y,i=document.elementFromPoint(t,n);else t=e.clientX,n=e.clientY,i=e.target;if(this.drag&&(this.pos_x_start==t&&this.pos_y_start==n||this.dispatch("nodeMoved",this.ele_selected.id.slice(5))),this.drag_point&&(this.ele_selected.classList.remove("selected"),this.pos_x_start==t&&this.pos_y_start==n||this.dispatch("rerouteMoved",this.ele_selected.parentElement.classList[2].slice(14))),this.editor_selected&&(this.canvas_x=this.canvas_x+-(this.pos_x-t),this.canvas_y=this.canvas_y+-(this.pos_y-n),this.editor_selected=!1),!0===this.connection)if("input"===i.classList[0]||this.force_first_input&&(null!=i.closest(".drawflow_content_node")||"drawflow-node"===i.classList[0])){if(!this.force_first_input||null==i.closest(".drawflow_content_node")&&"drawflow-node"!==i.classList[0])s=i.parentElement.parentElement.id,o=i.classList[1];else{if(null!=i.closest(".drawflow_content_node"))var s=i.closest(".drawflow_content_node").parentElement.id;else var s=i.id;if(0===Object.keys(this.getNodeFromId(s.slice(5)).inputs).length)var o=!1;else var o="input_1"}var l=this.ele_selected.parentElement.parentElement.id,c=this.ele_selected.classList[1];if(l!==s&&!1!==o){if(0===this.container.querySelectorAll(".connection.node_in_"+s+".node_out_"+l+"."+c+"."+o).length){this.connection_ele.classList.add("node_in_"+s),this.connection_ele.classList.add("node_out_"+l),this.connection_ele.classList.add(c),this.connection_ele.classList.add(o);var d=s.slice(5),a=l.slice(5);this.drawflow.drawflow[this.module].data[a].outputs[c].connections.push({node:d,output:o}),this.drawflow.drawflow[this.module].data[d].inputs[o].connections.push({node:a,input:c}),this.updateConnectionNodes("node-"+a),this.updateConnectionNodes("node-"+d),this.dispatch("connectionCreated",{output_id:a,input_id:d,output_class:c,input_class:o})}else this.dispatch("connectionCancel",!0),this.connection_ele.remove();this.connection_ele=null}else this.dispatch("connectionCancel",!0),this.connection_ele.remove(),this.connection_ele=null}else this.dispatch("connectionCancel",!0),this.connection_ele.remove(),this.connection_ele=null;this.drag=!1,this.drag_point=!1,this.connection=!1,this.ele_selected=null,this.editor_selected=!1,this.dispatch("mouseUp",e)}contextmenu(e){if(this.dispatch("contextmenu",e),e.preventDefault(),"fixed"===this.editor_mode||"view"===this.editor_mode)return!1;if(this.precanvas.getElementsByClassName("drawflow-delete").length&&this.precanvas.getElementsByClassName("drawflow-delete")[0].remove(),this.node_selected||this.connection_selected){var t=document.createElement("div");t.classList.add("drawflow-delete"),t.innerHTML="x",this.node_selected&&this.node_selected.appendChild(t),this.connection_selected&&this.connection_selected.parentElement.classList.length>1&&(t.style.top=e.clientY*(this.precanvas.clientHeight/(this.precanvas.clientHeight*this.zoom))-this.precanvas.getBoundingClientRect().y*(this.precanvas.clientHeight/(this.precanvas.clientHeight*this.zoom))+"px",t.style.left=e.clientX*(this.precanvas.clientWidth/(this.precanvas.clientWidth*this.zoom))-this.precanvas.getBoundingClientRect().x*(this.precanvas.clientWidth/(this.precanvas.clientWidth*this.zoom))+"px",this.precanvas.appendChild(t))}}contextmenuDel(){this.precanvas.getElementsByClassName("drawflow-delete").length&&this.precanvas.getElementsByClassName("drawflow-delete")[0].remove()}key(e){if(this.dispatch("keydown",e),"fixed"===this.editor_mode||"view"===this.editor_mode)return!1;("Delete"===e.key||"Backspace"===e.key&&e.metaKey)&&(null!=this.node_selected&&"INPUT"!==this.first_click.tagName&&"TEXTAREA"!==this.first_click.tagName&&!0!==this.first_click.hasAttribute("contenteditable")&&this.removeNodeId(this.node_selected.id),null!=this.connection_selected&&this.removeConnection())}zoom_enter(e,t){e.ctrlKey&&(e.preventDefault(),e.deltaY>0?this.zoom_out():this.zoom_in())}zoom_refresh(){this.dispatch("zoom",this.zoom),this.canvas_x=this.canvas_x/this.zoom_last_value*this.zoom,this.canvas_y=this.canvas_y/this.zoom_last_value*this.zoom,this.zoom_last_value=this.zoom,this.precanvas.style.transform="translate("+this.canvas_x+"px, "+this.canvas_y+"px) scale("+this.zoom+")"}zoom_in(){this.zoomthis.zoom_min&&(this.zoom-=this.zoom_value,this.zoom_refresh())}zoom_reset(){1!=this.zoom&&(this.zoom=1,this.zoom_refresh())}createCurvature(e,t,n,i,s,o){var l=e,c=t,d=n,a=i,r=s;switch(o){case"open":if(e>=n)var h=l+Math.abs(d-l)*r,u=d-Math.abs(d-l)*(-1*r);else h=l+Math.abs(d-l)*r,u=d-Math.abs(d-l)*r;return" M "+l+" "+c+" C "+h+" "+c+" "+u+" "+a+" "+d+" "+a;case"close":if(e>=n)h=l+Math.abs(d-l)*(-1*r),u=d-Math.abs(d-l)*r;else h=l+Math.abs(d-l)*r,u=d-Math.abs(d-l)*r;return" M "+l+" "+c+" C "+h+" "+c+" "+u+" "+a+" "+d+" "+a;case"other":if(e>=n)h=l+Math.abs(d-l)*(-1*r),u=d-Math.abs(d-l)*(-1*r);else h=l+Math.abs(d-l)*r,u=d-Math.abs(d-l)*r;return" M "+l+" "+c+" C "+h+" "+c+" "+u+" "+a+" "+d+" "+a;default:return" M "+l+" "+c+" C "+(h=l+Math.abs(d-l)*r)+" "+c+" "+(u=d-Math.abs(d-l)*r)+" "+a+" "+d+" "+a}}drawConnection(e){var t=document.createElementNS("http://www.w3.org/2000/svg","svg");this.connection_ele=t;var n=document.createElementNS("http://www.w3.org/2000/svg","path");n.classList.add("main-path"),n.setAttributeNS(null,"d",""),t.classList.add("connection"),t.appendChild(n),this.precanvas.appendChild(t);var i=e.parentElement.parentElement.id.slice(5),s=e.classList[1];this.dispatch("connectionStart",{output_id:i,output_class:s})}updateConnection(e,t){const n=this.precanvas,i=this.zoom;let s=n.clientWidth/(n.clientWidth*i);s=s||0;let o=n.clientHeight/(n.clientHeight*i);o=o||0;var l=this.connection_ele.children[0],c=this.ele_selected.offsetWidth/2+(this.ele_selected.getBoundingClientRect().x-n.getBoundingClientRect().x)*s,d=this.ele_selected.offsetHeight/2+(this.ele_selected.getBoundingClientRect().y-n.getBoundingClientRect().y)*o,a=e*(this.precanvas.clientWidth/(this.precanvas.clientWidth*this.zoom))-this.precanvas.getBoundingClientRect().x*(this.precanvas.clientWidth/(this.precanvas.clientWidth*this.zoom)),r=t*(this.precanvas.clientHeight/(this.precanvas.clientHeight*this.zoom))-this.precanvas.getBoundingClientRect().y*(this.precanvas.clientHeight/(this.precanvas.clientHeight*this.zoom)),h=this.curvature,u=this.createCurvature(c,d,a,r,h,"openclose");l.setAttributeNS(null,"d",u)}addConnection(e,t,n,i){var s=this.getModuleFromNodeId(e);if(s===this.getModuleFromNodeId(t)){var o=this.getNodeFromId(e),l=!1;for(var c in o.outputs[n].connections){var d=o.outputs[n].connections[c];d.node==t&&d.output==i&&(l=!0)}if(!1===l){if(this.drawflow.drawflow[s].data[e].outputs[n].connections.push({node:t.toString(),output:i}),this.drawflow.drawflow[s].data[t].inputs[i].connections.push({node:e.toString(),input:n}),this.module===s){var a=document.createElementNS("http://www.w3.org/2000/svg","svg"),r=document.createElementNS("http://www.w3.org/2000/svg","path");r.classList.add("main-path"),r.setAttributeNS(null,"d",""),a.classList.add("connection"),a.classList.add("node_in_node-"+t),a.classList.add("node_out_node-"+e),a.classList.add(n),a.classList.add(i),a.appendChild(r),this.precanvas.appendChild(a),this.updateConnectionNodes("node-"+e),this.updateConnectionNodes("node-"+t)}this.dispatch("connectionCreated",{output_id:e,input_id:t,output_class:n,input_class:i})}}}updateConnectionNodes(e){const t="node_in_"+e,n="node_out_"+e;this.line_path;const i=this.container,s=this.precanvas,o=this.curvature,l=this.createCurvature,c=this.reroute_curvature,d=this.reroute_curvature_start_end,a=this.reroute_fix_curvature,r=this.reroute_width,h=this.zoom;let u=s.clientWidth/(s.clientWidth*h);u=u||0;let p=s.clientHeight/(s.clientHeight*h);p=p||0;const f=i.querySelectorAll("."+n);Object.keys(f).map((function(t,n){if(null===f[t].querySelector(".point")){var m=i.querySelector("#"+e),g=f[t].classList[1].replace("node_in_",""),_=i.querySelector("#"+g).querySelectorAll("."+f[t].classList[4])[0],w=_.offsetWidth/2+(_.getBoundingClientRect().x-s.getBoundingClientRect().x)*u,v=_.offsetHeight/2+(_.getBoundingClientRect().y-s.getBoundingClientRect().y)*p,y=m.querySelectorAll("."+f[t].classList[3])[0],C=y.offsetWidth/2+(y.getBoundingClientRect().x-s.getBoundingClientRect().x)*u,x=y.offsetHeight/2+(y.getBoundingClientRect().y-s.getBoundingClientRect().y)*p;const n=l(C,x,w,v,o,"openclose");f[t].children[0].setAttributeNS(null,"d",n)}else{const n=f[t].querySelectorAll(".point");let o="";const m=[];n.forEach((t,a)=>{if(0===a&&n.length-1==0){var f=i.querySelector("#"+e),g=((x=t).getBoundingClientRect().x-s.getBoundingClientRect().x)*u+r,_=(x.getBoundingClientRect().y-s.getBoundingClientRect().y)*p+r,w=(L=f.querySelectorAll("."+t.parentElement.classList[3])[0]).offsetWidth/2+(L.getBoundingClientRect().x-s.getBoundingClientRect().x)*u,v=L.offsetHeight/2+(L.getBoundingClientRect().y-s.getBoundingClientRect().y)*p,y=l(w,v,g,_,d,"open");o+=y,m.push(y);f=t;var C=t.parentElement.classList[1].replace("node_in_",""),x=(E=i.querySelector("#"+C)).querySelectorAll("."+t.parentElement.classList[4])[0];g=(R=E.querySelectorAll("."+t.parentElement.classList[4])[0]).offsetWidth/2+(R.getBoundingClientRect().x-s.getBoundingClientRect().x)*u,_=R.offsetHeight/2+(R.getBoundingClientRect().y-s.getBoundingClientRect().y)*p,w=(f.getBoundingClientRect().x-s.getBoundingClientRect().x)*u+r,v=(f.getBoundingClientRect().y-s.getBoundingClientRect().y)*p+r,y=l(w,v,g,_,d,"close");o+=y,m.push(y)}else if(0===a){var L;f=i.querySelector("#"+e),g=((x=t).getBoundingClientRect().x-s.getBoundingClientRect().x)*u+r,_=(x.getBoundingClientRect().y-s.getBoundingClientRect().y)*p+r,w=(L=f.querySelectorAll("."+t.parentElement.classList[3])[0]).offsetWidth/2+(L.getBoundingClientRect().x-s.getBoundingClientRect().x)*u,v=L.offsetHeight/2+(L.getBoundingClientRect().y-s.getBoundingClientRect().y)*p,y=l(w,v,g,_,d,"open");o+=y,m.push(y);f=t,g=((x=n[a+1]).getBoundingClientRect().x-s.getBoundingClientRect().x)*u+r,_=(x.getBoundingClientRect().y-s.getBoundingClientRect().y)*p+r,w=(f.getBoundingClientRect().x-s.getBoundingClientRect().x)*u+r,v=(f.getBoundingClientRect().y-s.getBoundingClientRect().y)*p+r,y=l(w,v,g,_,c,"other");o+=y,m.push(y)}else if(a===n.length-1){var E,R;f=t,C=t.parentElement.classList[1].replace("node_in_",""),x=(E=i.querySelector("#"+C)).querySelectorAll("."+t.parentElement.classList[4])[0],g=(R=E.querySelectorAll("."+t.parentElement.classList[4])[0]).offsetWidth/2+(R.getBoundingClientRect().x-s.getBoundingClientRect().x)*u,_=R.offsetHeight/2+(R.getBoundingClientRect().y-s.getBoundingClientRect().y)*p,w=(f.getBoundingClientRect().x-s.getBoundingClientRect().x)*(s.clientWidth/(s.clientWidth*h))+r,v=(f.getBoundingClientRect().y-s.getBoundingClientRect().y)*(s.clientHeight/(s.clientHeight*h))+r,y=l(w,v,g,_,d,"close");o+=y,m.push(y)}else{f=t,g=((x=n[a+1]).getBoundingClientRect().x-s.getBoundingClientRect().x)*(s.clientWidth/(s.clientWidth*h))+r,_=(x.getBoundingClientRect().y-s.getBoundingClientRect().y)*(s.clientHeight/(s.clientHeight*h))+r,w=(f.getBoundingClientRect().x-s.getBoundingClientRect().x)*(s.clientWidth/(s.clientWidth*h))+r,v=(f.getBoundingClientRect().y-s.getBoundingClientRect().y)*(s.clientHeight/(s.clientHeight*h))+r,y=l(w,v,g,_,c,"other");o+=y,m.push(y)}}),a?m.forEach((e,n)=>{f[t].children[n].setAttributeNS(null,"d",e)}):f[t].children[0].setAttributeNS(null,"d",o)}}));const m=i.querySelectorAll("."+t);Object.keys(m).map((function(t,n){if(null===m[t].querySelector(".point")){var h=i.querySelector("#"+e),f=m[t].classList[2].replace("node_out_",""),g=i.querySelector("#"+f).querySelectorAll("."+m[t].classList[3])[0],_=g.offsetWidth/2+(g.getBoundingClientRect().x-s.getBoundingClientRect().x)*u,w=g.offsetHeight/2+(g.getBoundingClientRect().y-s.getBoundingClientRect().y)*p,v=(h=h.querySelectorAll("."+m[t].classList[4])[0]).offsetWidth/2+(h.getBoundingClientRect().x-s.getBoundingClientRect().x)*u,y=h.offsetHeight/2+(h.getBoundingClientRect().y-s.getBoundingClientRect().y)*p;const n=l(_,w,v,y,o,"openclose");m[t].children[0].setAttributeNS(null,"d",n)}else{const n=m[t].querySelectorAll(".point");let o="";const h=[];n.forEach((t,a)=>{if(0===a&&n.length-1==0){var f=i.querySelector("#"+e),m=((C=t).getBoundingClientRect().x-s.getBoundingClientRect().x)*u+r,g=(C.getBoundingClientRect().y-s.getBoundingClientRect().y)*p+r,_=(E=f.querySelectorAll("."+t.parentElement.classList[4])[0]).offsetWidth/2+(E.getBoundingClientRect().x-s.getBoundingClientRect().x)*u,w=E.offsetHeight/2+(E.getBoundingClientRect().y-s.getBoundingClientRect().y)*p,v=l(m,g,_,w,d,"close");o+=v,h.push(v);f=t;var y=t.parentElement.classList[2].replace("node_out_",""),C=(L=i.querySelector("#"+y)).querySelectorAll("."+t.parentElement.classList[3])[0];m=(x=L.querySelectorAll("."+t.parentElement.classList[3])[0]).offsetWidth/2+(x.getBoundingClientRect().x-s.getBoundingClientRect().x)*u,g=x.offsetHeight/2+(x.getBoundingClientRect().y-s.getBoundingClientRect().y)*p,_=(f.getBoundingClientRect().x-s.getBoundingClientRect().x)*u+r,w=(f.getBoundingClientRect().y-s.getBoundingClientRect().y)*p+r,v=l(m,g,_,w,d,"open");o+=v,h.push(v)}else if(0===a){var x;f=t,y=t.parentElement.classList[2].replace("node_out_",""),C=(L=i.querySelector("#"+y)).querySelectorAll("."+t.parentElement.classList[3])[0],m=(x=L.querySelectorAll("."+t.parentElement.classList[3])[0]).offsetWidth/2+(x.getBoundingClientRect().x-s.getBoundingClientRect().x)*u,g=x.offsetHeight/2+(x.getBoundingClientRect().y-s.getBoundingClientRect().y)*p,_=(f.getBoundingClientRect().x-s.getBoundingClientRect().x)*u+r,w=(f.getBoundingClientRect().y-s.getBoundingClientRect().y)*p+r,v=l(m,g,_,w,d,"open");o+=v,h.push(v);f=t,_=((C=n[a+1]).getBoundingClientRect().x-s.getBoundingClientRect().x)*u+r,w=(C.getBoundingClientRect().y-s.getBoundingClientRect().y)*p+r,m=(f.getBoundingClientRect().x-s.getBoundingClientRect().x)*u+r,g=(f.getBoundingClientRect().y-s.getBoundingClientRect().y)*p+r,v=l(m,g,_,w,c,"other");o+=v,h.push(v)}else if(a===n.length-1){var L,E;f=t,y=t.parentElement.classList[1].replace("node_in_",""),C=(L=i.querySelector("#"+y)).querySelectorAll("."+t.parentElement.classList[4])[0],_=(E=L.querySelectorAll("."+t.parentElement.classList[4])[0]).offsetWidth/2+(E.getBoundingClientRect().x-s.getBoundingClientRect().x)*u,w=E.offsetHeight/2+(E.getBoundingClientRect().y-s.getBoundingClientRect().y)*p,m=(f.getBoundingClientRect().x-s.getBoundingClientRect().x)*u+r,g=(f.getBoundingClientRect().y-s.getBoundingClientRect().y)*p+r,v=l(m,g,_,w,d,"close");o+=v,h.push(v)}else{f=t,_=((C=n[a+1]).getBoundingClientRect().x-s.getBoundingClientRect().x)*u+r,w=(C.getBoundingClientRect().y-s.getBoundingClientRect().y)*p+r,m=(f.getBoundingClientRect().x-s.getBoundingClientRect().x)*u+r,g=(f.getBoundingClientRect().y-s.getBoundingClientRect().y)*p+r,v=l(m,g,_,w,c,"other");o+=v,h.push(v)}}),a?h.forEach((e,n)=>{m[t].children[n].setAttributeNS(null,"d",e)}):m[t].children[0].setAttributeNS(null,"d",o)}}))}dblclick(e){null!=this.connection_selected&&this.reroute&&this.createReroutePoint(this.connection_selected),"point"===e.target.classList[0]&&this.removeReroutePoint(e.target)}createReroutePoint(e){this.connection_selected.classList.remove("selected");const t=this.connection_selected.parentElement.classList[2].slice(9),n=this.connection_selected.parentElement.classList[1].slice(13),i=this.connection_selected.parentElement.classList[3],s=this.connection_selected.parentElement.classList[4];this.connection_selected=null;const o=document.createElementNS("http://www.w3.org/2000/svg","circle");o.classList.add("point");var l=this.pos_x*(this.precanvas.clientWidth/(this.precanvas.clientWidth*this.zoom))-this.precanvas.getBoundingClientRect().x*(this.precanvas.clientWidth/(this.precanvas.clientWidth*this.zoom)),c=this.pos_y*(this.precanvas.clientHeight/(this.precanvas.clientHeight*this.zoom))-this.precanvas.getBoundingClientRect().y*(this.precanvas.clientHeight/(this.precanvas.clientHeight*this.zoom));o.setAttributeNS(null,"cx",l),o.setAttributeNS(null,"cy",c),o.setAttributeNS(null,"r",this.reroute_width);let d=0;if(this.reroute_fix_curvature){const t=e.parentElement.querySelectorAll(".main-path").length;var a=document.createElementNS("http://www.w3.org/2000/svg","path");if(a.classList.add("main-path"),a.setAttributeNS(null,"d",""),e.parentElement.insertBefore(a,e.parentElement.children[t]),1===t)e.parentElement.appendChild(o);else{const n=Array.from(e.parentElement.children).indexOf(e);d=n,e.parentElement.insertBefore(o,e.parentElement.children[n+t+1])}}else e.parentElement.appendChild(o);const r=t.slice(5),h=this.drawflow.drawflow[this.module].data[r].outputs[i].connections.findIndex((function(e,t){return e.node===n&&e.output===s}));void 0===this.drawflow.drawflow[this.module].data[r].outputs[i].connections[h].points&&(this.drawflow.drawflow[this.module].data[r].outputs[i].connections[h].points=[]),this.reroute_fix_curvature?(d>0||this.drawflow.drawflow[this.module].data[r].outputs[i].connections[h].points!==[]?this.drawflow.drawflow[this.module].data[r].outputs[i].connections[h].points.splice(d,0,{pos_x:l,pos_y:c}):this.drawflow.drawflow[this.module].data[r].outputs[i].connections[h].points.push({pos_x:l,pos_y:c}),e.parentElement.querySelectorAll(".main-path").forEach((e,t)=>{e.classList.remove("selected")})):this.drawflow.drawflow[this.module].data[r].outputs[i].connections[h].points.push({pos_x:l,pos_y:c}),this.dispatch("addReroute",r),this.updateConnectionNodes(t)}removeReroutePoint(e){const t=e.parentElement.classList[2].slice(9),n=e.parentElement.classList[1].slice(13),i=e.parentElement.classList[3],s=e.parentElement.classList[4];let o=Array.from(e.parentElement.children).indexOf(e);const l=t.slice(5),c=this.drawflow.drawflow[this.module].data[l].outputs[i].connections.findIndex((function(e,t){return e.node===n&&e.output===s}));if(this.reroute_fix_curvature){const t=e.parentElement.querySelectorAll(".main-path").length;e.parentElement.children[t-1].remove(),o-=t,o<0&&(o=0)}else o--;this.drawflow.drawflow[this.module].data[l].outputs[i].connections[c].points.splice(o,1),e.remove(),this.dispatch("removeReroute",l),this.updateConnectionNodes(t)}registerNode(e,t,n=null,i=null){this.noderegister[e]={html:t,props:n,options:i}}getNodeFromId(e){var t=this.getModuleFromNodeId(e);return JSON.parse(JSON.stringify(this.drawflow.drawflow[t].data[e]))}getNodesFromName(e){var t=[];const n=this.drawflow.drawflow;return Object.keys(n).map((function(i,s){for(var o in n[i].data)n[i].data[o].name==e&&t.push(n[i].data[o].id)})),t}addNode(e,t,n,i,s,o,l,c,d=!1){if(this.useuuid)var a=this.getUuid();else a=this.nodeId;const r=document.createElement("div");r.classList.add("parent-node");const h=document.createElement("div");h.innerHTML="",h.setAttribute("id","node-"+a),h.classList.add("drawflow-node"),""!=o&&h.classList.add(...o.split(" "));const u=document.createElement("div");u.classList.add("inputs");const p=document.createElement("div");p.classList.add("outputs");const f={};for(var m=0;me(this.noderegister[c].html,{props:this.noderegister[c].props}),...this.noderegister[c].options}).$mount();_.appendChild(e.$el)}Object.entries(l).forEach((function(e,t){if("object"==typeof e[1])!function e(t,n,i){if(null===t)t=l[n];else t=t[n];null!==t&&Object.entries(t).forEach((function(n,s){if("object"==typeof n[1])e(t,n[0],i+"-"+n[0]);else for(var o=_.querySelectorAll("[df-"+i+"-"+n[0]+"]"),l=0;lt(this.noderegister[e.html].html,{props:this.noderegister[e.html].props}),...this.noderegister[e.html].options}).$mount();c.appendChild(t.$el)}Object.entries(e.data).forEach((function(t,n){if("object"==typeof t[1])!function t(n,i,s){if(null===n)n=e.data[i];else n=n[i];null!==n&&Object.entries(n).forEach((function(e,i){if("object"==typeof e[1])t(n,e[0],s+"-"+e[0]);else for(var o=c.querySelectorAll("[df-"+s+"-"+e[0]+"]"),l=0;l{const a=e.outputs[s].connections[o].node,r=e.outputs[s].connections[o].output,h=i.querySelector(".connection.node_in_node-"+a+".node_out_node-"+e.id+"."+s+"."+r);if(n&&0===d)for(var u=0;u{this.removeSingleConnection(e.id_output,e.id,e.output_class,e.input_class)}),delete this.drawflow.drawflow[n].data[e].inputs[t];const o=[],l=this.drawflow.drawflow[n].data[e].inputs;Object.keys(l).map((function(e,t){o.push(l[e])})),this.drawflow.drawflow[n].data[e].inputs={};const c=t.slice(6);let d=[];if(o.forEach((t,i)=>{t.connections.forEach((e,t)=>{d.push(e)}),this.drawflow.drawflow[n].data[e].inputs["input_"+(i+1)]=t}),d=new Set(d.map(e=>JSON.stringify(e))),d=Array.from(d).map(e=>JSON.parse(e)),this.module===n){this.container.querySelectorAll("#node-"+e+" .inputs .input").forEach((e,t)=>{const n=e.classList[1].slice(6);parseInt(c){this.drawflow.drawflow[n].data[t.node].outputs[t.input].connections.forEach((i,s)=>{if(i.node==e){const o=i.output.slice(6);if(parseInt(c){this.removeSingleConnection(e.id,e.id_input,e.output_class,e.input_class)}),delete this.drawflow.drawflow[n].data[e].outputs[t];const o=[],l=this.drawflow.drawflow[n].data[e].outputs;Object.keys(l).map((function(e,t){o.push(l[e])})),this.drawflow.drawflow[n].data[e].outputs={};const c=t.slice(7);let d=[];if(o.forEach((t,i)=>{t.connections.forEach((e,t)=>{d.push({node:e.node,output:e.output})}),this.drawflow.drawflow[n].data[e].outputs["output_"+(i+1)]=t}),d=new Set(d.map(e=>JSON.stringify(e))),d=Array.from(d).map(e=>JSON.parse(e)),this.module===n){this.container.querySelectorAll("#node-"+e+" .outputs .output").forEach((e,t)=>{const n=e.classList[1].slice(7);parseInt(c){this.drawflow.drawflow[n].data[t.node].inputs[t.output].connections.forEach((i,s)=>{if(i.node==e){const o=i.input.slice(7);if(parseInt(c)-1){this.module===s&&this.container.querySelector(".connection.node_in_node-"+t+".node_out_node-"+e+"."+n+"."+i).remove();var o=this.drawflow.drawflow[s].data[e].outputs[n].connections.findIndex((function(e,n){return e.node==t&&e.output===i}));this.drawflow.drawflow[s].data[e].outputs[n].connections.splice(o,1);var l=this.drawflow.drawflow[s].data[t].inputs[i].connections.findIndex((function(t,i){return t.node==e&&t.input===n}));return this.drawflow.drawflow[s].data[t].inputs[i].connections.splice(l,1),this.dispatch("connectionRemoved",{output_id:e,input_id:t,output_class:n,input_class:i}),!0}return!1}return!1}removeConnectionNodeId(e){const t="node_in_"+e,n="node_out_"+e,i=this.container.querySelectorAll("."+n);for(var s=i.length-1;s>=0;s--){var o=i[s].classList,l=this.drawflow.drawflow[this.module].data[o[1].slice(13)].inputs[o[4]].connections.findIndex((function(e,t){return e.node===o[2].slice(14)&&e.input===o[3]}));this.drawflow.drawflow[this.module].data[o[1].slice(13)].inputs[o[4]].connections.splice(l,1);var c=this.drawflow.drawflow[this.module].data[o[2].slice(14)].outputs[o[3]].connections.findIndex((function(e,t){return e.node===o[1].slice(13)&&e.output===o[4]}));this.drawflow.drawflow[this.module].data[o[2].slice(14)].outputs[o[3]].connections.splice(c,1),i[s].remove(),this.dispatch("connectionRemoved",{output_id:o[2].slice(14),input_id:o[1].slice(13),output_class:o[3],input_class:o[4]})}const d=this.container.querySelectorAll("."+t);for(s=d.length-1;s>=0;s--){o=d[s].classList,c=this.drawflow.drawflow[this.module].data[o[2].slice(14)].outputs[o[3]].connections.findIndex((function(e,t){return e.node===o[1].slice(13)&&e.output===o[4]}));this.drawflow.drawflow[this.module].data[o[2].slice(14)].outputs[o[3]].connections.splice(c,1);l=this.drawflow.drawflow[this.module].data[o[1].slice(13)].inputs[o[4]].connections.findIndex((function(e,t){return e.node===o[2].slice(14)&&e.input===o[3]}));this.drawflow.drawflow[this.module].data[o[1].slice(13)].inputs[o[4]].connections.splice(l,1),d[s].remove(),this.dispatch("connectionRemoved",{output_id:o[2].slice(14),input_id:o[1].slice(13),output_class:o[3],input_class:o[4]})}}getModuleFromNodeId(e){var t;const n=this.drawflow.drawflow;return Object.keys(n).map((function(i,s){Object.keys(n[i].data).map((function(n,s){n==e&&(t=i)}))})),t}addModule(e){this.drawflow.drawflow[e]={data:{}},this.dispatch("moduleCreated",e)}changeModule(e){this.dispatch("moduleChanged",e),this.module=e,this.precanvas.innerHTML="",this.canvas_x=0,this.canvas_y=0,this.pos_x=0,this.pos_y=0,this.mouse_x=0,this.mouse_y=0,this.zoom=1,this.zoom_last_value=1,this.precanvas.style.transform="",this.import(this.drawflow,!1)}removeModule(e){this.module===e&&this.changeModule("Home"),delete this.drawflow.drawflow[e],this.dispatch("moduleRemoved",e)}clearModuleSelected(){this.precanvas.innerHTML="",this.drawflow.drawflow[this.module]={data:{}}}clear(){this.precanvas.innerHTML="",this.drawflow={drawflow:{Home:{data:{}}}}}export(){const e=JSON.parse(JSON.stringify(this.drawflow));return this.dispatch("export",e),e}import(e,t=!0){this.clear(),this.drawflow=JSON.parse(JSON.stringify(e)),this.load(),t&&this.dispatch("import","import")}on(e,t){return"function"!=typeof t?(console.error("The listener callback must be a function, the given type is "+typeof t),!1):"string"!=typeof e?(console.error("The event name must be a string, the given type is "+typeof e),!1):(void 0===this.events[e]&&(this.events[e]={listeners:[]}),void this.events[e].listeners.push(t))}removeListener(e,t){if(!this.events[e])return!1;const n=this.events[e].listeners,i=n.indexOf(t);i>-1&&n.splice(i,1)}dispatch(e,t){if(void 0===this.events[e])return!1;this.events[e].listeners.forEach(e=>{e(t)})}getUuid(){for(var e=[],t=0;t<36;t++)e[t]="0123456789abcdef".substr(Math.floor(16*Math.random()),1);return e[14]="4",e[19]="0123456789abcdef".substr(3&e[19]|8,1),e[8]=e[13]=e[18]=e[23]="-",e.join("")}}}]).default})); \ No newline at end of file diff --git a/src/main/resources/static/plugins/drawflow/drawflow.style.js b/src/main/resources/static/plugins/drawflow/drawflow.style.js new file mode 100644 index 0000000..d496844 --- /dev/null +++ b/src/main/resources/static/plugins/drawflow/drawflow.style.js @@ -0,0 +1 @@ +import {css} from "lit-element"; export const style = css`.drawflow,.drawflow .parent-node{position:relative}.parent-drawflow{display:flex;overflow:hidden;touch-action:none;outline:0}.drawflow{width:100%;height:100%;user-select:none;perspective:0}.drawflow .drawflow-node{display:flex;align-items:center;position:absolute;background:#0ff;width:160px;min-height:40px;border-radius:4px;border:2px solid #000;color:#000;z-index:2;padding:15px}.drawflow .drawflow-node.selected{background:red}.drawflow .drawflow-node:hover{cursor:move}.drawflow .drawflow-node .inputs,.drawflow .drawflow-node .outputs{width:0}.drawflow .drawflow-node .drawflow_content_node{width:100%;display:block}.drawflow .drawflow-node .input,.drawflow .drawflow-node .output{position:relative;width:20px;height:20px;background:#fff;border-radius:50%;border:2px solid #000;cursor:crosshair;z-index:1;margin-bottom:5px}.drawflow .drawflow-node .input{left:-27px;top:2px;background:#ff0}.drawflow .drawflow-node .output{right:-3px;top:2px}.drawflow svg{z-index:0;position:absolute;overflow:visible!important}.drawflow .connection{position:absolute;pointer-events:none;aspect-ratio:1/1}.drawflow .connection .main-path{fill:none;stroke-width:5px;stroke:#4682b4;pointer-events:all}.drawflow .connection .main-path:hover{stroke:#1266ab;cursor:pointer}.drawflow .connection .main-path.selected{stroke:#43b993}.drawflow .connection .point{cursor:move;stroke:#000;stroke-width:2;fill:#fff;pointer-events:all}.drawflow .connection .point.selected,.drawflow .connection .point:hover{fill:#1266ab}.drawflow .main-path{fill:none;stroke-width:5px;stroke:#4682b4}.drawflow-delete{position:absolute;display:block;width:30px;height:30px;background:#000;color:#fff;z-index:4;border:2px solid #fff;line-height:30px;font-weight:700;text-align:center;border-radius:50%;font-family:monospace;cursor:pointer}.drawflow>.drawflow-delete{margin-left:-15px;margin-top:15px}.parent-node .drawflow-delete{right:-15px;top:-15px}`; \ No newline at end of file diff --git a/src/main/resources/static/plugins/jquery-ui/images/ui-icons_444444_256x240.png b/src/main/resources/static/plugins/jquery-ui/images/ui-icons_444444_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..56d546beb39061e9a9f21d61e63fde3d5bcd6267 GIT binary patch literal 7142 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%0AZGyUy!((0He7MIsZEYx3qKKf|mxuLH!WY!>T3 z=aG0(jC%)r{zuw9b^tcB)!Zd;RsxvaeUJ;cFnLwRcXme_8iNSc{`O2ee?H~zPn`}W z#ay5c-_m7{M|W0q)7D)fM{pn4PQ|J%20sKGA5{tJqn8|DCua(cPABEkg0v#$@;X0p zyisZoe)(i|Y8|>Q*CqiDc^`eeyvH}-!Uq`pg|98Hx5~L)zj%y6A#sk0L_k_{ z?X5L#$!)$I>4KKL%vUSVe#9k{{*lN8A5IWJpZG?-_6s>&)?3|`+q4B7nT;1 z{3oW^2hwqiq5lWQ(979B$j;XZc;x71?*vo#v~zJXaI$j@@%irbk7gU7uA-w{rf3`a F{{Wt|fMoyx literal 0 HcmV?d00001 diff --git a/src/main/resources/static/plugins/jquery-ui/images/ui-icons_777620_256x240.png b/src/main/resources/static/plugins/jquery-ui/images/ui-icons_777620_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..b0482f86955307acc964be916150cbd973428c8f GIT binary patch literal 4670 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/static/plugins/jquery-ui/images/ui-icons_cc0000_256x240.png b/src/main/resources/static/plugins/jquery-ui/images/ui-icons_cc0000_256x240.png new file mode 100644 index 0000000000000000000000000000000000000000..1f96135a16f41c9eda7474c9e177c353ac2fe6fe GIT binary patch literal 4670 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 l1;|@Enp?4{+nd=~=~ + + + + jQuery UI Example Page + + + + + +

    Welcome to jQuery UI!

    + +
    +

    This page demonstrates the widgets and theme you selected in Download Builder. Please make sure you are using them with a compatible jQuery version.

    +
    + +

    YOUR COMPONENTS:

    + + +

    Accordion

    +
    +

    First

    +
    Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet.
    +

    Second

    +
    Phasellus mattis tincidunt nibh.
    +

    Third

    +
    Nam dui erat, auctor a, dignissim quis.
    +
    + + +

    Autocomplete

    +
    + +
    + + +

    Button

    + + + + +

    Checkboxradio

    +
    +
    + + + +
    +
    + + +

    Controlgroup

    +
    + Rental Car +
    + + + + + + + + + + +
    +
    + + +

    Tabs

    +
    + +
    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
    +
    Phasellus mattis tincidunt nibh. Cras orci urna, blandit id, pretium vel, aliquet ornare, felis. Maecenas scelerisque sem non nisl. Fusce sed lorem in enim dictum bibendum.
    +
    Nam dui erat, auctor a, dignissim quis, sollicitudin eu, felis. Pellentesque nisi urna, interdum eget, sagittis et, consequat vestibulum, lacus. Mauris porttitor ullamcorper augue.
    +
    + +

    Dialog

    +

    + +

    + +

    Overlay and Shadow Classes

    +
    +

    Lorem ipsum dolor sit amet, Nulla nec tortor. Donec id elit quis purus consectetur consequat.

    Nam congue semper tellus. Sed erat dolor, dapibus sit amet, venenatis ornare, ultrices ut, nisi. Aliquam ante. Suspendisse scelerisque dui nec velit. Duis augue augue, gravida euismod, vulputate ac, facilisis id, sem. Morbi in orci.

    Nulla purus lacus, pulvinar vel, malesuada ac, mattis nec, quam. Nam molestie scelerisque quam. Nullam feugiat cursus lacus.orem ipsum dolor sit amet, consectetur adipiscing elit. Donec libero risus, commodo vitae, pharetra mollis, posuere eu, pede. Nulla nec tortor. Donec id elit quis purus consectetur consequat.

    Nam congue semper tellus. Sed erat dolor, dapibus sit amet, venenatis ornare, ultrices ut, nisi. Aliquam ante. Suspendisse scelerisque dui nec velit. Duis augue augue, gravida euismod, vulputate ac, facilisis id, sem. Morbi in orci. Nulla purus lacus, pulvinar vel, malesuada ac, mattis nec, quam. Nam molestie scelerisque quam.

    Nullam feugiat cursus lacus.orem ipsum dolor sit amet, consectetur adipiscing elit. Donec libero risus, commodo vitae, pharetra mollis, posuere eu, pede. Nulla nec tortor. Donec id elit quis purus consectetur consequat. Nam congue semper tellus. Sed erat dolor, dapibus sit amet, venenatis ornare, ultrices ut, nisi. Aliquam ante.

    Suspendisse scelerisque dui nec velit. Duis augue augue, gravida euismod, vulputate ac, facilisis id, sem. Morbi in orci. Nulla purus lacus, pulvinar vel, malesuada ac, mattis nec, quam. Nam molestie scelerisque quam. Nullam feugiat cursus lacus.orem ipsum dolor sit amet, consectetur adipiscing elit. Donec libero risus, commodo vitae, pharetra mollis, posuere eu, pede. Nulla nec tortor. Donec id elit quis purus consectetur consequat. Nam congue semper tellus. Sed erat dolor, dapibus sit amet, venenatis ornare, ultrices ut, nisi.

    + + +
    +
    + Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. +
    + +
    + + +
    +

    Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

    +
    + + +

    Framework Icons (content color preview)

    +
      +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    • +
    + + +

    Slider

    +
    + + +

    Datepicker

    +
    + + +

    Progressbar

    +
    + + +

    Selectmenu

    + + + +

    Spinner

    + + + +

    Menu

    + + + +

    Tooltip

    +

    + Tooltips can be attached to any element. When you hover +the element with your mouse, the title attribute is displayed in a little box next to the element, just like a native tooltip. +

    + + +

    Highlight / Error

    +
    +
    +

    + Hey! Sample ui-state-highlight style.

    +
    +
    +
    +
    +
    +

    + Alert: Sample ui-state-error style.

    +
    +
    + + + + + + diff --git a/src/main/resources/static/plugins/jquery-ui/jquery-ui.css b/src/main/resources/static/plugins/jquery-ui/jquery-ui.css new file mode 100644 index 0000000..d394bd2 --- /dev/null +++ b/src/main/resources/static/plugins/jquery-ui/jquery-ui.css @@ -0,0 +1,1315 @@ +/*! jQuery UI - v1.13.2 - 2022-07-14 +* http://jqueryui.com +* Includes: core.css, accordion.css, autocomplete.css, menu.css, button.css, controlgroup.css, checkboxradio.css, datepicker.css, dialog.css, draggable.css, resizable.css, progressbar.css, selectable.css, selectmenu.css, slider.css, sortable.css, spinner.css, tabs.css, tooltip.css, theme.css +* To view and modify this theme, visit http://jqueryui.com/themeroller/?bgShadowXPos=&bgOverlayXPos=&bgErrorXPos=&bgHighlightXPos=&bgContentXPos=&bgHeaderXPos=&bgActiveXPos=&bgHoverXPos=&bgDefaultXPos=&bgShadowYPos=&bgOverlayYPos=&bgErrorYPos=&bgHighlightYPos=&bgContentYPos=&bgHeaderYPos=&bgActiveYPos=&bgHoverYPos=&bgDefaultYPos=&bgShadowRepeat=&bgOverlayRepeat=&bgErrorRepeat=&bgHighlightRepeat=&bgContentRepeat=&bgHeaderRepeat=&bgActiveRepeat=&bgHoverRepeat=&bgDefaultRepeat=&iconsHover=url(%22images%2Fui-icons_555555_256x240.png%22)&iconsHighlight=url(%22images%2Fui-icons_777620_256x240.png%22)&iconsHeader=url(%22images%2Fui-icons_444444_256x240.png%22)&iconsError=url(%22images%2Fui-icons_cc0000_256x240.png%22)&iconsDefault=url(%22images%2Fui-icons_777777_256x240.png%22)&iconsContent=url(%22images%2Fui-icons_444444_256x240.png%22)&iconsActive=url(%22images%2Fui-icons_ffffff_256x240.png%22)&bgImgUrlShadow=&bgImgUrlOverlay=&bgImgUrlHover=&bgImgUrlHighlight=&bgImgUrlHeader=&bgImgUrlError=&bgImgUrlDefault=&bgImgUrlContent=&bgImgUrlActive=&opacityFilterShadow=Alpha(Opacity%3D30)&opacityFilterOverlay=Alpha(Opacity%3D30)&opacityShadowPerc=30&opacityOverlayPerc=30&iconColorHover=%23555555&iconColorHighlight=%23777620&iconColorHeader=%23444444&iconColorError=%23cc0000&iconColorDefault=%23777777&iconColorContent=%23444444&iconColorActive=%23ffffff&bgImgOpacityShadow=0&bgImgOpacityOverlay=0&bgImgOpacityError=95&bgImgOpacityHighlight=55&bgImgOpacityContent=75&bgImgOpacityHeader=75&bgImgOpacityActive=65&bgImgOpacityHover=75&bgImgOpacityDefault=75&bgTextureShadow=flat&bgTextureOverlay=flat&bgTextureError=flat&bgTextureHighlight=flat&bgTextureContent=flat&bgTextureHeader=flat&bgTextureActive=flat&bgTextureHover=flat&bgTextureDefault=flat&cornerRadius=3px&fwDefault=normal&ffDefault=Arial%2CHelvetica%2Csans-serif&fsDefault=1em&cornerRadiusShadow=8px&thicknessShadow=5px&offsetLeftShadow=0px&offsetTopShadow=0px&opacityShadow=.3&bgColorShadow=%23666666&opacityOverlay=.3&bgColorOverlay=%23aaaaaa&fcError=%235f3f3f&borderColorError=%23f1a899&bgColorError=%23fddfdf&fcHighlight=%23777620&borderColorHighlight=%23dad55e&bgColorHighlight=%23fffa90&fcContent=%23333333&borderColorContent=%23dddddd&bgColorContent=%23ffffff&fcHeader=%23333333&borderColorHeader=%23dddddd&bgColorHeader=%23e9e9e9&fcActive=%23ffffff&borderColorActive=%23003eff&bgColorActive=%23007fff&fcHover=%232b2b2b&borderColorHover=%23cccccc&bgColorHover=%23ededed&fcDefault=%23454545&borderColorDefault=%23c5c5c5&bgColorDefault=%23f6f6f6 +* Copyright jQuery Foundation and other contributors; Licensed MIT */ + +/* Layout helpers +----------------------------------*/ +.ui-helper-hidden { + display: none; +} +.ui-helper-hidden-accessible { + border: 0; + clip: rect(0 0 0 0); + height: 1px; + margin: -1px; + overflow: hidden; + padding: 0; + position: absolute; + width: 1px; +} +.ui-helper-reset { + margin: 0; + padding: 0; + border: 0; + outline: 0; + line-height: 1.3; + text-decoration: none; + font-size: 100%; + list-style: none; +} +.ui-helper-clearfix:before, +.ui-helper-clearfix:after { + content: ""; + display: table; + border-collapse: collapse; +} +.ui-helper-clearfix:after { + clear: both; +} +.ui-helper-zfix { + width: 100%; + height: 100%; + top: 0; + left: 0; + position: absolute; + opacity: 0; + -ms-filter: "alpha(opacity=0)"; /* support: IE8 */ +} + +.ui-front { + z-index: 100; +} + + +/* Interaction Cues +----------------------------------*/ +.ui-state-disabled { + cursor: default !important; + pointer-events: none; +} + + +/* Icons +----------------------------------*/ +.ui-icon { + display: inline-block; + vertical-align: middle; + margin-top: -.25em; + position: relative; + text-indent: -99999px; + overflow: hidden; + background-repeat: no-repeat; +} + +.ui-widget-icon-block { + left: 50%; + margin-left: -8px; + display: block; +} + +/* Misc visuals +----------------------------------*/ + +/* Overlays */ +.ui-widget-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; +} +.ui-accordion .ui-accordion-header { + display: block; + cursor: pointer; + position: relative; + margin: 2px 0 0 0; + padding: .5em .5em .5em .7em; + font-size: 100%; +} +.ui-accordion .ui-accordion-content { + padding: 1em 2.2em; + border-top: 0; + overflow: auto; +} +.ui-autocomplete { + position: absolute; + top: 0; + left: 0; + cursor: default; +} +.ui-menu { + list-style: none; + padding: 0; + margin: 0; + display: block; + outline: 0; +} +.ui-menu .ui-menu { + position: absolute; +} +.ui-menu .ui-menu-item { + margin: 0; + cursor: pointer; + /* support: IE10, see #8844 */ + list-style-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"); +} +.ui-menu .ui-menu-item-wrapper { + position: relative; + padding: 3px 1em 3px .4em; +} +.ui-menu .ui-menu-divider { + margin: 5px 0; + height: 0; + font-size: 0; + line-height: 0; + border-width: 1px 0 0 0; +} +.ui-menu .ui-state-focus, +.ui-menu .ui-state-active { + margin: -1px; +} + +/* icon support */ +.ui-menu-icons { + position: relative; +} +.ui-menu-icons .ui-menu-item-wrapper { + padding-left: 2em; +} + +/* left-aligned */ +.ui-menu .ui-icon { + position: absolute; + top: 0; + bottom: 0; + left: .2em; + margin: auto 0; +} + +/* right-aligned */ +.ui-menu .ui-menu-icon { + left: auto; + right: 0; +} +.ui-button { + padding: .4em 1em; + display: inline-block; + position: relative; + line-height: normal; + margin-right: .1em; + cursor: pointer; + vertical-align: middle; + text-align: center; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + + /* Support: IE <= 11 */ + overflow: visible; +} + +.ui-button, +.ui-button:link, +.ui-button:visited, +.ui-button:hover, +.ui-button:active { + text-decoration: none; +} + +/* to make room for the icon, a width needs to be set here */ +.ui-button-icon-only { + width: 2em; + box-sizing: border-box; + text-indent: -9999px; + white-space: nowrap; +} + +/* no icon support for input elements */ +input.ui-button.ui-button-icon-only { + text-indent: 0; +} + +/* button icon element(s) */ +.ui-button-icon-only .ui-icon { + position: absolute; + top: 50%; + left: 50%; + margin-top: -8px; + margin-left: -8px; +} + +.ui-button.ui-icon-notext .ui-icon { + padding: 0; + width: 2.1em; + height: 2.1em; + text-indent: -9999px; + white-space: nowrap; + +} + +input.ui-button.ui-icon-notext .ui-icon { + width: auto; + height: auto; + text-indent: 0; + white-space: normal; + padding: .4em 1em; +} + +/* workarounds */ +/* Support: Firefox 5 - 40 */ +input.ui-button::-moz-focus-inner, +button.ui-button::-moz-focus-inner { + border: 0; + padding: 0; +} +.ui-controlgroup { + vertical-align: middle; + display: inline-block; +} +.ui-controlgroup > .ui-controlgroup-item { + float: left; + margin-left: 0; + margin-right: 0; +} +.ui-controlgroup > .ui-controlgroup-item:focus, +.ui-controlgroup > .ui-controlgroup-item.ui-visual-focus { + z-index: 9999; +} +.ui-controlgroup-vertical > .ui-controlgroup-item { + display: block; + float: none; + width: 100%; + margin-top: 0; + margin-bottom: 0; + text-align: left; +} +.ui-controlgroup-vertical .ui-controlgroup-item { + box-sizing: border-box; +} +.ui-controlgroup .ui-controlgroup-label { + padding: .4em 1em; +} +.ui-controlgroup .ui-controlgroup-label span { + font-size: 80%; +} +.ui-controlgroup-horizontal .ui-controlgroup-label + .ui-controlgroup-item { + border-left: none; +} +.ui-controlgroup-vertical .ui-controlgroup-label + .ui-controlgroup-item { + border-top: none; +} +.ui-controlgroup-horizontal .ui-controlgroup-label.ui-widget-content { + border-right: none; +} +.ui-controlgroup-vertical .ui-controlgroup-label.ui-widget-content { + border-bottom: none; +} + +/* Spinner specific style fixes */ +.ui-controlgroup-vertical .ui-spinner-input { + + /* Support: IE8 only, Android < 4.4 only */ + width: 75%; + width: calc( 100% - 2.4em ); +} +.ui-controlgroup-vertical .ui-spinner .ui-spinner-up { + border-top-style: solid; +} + +.ui-checkboxradio-label .ui-icon-background { + box-shadow: inset 1px 1px 1px #ccc; + border-radius: .12em; + border: none; +} +.ui-checkboxradio-radio-label .ui-icon-background { + width: 16px; + height: 16px; + border-radius: 1em; + overflow: visible; + border: none; +} +.ui-checkboxradio-radio-label.ui-checkboxradio-checked .ui-icon, +.ui-checkboxradio-radio-label.ui-checkboxradio-checked:hover .ui-icon { + background-image: none; + width: 8px; + height: 8px; + border-width: 4px; + border-style: solid; +} +.ui-checkboxradio-disabled { + pointer-events: none; +} +.ui-datepicker { + width: 17em; + padding: .2em .2em 0; + display: none; +} +.ui-datepicker .ui-datepicker-header { + position: relative; + padding: .2em 0; +} +.ui-datepicker .ui-datepicker-prev, +.ui-datepicker .ui-datepicker-next { + position: absolute; + top: 2px; + width: 1.8em; + height: 1.8em; +} +.ui-datepicker .ui-datepicker-prev-hover, +.ui-datepicker .ui-datepicker-next-hover { + top: 1px; +} +.ui-datepicker .ui-datepicker-prev { + left: 2px; +} +.ui-datepicker .ui-datepicker-next { + right: 2px; +} +.ui-datepicker .ui-datepicker-prev-hover { + left: 1px; +} +.ui-datepicker .ui-datepicker-next-hover { + right: 1px; +} +.ui-datepicker .ui-datepicker-prev span, +.ui-datepicker .ui-datepicker-next span { + display: block; + position: absolute; + left: 50%; + margin-left: -8px; + top: 50%; + margin-top: -8px; +} +.ui-datepicker .ui-datepicker-title { + margin: 0 2.3em; + line-height: 1.8em; + text-align: center; +} +.ui-datepicker .ui-datepicker-title select { + font-size: 1em; + margin: 1px 0; +} +.ui-datepicker select.ui-datepicker-month, +.ui-datepicker select.ui-datepicker-year { + width: 45%; +} +.ui-datepicker table { + width: 100%; + font-size: .9em; + border-collapse: collapse; + margin: 0 0 .4em; +} +.ui-datepicker th { + padding: .7em .3em; + text-align: center; + font-weight: bold; + border: 0; +} +.ui-datepicker td { + border: 0; + padding: 1px; +} +.ui-datepicker td span, +.ui-datepicker td a { + display: block; + padding: .2em; + text-align: right; + text-decoration: none; +} +.ui-datepicker .ui-datepicker-buttonpane { + background-image: none; + margin: .7em 0 0 0; + padding: 0 .2em; + border-left: 0; + border-right: 0; + border-bottom: 0; +} +.ui-datepicker .ui-datepicker-buttonpane button { + float: right; + margin: .5em .2em .4em; + cursor: pointer; + padding: .2em .6em .3em .6em; + width: auto; + overflow: visible; +} +.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { + float: left; +} + +/* with multiple calendars */ +.ui-datepicker.ui-datepicker-multi { + width: auto; +} +.ui-datepicker-multi .ui-datepicker-group { + float: left; +} +.ui-datepicker-multi .ui-datepicker-group table { + width: 95%; + margin: 0 auto .4em; +} +.ui-datepicker-multi-2 .ui-datepicker-group { + width: 50%; +} +.ui-datepicker-multi-3 .ui-datepicker-group { + width: 33.3%; +} +.ui-datepicker-multi-4 .ui-datepicker-group { + width: 25%; +} +.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header, +.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { + border-left-width: 0; +} +.ui-datepicker-multi .ui-datepicker-buttonpane { + clear: left; +} +.ui-datepicker-row-break { + clear: both; + width: 100%; + font-size: 0; +} + +/* RTL support */ +.ui-datepicker-rtl { + direction: rtl; +} +.ui-datepicker-rtl .ui-datepicker-prev { + right: 2px; + left: auto; +} +.ui-datepicker-rtl .ui-datepicker-next { + left: 2px; + right: auto; +} +.ui-datepicker-rtl .ui-datepicker-prev:hover { + right: 1px; + left: auto; +} +.ui-datepicker-rtl .ui-datepicker-next:hover { + left: 1px; + right: auto; +} +.ui-datepicker-rtl .ui-datepicker-buttonpane { + clear: right; +} +.ui-datepicker-rtl .ui-datepicker-buttonpane button { + float: left; +} +.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current, +.ui-datepicker-rtl .ui-datepicker-group { + float: right; +} +.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header, +.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { + border-right-width: 0; + border-left-width: 1px; +} + +/* Icons */ +.ui-datepicker .ui-icon { + display: block; + text-indent: -99999px; + overflow: hidden; + background-repeat: no-repeat; + left: .5em; + top: .3em; +} +.ui-dialog { + position: absolute; + top: 0; + left: 0; + padding: .2em; + outline: 0; +} +.ui-dialog .ui-dialog-titlebar { + padding: .4em 1em; + position: relative; +} +.ui-dialog .ui-dialog-title { + float: left; + margin: .1em 0; + white-space: nowrap; + width: 90%; + overflow: hidden; + text-overflow: ellipsis; +} +.ui-dialog .ui-dialog-titlebar-close { + position: absolute; + right: .3em; + top: 50%; + width: 20px; + margin: -10px 0 0 0; + padding: 1px; + height: 20px; +} +.ui-dialog .ui-dialog-content { + position: relative; + border: 0; + padding: .5em 1em; + background: none; + overflow: auto; +} +.ui-dialog .ui-dialog-buttonpane { + text-align: left; + border-width: 1px 0 0 0; + background-image: none; + margin-top: .5em; + padding: .3em 1em .5em .4em; +} +.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { + float: right; +} +.ui-dialog .ui-dialog-buttonpane button { + margin: .5em .4em .5em 0; + cursor: pointer; +} +.ui-dialog .ui-resizable-n { + height: 2px; + top: 0; +} +.ui-dialog .ui-resizable-e { + width: 2px; + right: 0; +} +.ui-dialog .ui-resizable-s { + height: 2px; + bottom: 0; +} +.ui-dialog .ui-resizable-w { + width: 2px; + left: 0; +} +.ui-dialog .ui-resizable-se, +.ui-dialog .ui-resizable-sw, +.ui-dialog .ui-resizable-ne, +.ui-dialog .ui-resizable-nw { + width: 7px; + height: 7px; +} +.ui-dialog .ui-resizable-se { + right: 0; + bottom: 0; +} +.ui-dialog .ui-resizable-sw { + left: 0; + bottom: 0; +} +.ui-dialog .ui-resizable-ne { + right: 0; + top: 0; +} +.ui-dialog .ui-resizable-nw { + left: 0; + top: 0; +} +.ui-draggable .ui-dialog-titlebar { + cursor: move; +} +.ui-draggable-handle { + -ms-touch-action: none; + touch-action: none; +} +.ui-resizable { + position: relative; +} +.ui-resizable-handle { + position: absolute; + font-size: 0.1px; + display: block; + -ms-touch-action: none; + touch-action: none; +} +.ui-resizable-disabled .ui-resizable-handle, +.ui-resizable-autohide .ui-resizable-handle { + display: none; +} +.ui-resizable-n { + cursor: n-resize; + height: 7px; + width: 100%; + top: -5px; + left: 0; +} +.ui-resizable-s { + cursor: s-resize; + height: 7px; + width: 100%; + bottom: -5px; + left: 0; +} +.ui-resizable-e { + cursor: e-resize; + width: 7px; + right: -5px; + top: 0; + height: 100%; +} +.ui-resizable-w { + cursor: w-resize; + width: 7px; + left: -5px; + top: 0; + height: 100%; +} +.ui-resizable-se { + cursor: se-resize; + width: 12px; + height: 12px; + right: 1px; + bottom: 1px; +} +.ui-resizable-sw { + cursor: sw-resize; + width: 9px; + height: 9px; + left: -5px; + bottom: -5px; +} +.ui-resizable-nw { + cursor: nw-resize; + width: 9px; + height: 9px; + left: -5px; + top: -5px; +} +.ui-resizable-ne { + cursor: ne-resize; + width: 9px; + height: 9px; + right: -5px; + top: -5px; +} +.ui-progressbar { + height: 2em; + text-align: left; + overflow: hidden; +} +.ui-progressbar .ui-progressbar-value { + margin: -1px; + height: 100%; +} +.ui-progressbar .ui-progressbar-overlay { + background: url("data:image/gif;base64,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"); + height: 100%; + -ms-filter: "alpha(opacity=25)"; /* support: IE8 */ + opacity: 0.25; +} +.ui-progressbar-indeterminate .ui-progressbar-value { + background-image: none; +} +.ui-selectable { + -ms-touch-action: none; + touch-action: none; +} +.ui-selectable-helper { + position: absolute; + z-index: 100; + border: 1px dotted black; +} +.ui-selectmenu-menu { + padding: 0; + margin: 0; + position: absolute; + top: 0; + left: 0; + display: none; +} +.ui-selectmenu-menu .ui-menu { + overflow: auto; + overflow-x: hidden; + padding-bottom: 1px; +} +.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup { + font-size: 1em; + font-weight: bold; + line-height: 1.5; + padding: 2px 0.4em; + margin: 0.5em 0 0 0; + height: auto; + border: 0; +} +.ui-selectmenu-open { + display: block; +} +.ui-selectmenu-text { + display: block; + margin-right: 20px; + overflow: hidden; + text-overflow: ellipsis; +} +.ui-selectmenu-button.ui-button { + text-align: left; + white-space: nowrap; + width: 14em; +} +.ui-selectmenu-icon.ui-icon { + float: right; + margin-top: 0; +} +.ui-slider { + position: relative; + text-align: left; +} +.ui-slider .ui-slider-handle { + position: absolute; + z-index: 2; + width: 1.2em; + height: 1.2em; + cursor: pointer; + -ms-touch-action: none; + touch-action: none; +} +.ui-slider .ui-slider-range { + position: absolute; + z-index: 1; + font-size: .7em; + display: block; + border: 0; + background-position: 0 0; +} + +/* support: IE8 - See #6727 */ +.ui-slider.ui-state-disabled .ui-slider-handle, +.ui-slider.ui-state-disabled .ui-slider-range { + filter: inherit; +} + +.ui-slider-horizontal { + height: .8em; +} +.ui-slider-horizontal .ui-slider-handle { + top: -.3em; + margin-left: -.6em; +} +.ui-slider-horizontal .ui-slider-range { + top: 0; + height: 100%; +} +.ui-slider-horizontal .ui-slider-range-min { + left: 0; +} +.ui-slider-horizontal .ui-slider-range-max { + right: 0; +} + +.ui-slider-vertical { + width: .8em; + height: 100px; +} +.ui-slider-vertical .ui-slider-handle { + left: -.3em; + margin-left: 0; + margin-bottom: -.6em; +} +.ui-slider-vertical .ui-slider-range { + left: 0; + width: 100%; +} +.ui-slider-vertical .ui-slider-range-min { + bottom: 0; +} +.ui-slider-vertical .ui-slider-range-max { + top: 0; +} +.ui-sortable-handle { + -ms-touch-action: none; + touch-action: none; +} +.ui-spinner { + position: relative; + display: inline-block; + overflow: hidden; + padding: 0; + vertical-align: middle; +} +.ui-spinner-input { + border: none; + background: none; + color: inherit; + padding: .222em 0; + margin: .2em 0; + vertical-align: middle; + margin-left: .4em; + margin-right: 2em; +} +.ui-spinner-button { + width: 1.6em; + height: 50%; + font-size: .5em; + padding: 0; + margin: 0; + text-align: center; + position: absolute; + cursor: default; + display: block; + overflow: hidden; + right: 0; +} +/* more specificity required here to override default borders */ +.ui-spinner a.ui-spinner-button { + border-top-style: none; + border-bottom-style: none; + border-right-style: none; +} +.ui-spinner-up { + top: 0; +} +.ui-spinner-down { + bottom: 0; +} +.ui-tabs { + position: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */ + padding: .2em; +} +.ui-tabs .ui-tabs-nav { + margin: 0; + padding: .2em .2em 0; +} +.ui-tabs .ui-tabs-nav li { + list-style: none; + float: left; + position: relative; + top: 0; + margin: 1px .2em 0 0; + border-bottom-width: 0; + padding: 0; + white-space: nowrap; +} +.ui-tabs .ui-tabs-nav .ui-tabs-anchor { + float: left; + padding: .5em 1em; + text-decoration: none; +} +.ui-tabs .ui-tabs-nav li.ui-tabs-active { + margin-bottom: -1px; + padding-bottom: 1px; +} +.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor, +.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor, +.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor { + cursor: text; +} +.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor { + cursor: pointer; +} +.ui-tabs .ui-tabs-panel { + display: block; + border-width: 0; + padding: 1em 1.4em; + background: none; +} +.ui-tooltip { + padding: 8px; + position: absolute; + z-index: 9999; + max-width: 300px; +} +body .ui-tooltip { + border-width: 2px; +} + +/* Component containers +----------------------------------*/ +.ui-widget { + font-family: Arial,Helvetica,sans-serif; + font-size: 1em; +} +.ui-widget .ui-widget { + font-size: 1em; +} +.ui-widget input, +.ui-widget select, +.ui-widget textarea, +.ui-widget button { + font-family: Arial,Helvetica,sans-serif; + font-size: 1em; +} +.ui-widget.ui-widget-content { + border: 1px solid #c5c5c5; +} +.ui-widget-content { + border: 1px solid #dddddd; + background: #ffffff; + color: #333333; +} +.ui-widget-content a { + color: #333333; +} +.ui-widget-header { + border: 1px solid #dddddd; + background: #e9e9e9; + color: #333333; + font-weight: bold; +} +.ui-widget-header a { + color: #333333; +} + +/* Interaction states +----------------------------------*/ +.ui-state-default, +.ui-widget-content .ui-state-default, +.ui-widget-header .ui-state-default, +.ui-button, + +/* We use html here because we need a greater specificity to make sure disabled +works properly when clicked or hovered */ +html .ui-button.ui-state-disabled:hover, +html .ui-button.ui-state-disabled:active { + border: 1px solid #c5c5c5; + background: #f6f6f6; + font-weight: normal; + color: #454545; +} +.ui-state-default a, +.ui-state-default a:link, +.ui-state-default a:visited, +a.ui-button, +a:link.ui-button, +a:visited.ui-button, +.ui-button { + color: #454545; + text-decoration: none; +} +.ui-state-hover, +.ui-widget-content .ui-state-hover, +.ui-widget-header .ui-state-hover, +.ui-state-focus, +.ui-widget-content .ui-state-focus, +.ui-widget-header .ui-state-focus, +.ui-button:hover, +.ui-button:focus { + border: 1px solid #cccccc; + background: #ededed; + font-weight: normal; + color: #2b2b2b; +} +.ui-state-hover a, +.ui-state-hover a:hover, +.ui-state-hover a:link, +.ui-state-hover a:visited, +.ui-state-focus a, +.ui-state-focus a:hover, +.ui-state-focus a:link, +.ui-state-focus a:visited, +a.ui-button:hover, +a.ui-button:focus { + color: #2b2b2b; + text-decoration: none; +} + +.ui-visual-focus { + box-shadow: 0 0 3px 1px rgb(94, 158, 214); +} +.ui-state-active, +.ui-widget-content .ui-state-active, +.ui-widget-header .ui-state-active, +a.ui-button:active, +.ui-button:active, +.ui-button.ui-state-active:hover { + border: 1px solid #003eff; + background: #007fff; + font-weight: normal; + color: #ffffff; +} +.ui-icon-background, +.ui-state-active .ui-icon-background { + border: #003eff; + background-color: #ffffff; +} +.ui-state-active a, +.ui-state-active a:link, +.ui-state-active a:visited { + color: #ffffff; + text-decoration: none; +} + +/* Interaction Cues +----------------------------------*/ +.ui-state-highlight, +.ui-widget-content .ui-state-highlight, +.ui-widget-header .ui-state-highlight { + border: 1px solid #dad55e; + background: #fffa90; + color: #777620; +} +.ui-state-checked { + border: 1px solid #dad55e; + background: #fffa90; +} +.ui-state-highlight a, +.ui-widget-content .ui-state-highlight a, +.ui-widget-header .ui-state-highlight a { + color: #777620; +} +.ui-state-error, +.ui-widget-content .ui-state-error, +.ui-widget-header .ui-state-error { + border: 1px solid #f1a899; + background: #fddfdf; + color: #5f3f3f; +} +.ui-state-error a, +.ui-widget-content .ui-state-error a, +.ui-widget-header .ui-state-error a { + color: #5f3f3f; +} +.ui-state-error-text, +.ui-widget-content .ui-state-error-text, +.ui-widget-header .ui-state-error-text { + color: #5f3f3f; +} +.ui-priority-primary, +.ui-widget-content .ui-priority-primary, +.ui-widget-header .ui-priority-primary { + font-weight: bold; +} +.ui-priority-secondary, +.ui-widget-content .ui-priority-secondary, +.ui-widget-header .ui-priority-secondary { + opacity: .7; + -ms-filter: "alpha(opacity=70)"; /* support: IE8 */ + font-weight: normal; +} +.ui-state-disabled, +.ui-widget-content .ui-state-disabled, +.ui-widget-header .ui-state-disabled { + opacity: .35; + -ms-filter: "alpha(opacity=35)"; /* support: IE8 */ + background-image: none; +} +.ui-state-disabled .ui-icon { + -ms-filter: "alpha(opacity=35)"; /* support: IE8 - See #6059 */ +} + +/* Icons +----------------------------------*/ + +/* states and images */ +.ui-icon { + width: 16px; + height: 16px; +} +.ui-icon, +.ui-widget-content .ui-icon { + background-image: url("images/ui-icons_444444_256x240.png"); +} +.ui-widget-header .ui-icon { + background-image: url("images/ui-icons_444444_256x240.png"); +} +.ui-state-hover .ui-icon, +.ui-state-focus .ui-icon, +.ui-button:hover .ui-icon, +.ui-button:focus .ui-icon { + background-image: url("images/ui-icons_555555_256x240.png"); +} +.ui-state-active .ui-icon, +.ui-button:active .ui-icon { + background-image: url("images/ui-icons_ffffff_256x240.png"); +} +.ui-state-highlight .ui-icon, +.ui-button .ui-state-highlight.ui-icon { + background-image: url("images/ui-icons_777620_256x240.png"); +} +.ui-state-error .ui-icon, +.ui-state-error-text .ui-icon { + background-image: url("images/ui-icons_cc0000_256x240.png"); +} +.ui-button .ui-icon { + background-image: url("images/ui-icons_777777_256x240.png"); +} + +/* positioning */ +/* Three classes needed to override `.ui-button:hover .ui-icon` */ +.ui-icon-blank.ui-icon-blank.ui-icon-blank { + background-image: none; +} +.ui-icon-caret-1-n { background-position: 0 0; } +.ui-icon-caret-1-ne { background-position: -16px 0; } +.ui-icon-caret-1-e { background-position: -32px 0; } +.ui-icon-caret-1-se { background-position: -48px 0; } +.ui-icon-caret-1-s { background-position: -65px 0; } +.ui-icon-caret-1-sw { background-position: -80px 0; } +.ui-icon-caret-1-w { background-position: -96px 0; } +.ui-icon-caret-1-nw { background-position: -112px 0; } +.ui-icon-caret-2-n-s { background-position: -128px 0; } +.ui-icon-caret-2-e-w { background-position: -144px 0; } +.ui-icon-triangle-1-n { background-position: 0 -16px; } +.ui-icon-triangle-1-ne { background-position: -16px -16px; } +.ui-icon-triangle-1-e { background-position: -32px -16px; } +.ui-icon-triangle-1-se { background-position: -48px -16px; } +.ui-icon-triangle-1-s { background-position: -65px -16px; } +.ui-icon-triangle-1-sw { background-position: -80px -16px; } +.ui-icon-triangle-1-w { background-position: -96px -16px; } +.ui-icon-triangle-1-nw { background-position: -112px -16px; } +.ui-icon-triangle-2-n-s { background-position: -128px -16px; } +.ui-icon-triangle-2-e-w { background-position: -144px -16px; } +.ui-icon-arrow-1-n { background-position: 0 -32px; } +.ui-icon-arrow-1-ne { background-position: -16px -32px; } +.ui-icon-arrow-1-e { background-position: -32px -32px; } +.ui-icon-arrow-1-se { background-position: -48px -32px; } +.ui-icon-arrow-1-s { background-position: -65px -32px; } +.ui-icon-arrow-1-sw { background-position: -80px -32px; } +.ui-icon-arrow-1-w { background-position: -96px -32px; } +.ui-icon-arrow-1-nw { background-position: -112px -32px; } +.ui-icon-arrow-2-n-s { background-position: -128px -32px; } +.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } +.ui-icon-arrow-2-e-w { background-position: -160px -32px; } +.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } +.ui-icon-arrowstop-1-n { background-position: -192px -32px; } +.ui-icon-arrowstop-1-e { background-position: -208px -32px; } +.ui-icon-arrowstop-1-s { background-position: -224px -32px; } +.ui-icon-arrowstop-1-w { background-position: -240px -32px; } +.ui-icon-arrowthick-1-n { background-position: 1px -48px; } +.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } +.ui-icon-arrowthick-1-e { background-position: -32px -48px; } +.ui-icon-arrowthick-1-se { background-position: -48px -48px; } +.ui-icon-arrowthick-1-s { background-position: -64px -48px; } +.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } +.ui-icon-arrowthick-1-w { background-position: -96px -48px; } +.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } +.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } +.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } +.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } +.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } +.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } +.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } +.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } +.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } +.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } +.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } +.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } +.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } +.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } +.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } +.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } +.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } +.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } +.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } +.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } +.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } +.ui-icon-arrow-4 { background-position: 0 -80px; } +.ui-icon-arrow-4-diag { background-position: -16px -80px; } +.ui-icon-extlink { background-position: -32px -80px; } +.ui-icon-newwin { background-position: -48px -80px; } +.ui-icon-refresh { background-position: -64px -80px; } +.ui-icon-shuffle { background-position: -80px -80px; } +.ui-icon-transfer-e-w { background-position: -96px -80px; } +.ui-icon-transferthick-e-w { background-position: -112px -80px; } +.ui-icon-folder-collapsed { background-position: 0 -96px; } +.ui-icon-folder-open { background-position: -16px -96px; } +.ui-icon-document { background-position: -32px -96px; } +.ui-icon-document-b { background-position: -48px -96px; } +.ui-icon-note { background-position: -64px -96px; } +.ui-icon-mail-closed { background-position: -80px -96px; } +.ui-icon-mail-open { background-position: -96px -96px; } +.ui-icon-suitcase { background-position: -112px -96px; } +.ui-icon-comment { background-position: -128px -96px; } +.ui-icon-person { background-position: -144px -96px; } +.ui-icon-print { background-position: -160px -96px; } +.ui-icon-trash { background-position: -176px -96px; } +.ui-icon-locked { background-position: -192px -96px; } +.ui-icon-unlocked { background-position: -208px -96px; } +.ui-icon-bookmark { background-position: -224px -96px; } +.ui-icon-tag { background-position: -240px -96px; } +.ui-icon-home { background-position: 0 -112px; } +.ui-icon-flag { background-position: -16px -112px; } +.ui-icon-calendar { background-position: -32px -112px; } +.ui-icon-cart { background-position: -48px -112px; } +.ui-icon-pencil { background-position: -64px -112px; } +.ui-icon-clock { background-position: -80px -112px; } +.ui-icon-disk { background-position: -96px -112px; } +.ui-icon-calculator { background-position: -112px -112px; } +.ui-icon-zoomin { background-position: -128px -112px; } +.ui-icon-zoomout { background-position: -144px -112px; } +.ui-icon-search { background-position: -160px -112px; } +.ui-icon-wrench { background-position: -176px -112px; } +.ui-icon-gear { background-position: -192px -112px; } +.ui-icon-heart { background-position: -208px -112px; } +.ui-icon-star { background-position: -224px -112px; } +.ui-icon-link { background-position: -240px -112px; } +.ui-icon-cancel { background-position: 0 -128px; } +.ui-icon-plus { background-position: -16px -128px; } +.ui-icon-plusthick { background-position: -32px -128px; } +.ui-icon-minus { background-position: -48px -128px; } +.ui-icon-minusthick { background-position: -64px -128px; } +.ui-icon-close { background-position: -80px -128px; } +.ui-icon-closethick { background-position: -96px -128px; } +.ui-icon-key { background-position: -112px -128px; } +.ui-icon-lightbulb { background-position: -128px -128px; } +.ui-icon-scissors { background-position: -144px -128px; } +.ui-icon-clipboard { background-position: -160px -128px; } +.ui-icon-copy { background-position: -176px -128px; } +.ui-icon-contact { background-position: -192px -128px; } +.ui-icon-image { background-position: -208px -128px; } +.ui-icon-video { background-position: -224px -128px; } +.ui-icon-script { background-position: -240px -128px; } +.ui-icon-alert { background-position: 0 -144px; } +.ui-icon-info { background-position: -16px -144px; } +.ui-icon-notice { background-position: -32px -144px; } +.ui-icon-help { background-position: -48px -144px; } +.ui-icon-check { background-position: -64px -144px; } +.ui-icon-bullet { background-position: -80px -144px; } +.ui-icon-radio-on { background-position: -96px -144px; } +.ui-icon-radio-off { background-position: -112px -144px; } +.ui-icon-pin-w { background-position: -128px -144px; } +.ui-icon-pin-s { background-position: -144px -144px; } +.ui-icon-play { background-position: 0 -160px; } +.ui-icon-pause { background-position: -16px -160px; } +.ui-icon-seek-next { background-position: -32px -160px; } +.ui-icon-seek-prev { background-position: -48px -160px; } +.ui-icon-seek-end { background-position: -64px -160px; } +.ui-icon-seek-start { background-position: -80px -160px; } +/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */ +.ui-icon-seek-first { background-position: -80px -160px; } +.ui-icon-stop { background-position: -96px -160px; } +.ui-icon-eject { background-position: -112px -160px; } +.ui-icon-volume-off { background-position: -128px -160px; } +.ui-icon-volume-on { background-position: -144px -160px; } +.ui-icon-power { background-position: 0 -176px; } +.ui-icon-signal-diag { background-position: -16px -176px; } +.ui-icon-signal { background-position: -32px -176px; } +.ui-icon-battery-0 { background-position: -48px -176px; } +.ui-icon-battery-1 { background-position: -64px -176px; } +.ui-icon-battery-2 { background-position: -80px -176px; } +.ui-icon-battery-3 { background-position: -96px -176px; } +.ui-icon-circle-plus { background-position: 0 -192px; } +.ui-icon-circle-minus { background-position: -16px -192px; } +.ui-icon-circle-close { background-position: -32px -192px; } +.ui-icon-circle-triangle-e { background-position: -48px -192px; } +.ui-icon-circle-triangle-s { background-position: -64px -192px; } +.ui-icon-circle-triangle-w { background-position: -80px -192px; } +.ui-icon-circle-triangle-n { background-position: -96px -192px; } +.ui-icon-circle-arrow-e { background-position: -112px -192px; } +.ui-icon-circle-arrow-s { background-position: -128px -192px; } +.ui-icon-circle-arrow-w { background-position: -144px -192px; } +.ui-icon-circle-arrow-n { background-position: -160px -192px; } +.ui-icon-circle-zoomin { background-position: -176px -192px; } +.ui-icon-circle-zoomout { background-position: -192px -192px; } +.ui-icon-circle-check { background-position: -208px -192px; } +.ui-icon-circlesmall-plus { background-position: 0 -208px; } +.ui-icon-circlesmall-minus { background-position: -16px -208px; } +.ui-icon-circlesmall-close { background-position: -32px -208px; } +.ui-icon-squaresmall-plus { background-position: -48px -208px; } +.ui-icon-squaresmall-minus { background-position: -64px -208px; } +.ui-icon-squaresmall-close { background-position: -80px -208px; } +.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } +.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } +.ui-icon-grip-solid-vertical { background-position: -32px -224px; } +.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } +.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } +.ui-icon-grip-diagonal-se { background-position: -80px -224px; } + + +/* Misc visuals +----------------------------------*/ + +/* Corner radius */ +.ui-corner-all, +.ui-corner-top, +.ui-corner-left, +.ui-corner-tl { + border-top-left-radius: 3px; +} +.ui-corner-all, +.ui-corner-top, +.ui-corner-right, +.ui-corner-tr { + border-top-right-radius: 3px; +} +.ui-corner-all, +.ui-corner-bottom, +.ui-corner-left, +.ui-corner-bl { + border-bottom-left-radius: 3px; +} +.ui-corner-all, +.ui-corner-bottom, +.ui-corner-right, +.ui-corner-br { + border-bottom-right-radius: 3px; +} + +/* Overlays */ +.ui-widget-overlay { + background: #aaaaaa; + opacity: .003; + -ms-filter: Alpha(Opacity=.3); /* support: IE8 */ +} +.ui-widget-shadow { + -webkit-box-shadow: 0px 0px 5px #666666; + box-shadow: 0px 0px 5px #666666; +} diff --git a/src/main/resources/static/plugins/jquery-ui/jquery-ui.js b/src/main/resources/static/plugins/jquery-ui/jquery-ui.js new file mode 100644 index 0000000..1a613bf --- /dev/null +++ b/src/main/resources/static/plugins/jquery-ui/jquery-ui.js @@ -0,0 +1,19062 @@ +/*! jQuery UI - v1.13.2 - 2022-07-14 +* http://jqueryui.com +* Includes: widget.js, position.js, data.js, disable-selection.js, effect.js, effects/effect-blind.js, effects/effect-bounce.js, effects/effect-clip.js, effects/effect-drop.js, effects/effect-explode.js, effects/effect-fade.js, effects/effect-fold.js, effects/effect-highlight.js, effects/effect-puff.js, effects/effect-pulsate.js, effects/effect-scale.js, effects/effect-shake.js, effects/effect-size.js, effects/effect-slide.js, effects/effect-transfer.js, focusable.js, form-reset-mixin.js, jquery-patch.js, keycode.js, labels.js, scroll-parent.js, tabbable.js, unique-id.js, widgets/accordion.js, widgets/autocomplete.js, widgets/button.js, widgets/checkboxradio.js, widgets/controlgroup.js, widgets/datepicker.js, widgets/dialog.js, widgets/draggable.js, widgets/droppable.js, widgets/menu.js, widgets/mouse.js, widgets/progressbar.js, widgets/resizable.js, widgets/selectable.js, widgets/selectmenu.js, widgets/slider.js, widgets/sortable.js, widgets/spinner.js, widgets/tabs.js, widgets/tooltip.js +* Copyright jQuery Foundation and other contributors; Licensed MIT */ + +( function( factory ) { + "use strict"; + + if ( typeof define === "function" && define.amd ) { + + // AMD. Register as an anonymous module. + define( [ "jquery" ], factory ); + } else { + + // Browser globals + factory( jQuery ); + } +} )( function( $ ) { +"use strict"; + +$.ui = $.ui || {}; + +var version = $.ui.version = "1.13.2"; + + +/*! + * jQuery UI Widget 1.13.2 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Widget +//>>group: Core +//>>description: Provides a factory for creating stateful widgets with a common API. +//>>docs: http://api.jqueryui.com/jQuery.widget/ +//>>demos: http://jqueryui.com/widget/ + + +var widgetUuid = 0; +var widgetHasOwnProperty = Array.prototype.hasOwnProperty; +var widgetSlice = Array.prototype.slice; + +$.cleanData = ( function( orig ) { + return function( elems ) { + var events, elem, i; + for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) { + + // Only trigger remove when necessary to save time + events = $._data( elem, "events" ); + if ( events && events.remove ) { + $( elem ).triggerHandler( "remove" ); + } + } + orig( elems ); + }; +} )( $.cleanData ); + +$.widget = function( name, base, prototype ) { + var existingConstructor, constructor, basePrototype; + + // ProxiedPrototype allows the provided prototype to remain unmodified + // so that it can be used as a mixin for multiple widgets (#8876) + var proxiedPrototype = {}; + + var namespace = name.split( "." )[ 0 ]; + name = name.split( "." )[ 1 ]; + var fullName = namespace + "-" + name; + + if ( !prototype ) { + prototype = base; + base = $.Widget; + } + + if ( Array.isArray( prototype ) ) { + prototype = $.extend.apply( null, [ {} ].concat( prototype ) ); + } + + // Create selector for plugin + $.expr.pseudos[ fullName.toLowerCase() ] = function( elem ) { + return !!$.data( elem, fullName ); + }; + + $[ namespace ] = $[ namespace ] || {}; + existingConstructor = $[ namespace ][ name ]; + constructor = $[ namespace ][ name ] = function( options, element ) { + + // Allow instantiation without "new" keyword + if ( !this || !this._createWidget ) { + return new constructor( options, element ); + } + + // Allow instantiation without initializing for simple inheritance + // must use "new" keyword (the code above always passes args) + if ( arguments.length ) { + this._createWidget( options, element ); + } + }; + + // Extend with the existing constructor to carry over any static properties + $.extend( constructor, existingConstructor, { + version: prototype.version, + + // Copy the object used to create the prototype in case we need to + // redefine the widget later + _proto: $.extend( {}, prototype ), + + // Track widgets that inherit from this widget in case this widget is + // redefined after a widget inherits from it + _childConstructors: [] + } ); + + basePrototype = new base(); + + // We need to make the options hash a property directly on the new instance + // otherwise we'll modify the options hash on the prototype that we're + // inheriting from + basePrototype.options = $.widget.extend( {}, basePrototype.options ); + $.each( prototype, function( prop, value ) { + if ( typeof value !== "function" ) { + proxiedPrototype[ prop ] = value; + return; + } + proxiedPrototype[ prop ] = ( function() { + function _super() { + return base.prototype[ prop ].apply( this, arguments ); + } + + function _superApply( args ) { + return base.prototype[ prop ].apply( this, args ); + } + + return function() { + var __super = this._super; + var __superApply = this._superApply; + var returnValue; + + this._super = _super; + this._superApply = _superApply; + + returnValue = value.apply( this, arguments ); + + this._super = __super; + this._superApply = __superApply; + + return returnValue; + }; + } )(); + } ); + constructor.prototype = $.widget.extend( basePrototype, { + + // TODO: remove support for widgetEventPrefix + // always use the name + a colon as the prefix, e.g., draggable:start + // don't prefix for widgets that aren't DOM-based + widgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name + }, proxiedPrototype, { + constructor: constructor, + namespace: namespace, + widgetName: name, + widgetFullName: fullName + } ); + + // If this widget is being redefined then we need to find all widgets that + // are inheriting from it and redefine all of them so that they inherit from + // the new version of this widget. We're essentially trying to replace one + // level in the prototype chain. + if ( existingConstructor ) { + $.each( existingConstructor._childConstructors, function( i, child ) { + var childPrototype = child.prototype; + + // Redefine the child widget using the same prototype that was + // originally used, but inherit from the new version of the base + $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, + child._proto ); + } ); + + // Remove the list of existing child constructors from the old constructor + // so the old child constructors can be garbage collected + delete existingConstructor._childConstructors; + } else { + base._childConstructors.push( constructor ); + } + + $.widget.bridge( name, constructor ); + + return constructor; +}; + +$.widget.extend = function( target ) { + var input = widgetSlice.call( arguments, 1 ); + var inputIndex = 0; + var inputLength = input.length; + var key; + var value; + + for ( ; inputIndex < inputLength; inputIndex++ ) { + for ( key in input[ inputIndex ] ) { + value = input[ inputIndex ][ key ]; + if ( widgetHasOwnProperty.call( input[ inputIndex ], key ) && value !== undefined ) { + + // Clone objects + if ( $.isPlainObject( value ) ) { + target[ key ] = $.isPlainObject( target[ key ] ) ? + $.widget.extend( {}, target[ key ], value ) : + + // Don't extend strings, arrays, etc. with objects + $.widget.extend( {}, value ); + + // Copy everything else by reference + } else { + target[ key ] = value; + } + } + } + } + return target; +}; + +$.widget.bridge = function( name, object ) { + var fullName = object.prototype.widgetFullName || name; + $.fn[ name ] = function( options ) { + var isMethodCall = typeof options === "string"; + var args = widgetSlice.call( arguments, 1 ); + var returnValue = this; + + if ( isMethodCall ) { + + // If this is an empty collection, we need to have the instance method + // return undefined instead of the jQuery instance + if ( !this.length && options === "instance" ) { + returnValue = undefined; + } else { + this.each( function() { + var methodValue; + var instance = $.data( this, fullName ); + + if ( options === "instance" ) { + returnValue = instance; + return false; + } + + if ( !instance ) { + return $.error( "cannot call methods on " + name + + " prior to initialization; " + + "attempted to call method '" + options + "'" ); + } + + if ( typeof instance[ options ] !== "function" || + options.charAt( 0 ) === "_" ) { + return $.error( "no such method '" + options + "' for " + name + + " widget instance" ); + } + + methodValue = instance[ options ].apply( instance, args ); + + if ( methodValue !== instance && methodValue !== undefined ) { + returnValue = methodValue && methodValue.jquery ? + returnValue.pushStack( methodValue.get() ) : + methodValue; + return false; + } + } ); + } + } else { + + // Allow multiple hashes to be passed on init + if ( args.length ) { + options = $.widget.extend.apply( null, [ options ].concat( args ) ); + } + + this.each( function() { + var instance = $.data( this, fullName ); + if ( instance ) { + instance.option( options || {} ); + if ( instance._init ) { + instance._init(); + } + } else { + $.data( this, fullName, new object( options, this ) ); + } + } ); + } + + return returnValue; + }; +}; + +$.Widget = function( /* options, element */ ) {}; +$.Widget._childConstructors = []; + +$.Widget.prototype = { + widgetName: "widget", + widgetEventPrefix: "", + defaultElement: "
    ", + + options: { + classes: {}, + disabled: false, + + // Callbacks + create: null + }, + + _createWidget: function( options, element ) { + element = $( element || this.defaultElement || this )[ 0 ]; + this.element = $( element ); + this.uuid = widgetUuid++; + this.eventNamespace = "." + this.widgetName + this.uuid; + + this.bindings = $(); + this.hoverable = $(); + this.focusable = $(); + this.classesElementLookup = {}; + + if ( element !== this ) { + $.data( element, this.widgetFullName, this ); + this._on( true, this.element, { + remove: function( event ) { + if ( event.target === element ) { + this.destroy(); + } + } + } ); + this.document = $( element.style ? + + // Element within the document + element.ownerDocument : + + // Element is window or document + element.document || element ); + this.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow ); + } + + this.options = $.widget.extend( {}, + this.options, + this._getCreateOptions(), + options ); + + this._create(); + + if ( this.options.disabled ) { + this._setOptionDisabled( this.options.disabled ); + } + + this._trigger( "create", null, this._getCreateEventData() ); + this._init(); + }, + + _getCreateOptions: function() { + return {}; + }, + + _getCreateEventData: $.noop, + + _create: $.noop, + + _init: $.noop, + + destroy: function() { + var that = this; + + this._destroy(); + $.each( this.classesElementLookup, function( key, value ) { + that._removeClass( value, key ); + } ); + + // We can probably remove the unbind calls in 2.0 + // all event bindings should go through this._on() + this.element + .off( this.eventNamespace ) + .removeData( this.widgetFullName ); + this.widget() + .off( this.eventNamespace ) + .removeAttr( "aria-disabled" ); + + // Clean up events and states + this.bindings.off( this.eventNamespace ); + }, + + _destroy: $.noop, + + widget: function() { + return this.element; + }, + + option: function( key, value ) { + var options = key; + var parts; + var curOption; + var i; + + if ( arguments.length === 0 ) { + + // Don't return a reference to the internal hash + return $.widget.extend( {}, this.options ); + } + + if ( typeof key === "string" ) { + + // Handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } } + options = {}; + parts = key.split( "." ); + key = parts.shift(); + if ( parts.length ) { + curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] ); + for ( i = 0; i < parts.length - 1; i++ ) { + curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {}; + curOption = curOption[ parts[ i ] ]; + } + key = parts.pop(); + if ( arguments.length === 1 ) { + return curOption[ key ] === undefined ? null : curOption[ key ]; + } + curOption[ key ] = value; + } else { + if ( arguments.length === 1 ) { + return this.options[ key ] === undefined ? null : this.options[ key ]; + } + options[ key ] = value; + } + } + + this._setOptions( options ); + + return this; + }, + + _setOptions: function( options ) { + var key; + + for ( key in options ) { + this._setOption( key, options[ key ] ); + } + + return this; + }, + + _setOption: function( key, value ) { + if ( key === "classes" ) { + this._setOptionClasses( value ); + } + + this.options[ key ] = value; + + if ( key === "disabled" ) { + this._setOptionDisabled( value ); + } + + return this; + }, + + _setOptionClasses: function( value ) { + var classKey, elements, currentElements; + + for ( classKey in value ) { + currentElements = this.classesElementLookup[ classKey ]; + if ( value[ classKey ] === this.options.classes[ classKey ] || + !currentElements || + !currentElements.length ) { + continue; + } + + // We are doing this to create a new jQuery object because the _removeClass() call + // on the next line is going to destroy the reference to the current elements being + // tracked. We need to save a copy of this collection so that we can add the new classes + // below. + elements = $( currentElements.get() ); + this._removeClass( currentElements, classKey ); + + // We don't use _addClass() here, because that uses this.options.classes + // for generating the string of classes. We want to use the value passed in from + // _setOption(), this is the new value of the classes option which was passed to + // _setOption(). We pass this value directly to _classes(). + elements.addClass( this._classes( { + element: elements, + keys: classKey, + classes: value, + add: true + } ) ); + } + }, + + _setOptionDisabled: function( value ) { + this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, !!value ); + + // If the widget is becoming disabled, then nothing is interactive + if ( value ) { + this._removeClass( this.hoverable, null, "ui-state-hover" ); + this._removeClass( this.focusable, null, "ui-state-focus" ); + } + }, + + enable: function() { + return this._setOptions( { disabled: false } ); + }, + + disable: function() { + return this._setOptions( { disabled: true } ); + }, + + _classes: function( options ) { + var full = []; + var that = this; + + options = $.extend( { + element: this.element, + classes: this.options.classes || {} + }, options ); + + function bindRemoveEvent() { + var nodesToBind = []; + + options.element.each( function( _, element ) { + var isTracked = $.map( that.classesElementLookup, function( elements ) { + return elements; + } ) + .some( function( elements ) { + return elements.is( element ); + } ); + + if ( !isTracked ) { + nodesToBind.push( element ); + } + } ); + + that._on( $( nodesToBind ), { + remove: "_untrackClassesElement" + } ); + } + + function processClassString( classes, checkOption ) { + var current, i; + for ( i = 0; i < classes.length; i++ ) { + current = that.classesElementLookup[ classes[ i ] ] || $(); + if ( options.add ) { + bindRemoveEvent(); + current = $( $.uniqueSort( current.get().concat( options.element.get() ) ) ); + } else { + current = $( current.not( options.element ).get() ); + } + that.classesElementLookup[ classes[ i ] ] = current; + full.push( classes[ i ] ); + if ( checkOption && options.classes[ classes[ i ] ] ) { + full.push( options.classes[ classes[ i ] ] ); + } + } + } + + if ( options.keys ) { + processClassString( options.keys.match( /\S+/g ) || [], true ); + } + if ( options.extra ) { + processClassString( options.extra.match( /\S+/g ) || [] ); + } + + return full.join( " " ); + }, + + _untrackClassesElement: function( event ) { + var that = this; + $.each( that.classesElementLookup, function( key, value ) { + if ( $.inArray( event.target, value ) !== -1 ) { + that.classesElementLookup[ key ] = $( value.not( event.target ).get() ); + } + } ); + + this._off( $( event.target ) ); + }, + + _removeClass: function( element, keys, extra ) { + return this._toggleClass( element, keys, extra, false ); + }, + + _addClass: function( element, keys, extra ) { + return this._toggleClass( element, keys, extra, true ); + }, + + _toggleClass: function( element, keys, extra, add ) { + add = ( typeof add === "boolean" ) ? add : extra; + var shift = ( typeof element === "string" || element === null ), + options = { + extra: shift ? keys : extra, + keys: shift ? element : keys, + element: shift ? this.element : element, + add: add + }; + options.element.toggleClass( this._classes( options ), add ); + return this; + }, + + _on: function( suppressDisabledCheck, element, handlers ) { + var delegateElement; + var instance = this; + + // No suppressDisabledCheck flag, shuffle arguments + if ( typeof suppressDisabledCheck !== "boolean" ) { + handlers = element; + element = suppressDisabledCheck; + suppressDisabledCheck = false; + } + + // No element argument, shuffle and use this.element + if ( !handlers ) { + handlers = element; + element = this.element; + delegateElement = this.widget(); + } else { + element = delegateElement = $( element ); + this.bindings = this.bindings.add( element ); + } + + $.each( handlers, function( event, handler ) { + function handlerProxy() { + + // Allow widgets to customize the disabled handling + // - disabled as an array instead of boolean + // - disabled class as method for disabling individual parts + if ( !suppressDisabledCheck && + ( instance.options.disabled === true || + $( this ).hasClass( "ui-state-disabled" ) ) ) { + return; + } + return ( typeof handler === "string" ? instance[ handler ] : handler ) + .apply( instance, arguments ); + } + + // Copy the guid so direct unbinding works + if ( typeof handler !== "string" ) { + handlerProxy.guid = handler.guid = + handler.guid || handlerProxy.guid || $.guid++; + } + + var match = event.match( /^([\w:-]*)\s*(.*)$/ ); + var eventName = match[ 1 ] + instance.eventNamespace; + var selector = match[ 2 ]; + + if ( selector ) { + delegateElement.on( eventName, selector, handlerProxy ); + } else { + element.on( eventName, handlerProxy ); + } + } ); + }, + + _off: function( element, eventName ) { + eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) + + this.eventNamespace; + element.off( eventName ); + + // Clear the stack to avoid memory leaks (#10056) + this.bindings = $( this.bindings.not( element ).get() ); + this.focusable = $( this.focusable.not( element ).get() ); + this.hoverable = $( this.hoverable.not( element ).get() ); + }, + + _delay: function( handler, delay ) { + function handlerProxy() { + return ( typeof handler === "string" ? instance[ handler ] : handler ) + .apply( instance, arguments ); + } + var instance = this; + return setTimeout( handlerProxy, delay || 0 ); + }, + + _hoverable: function( element ) { + this.hoverable = this.hoverable.add( element ); + this._on( element, { + mouseenter: function( event ) { + this._addClass( $( event.currentTarget ), null, "ui-state-hover" ); + }, + mouseleave: function( event ) { + this._removeClass( $( event.currentTarget ), null, "ui-state-hover" ); + } + } ); + }, + + _focusable: function( element ) { + this.focusable = this.focusable.add( element ); + this._on( element, { + focusin: function( event ) { + this._addClass( $( event.currentTarget ), null, "ui-state-focus" ); + }, + focusout: function( event ) { + this._removeClass( $( event.currentTarget ), null, "ui-state-focus" ); + } + } ); + }, + + _trigger: function( type, event, data ) { + var prop, orig; + var callback = this.options[ type ]; + + data = data || {}; + event = $.Event( event ); + event.type = ( type === this.widgetEventPrefix ? + type : + this.widgetEventPrefix + type ).toLowerCase(); + + // The original event may come from any element + // so we need to reset the target on the new event + event.target = this.element[ 0 ]; + + // Copy original event properties over to the new event + orig = event.originalEvent; + if ( orig ) { + for ( prop in orig ) { + if ( !( prop in event ) ) { + event[ prop ] = orig[ prop ]; + } + } + } + + this.element.trigger( event, data ); + return !( typeof callback === "function" && + callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false || + event.isDefaultPrevented() ); + } +}; + +$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) { + $.Widget.prototype[ "_" + method ] = function( element, options, callback ) { + if ( typeof options === "string" ) { + options = { effect: options }; + } + + var hasOptions; + var effectName = !options ? + method : + options === true || typeof options === "number" ? + defaultEffect : + options.effect || defaultEffect; + + options = options || {}; + if ( typeof options === "number" ) { + options = { duration: options }; + } else if ( options === true ) { + options = {}; + } + + hasOptions = !$.isEmptyObject( options ); + options.complete = callback; + + if ( options.delay ) { + element.delay( options.delay ); + } + + if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) { + element[ method ]( options ); + } else if ( effectName !== method && element[ effectName ] ) { + element[ effectName ]( options.duration, options.easing, callback ); + } else { + element.queue( function( next ) { + $( this )[ method ](); + if ( callback ) { + callback.call( element[ 0 ] ); + } + next(); + } ); + } + }; +} ); + +var widget = $.widget; + + +/*! + * jQuery UI Position 1.13.2 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * http://api.jqueryui.com/position/ + */ + +//>>label: Position +//>>group: Core +//>>description: Positions elements relative to other elements. +//>>docs: http://api.jqueryui.com/position/ +//>>demos: http://jqueryui.com/position/ + + +( function() { +var cachedScrollbarWidth, + max = Math.max, + abs = Math.abs, + rhorizontal = /left|center|right/, + rvertical = /top|center|bottom/, + roffset = /[\+\-]\d+(\.[\d]+)?%?/, + rposition = /^\w+/, + rpercent = /%$/, + _position = $.fn.position; + +function getOffsets( offsets, width, height ) { + return [ + parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ), + parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 ) + ]; +} + +function parseCss( element, property ) { + return parseInt( $.css( element, property ), 10 ) || 0; +} + +function isWindow( obj ) { + return obj != null && obj === obj.window; +} + +function getDimensions( elem ) { + var raw = elem[ 0 ]; + if ( raw.nodeType === 9 ) { + return { + width: elem.width(), + height: elem.height(), + offset: { top: 0, left: 0 } + }; + } + if ( isWindow( raw ) ) { + return { + width: elem.width(), + height: elem.height(), + offset: { top: elem.scrollTop(), left: elem.scrollLeft() } + }; + } + if ( raw.preventDefault ) { + return { + width: 0, + height: 0, + offset: { top: raw.pageY, left: raw.pageX } + }; + } + return { + width: elem.outerWidth(), + height: elem.outerHeight(), + offset: elem.offset() + }; +} + +$.position = { + scrollbarWidth: function() { + if ( cachedScrollbarWidth !== undefined ) { + return cachedScrollbarWidth; + } + var w1, w2, + div = $( "
    " + + "
    " ), + innerDiv = div.children()[ 0 ]; + + $( "body" ).append( div ); + w1 = innerDiv.offsetWidth; + div.css( "overflow", "scroll" ); + + w2 = innerDiv.offsetWidth; + + if ( w1 === w2 ) { + w2 = div[ 0 ].clientWidth; + } + + div.remove(); + + return ( cachedScrollbarWidth = w1 - w2 ); + }, + getScrollInfo: function( within ) { + var overflowX = within.isWindow || within.isDocument ? "" : + within.element.css( "overflow-x" ), + overflowY = within.isWindow || within.isDocument ? "" : + within.element.css( "overflow-y" ), + hasOverflowX = overflowX === "scroll" || + ( overflowX === "auto" && within.width < within.element[ 0 ].scrollWidth ), + hasOverflowY = overflowY === "scroll" || + ( overflowY === "auto" && within.height < within.element[ 0 ].scrollHeight ); + return { + width: hasOverflowY ? $.position.scrollbarWidth() : 0, + height: hasOverflowX ? $.position.scrollbarWidth() : 0 + }; + }, + getWithinInfo: function( element ) { + var withinElement = $( element || window ), + isElemWindow = isWindow( withinElement[ 0 ] ), + isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9, + hasOffset = !isElemWindow && !isDocument; + return { + element: withinElement, + isWindow: isElemWindow, + isDocument: isDocument, + offset: hasOffset ? $( element ).offset() : { left: 0, top: 0 }, + scrollLeft: withinElement.scrollLeft(), + scrollTop: withinElement.scrollTop(), + width: withinElement.outerWidth(), + height: withinElement.outerHeight() + }; + } +}; + +$.fn.position = function( options ) { + if ( !options || !options.of ) { + return _position.apply( this, arguments ); + } + + // Make a copy, we don't want to modify arguments + options = $.extend( {}, options ); + + var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions, + + // Make sure string options are treated as CSS selectors + target = typeof options.of === "string" ? + $( document ).find( options.of ) : + $( options.of ), + + within = $.position.getWithinInfo( options.within ), + scrollInfo = $.position.getScrollInfo( within ), + collision = ( options.collision || "flip" ).split( " " ), + offsets = {}; + + dimensions = getDimensions( target ); + if ( target[ 0 ].preventDefault ) { + + // Force left top to allow flipping + options.at = "left top"; + } + targetWidth = dimensions.width; + targetHeight = dimensions.height; + targetOffset = dimensions.offset; + + // Clone to reuse original targetOffset later + basePosition = $.extend( {}, targetOffset ); + + // Force my and at to have valid horizontal and vertical positions + // if a value is missing or invalid, it will be converted to center + $.each( [ "my", "at" ], function() { + var pos = ( options[ this ] || "" ).split( " " ), + horizontalOffset, + verticalOffset; + + if ( pos.length === 1 ) { + pos = rhorizontal.test( pos[ 0 ] ) ? + pos.concat( [ "center" ] ) : + rvertical.test( pos[ 0 ] ) ? + [ "center" ].concat( pos ) : + [ "center", "center" ]; + } + pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center"; + pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center"; + + // Calculate offsets + horizontalOffset = roffset.exec( pos[ 0 ] ); + verticalOffset = roffset.exec( pos[ 1 ] ); + offsets[ this ] = [ + horizontalOffset ? horizontalOffset[ 0 ] : 0, + verticalOffset ? verticalOffset[ 0 ] : 0 + ]; + + // Reduce to just the positions without the offsets + options[ this ] = [ + rposition.exec( pos[ 0 ] )[ 0 ], + rposition.exec( pos[ 1 ] )[ 0 ] + ]; + } ); + + // Normalize collision option + if ( collision.length === 1 ) { + collision[ 1 ] = collision[ 0 ]; + } + + if ( options.at[ 0 ] === "right" ) { + basePosition.left += targetWidth; + } else if ( options.at[ 0 ] === "center" ) { + basePosition.left += targetWidth / 2; + } + + if ( options.at[ 1 ] === "bottom" ) { + basePosition.top += targetHeight; + } else if ( options.at[ 1 ] === "center" ) { + basePosition.top += targetHeight / 2; + } + + atOffset = getOffsets( offsets.at, targetWidth, targetHeight ); + basePosition.left += atOffset[ 0 ]; + basePosition.top += atOffset[ 1 ]; + + return this.each( function() { + var collisionPosition, using, + elem = $( this ), + elemWidth = elem.outerWidth(), + elemHeight = elem.outerHeight(), + marginLeft = parseCss( this, "marginLeft" ), + marginTop = parseCss( this, "marginTop" ), + collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + + scrollInfo.width, + collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + + scrollInfo.height, + position = $.extend( {}, basePosition ), + myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() ); + + if ( options.my[ 0 ] === "right" ) { + position.left -= elemWidth; + } else if ( options.my[ 0 ] === "center" ) { + position.left -= elemWidth / 2; + } + + if ( options.my[ 1 ] === "bottom" ) { + position.top -= elemHeight; + } else if ( options.my[ 1 ] === "center" ) { + position.top -= elemHeight / 2; + } + + position.left += myOffset[ 0 ]; + position.top += myOffset[ 1 ]; + + collisionPosition = { + marginLeft: marginLeft, + marginTop: marginTop + }; + + $.each( [ "left", "top" ], function( i, dir ) { + if ( $.ui.position[ collision[ i ] ] ) { + $.ui.position[ collision[ i ] ][ dir ]( position, { + targetWidth: targetWidth, + targetHeight: targetHeight, + elemWidth: elemWidth, + elemHeight: elemHeight, + collisionPosition: collisionPosition, + collisionWidth: collisionWidth, + collisionHeight: collisionHeight, + offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ], + my: options.my, + at: options.at, + within: within, + elem: elem + } ); + } + } ); + + if ( options.using ) { + + // Adds feedback as second argument to using callback, if present + using = function( props ) { + var left = targetOffset.left - position.left, + right = left + targetWidth - elemWidth, + top = targetOffset.top - position.top, + bottom = top + targetHeight - elemHeight, + feedback = { + target: { + element: target, + left: targetOffset.left, + top: targetOffset.top, + width: targetWidth, + height: targetHeight + }, + element: { + element: elem, + left: position.left, + top: position.top, + width: elemWidth, + height: elemHeight + }, + horizontal: right < 0 ? "left" : left > 0 ? "right" : "center", + vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle" + }; + if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) { + feedback.horizontal = "center"; + } + if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) { + feedback.vertical = "middle"; + } + if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) { + feedback.important = "horizontal"; + } else { + feedback.important = "vertical"; + } + options.using.call( this, props, feedback ); + }; + } + + elem.offset( $.extend( position, { using: using } ) ); + } ); +}; + +$.ui.position = { + fit: { + left: function( position, data ) { + var within = data.within, + withinOffset = within.isWindow ? within.scrollLeft : within.offset.left, + outerWidth = within.width, + collisionPosLeft = position.left - data.collisionPosition.marginLeft, + overLeft = withinOffset - collisionPosLeft, + overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset, + newOverRight; + + // Element is wider than within + if ( data.collisionWidth > outerWidth ) { + + // Element is initially over the left side of within + if ( overLeft > 0 && overRight <= 0 ) { + newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - + withinOffset; + position.left += overLeft - newOverRight; + + // Element is initially over right side of within + } else if ( overRight > 0 && overLeft <= 0 ) { + position.left = withinOffset; + + // Element is initially over both left and right sides of within + } else { + if ( overLeft > overRight ) { + position.left = withinOffset + outerWidth - data.collisionWidth; + } else { + position.left = withinOffset; + } + } + + // Too far left -> align with left edge + } else if ( overLeft > 0 ) { + position.left += overLeft; + + // Too far right -> align with right edge + } else if ( overRight > 0 ) { + position.left -= overRight; + + // Adjust based on position and margin + } else { + position.left = max( position.left - collisionPosLeft, position.left ); + } + }, + top: function( position, data ) { + var within = data.within, + withinOffset = within.isWindow ? within.scrollTop : within.offset.top, + outerHeight = data.within.height, + collisionPosTop = position.top - data.collisionPosition.marginTop, + overTop = withinOffset - collisionPosTop, + overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset, + newOverBottom; + + // Element is taller than within + if ( data.collisionHeight > outerHeight ) { + + // Element is initially over the top of within + if ( overTop > 0 && overBottom <= 0 ) { + newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - + withinOffset; + position.top += overTop - newOverBottom; + + // Element is initially over bottom of within + } else if ( overBottom > 0 && overTop <= 0 ) { + position.top = withinOffset; + + // Element is initially over both top and bottom of within + } else { + if ( overTop > overBottom ) { + position.top = withinOffset + outerHeight - data.collisionHeight; + } else { + position.top = withinOffset; + } + } + + // Too far up -> align with top + } else if ( overTop > 0 ) { + position.top += overTop; + + // Too far down -> align with bottom edge + } else if ( overBottom > 0 ) { + position.top -= overBottom; + + // Adjust based on position and margin + } else { + position.top = max( position.top - collisionPosTop, position.top ); + } + } + }, + flip: { + left: function( position, data ) { + var within = data.within, + withinOffset = within.offset.left + within.scrollLeft, + outerWidth = within.width, + offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left, + collisionPosLeft = position.left - data.collisionPosition.marginLeft, + overLeft = collisionPosLeft - offsetLeft, + overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft, + myOffset = data.my[ 0 ] === "left" ? + -data.elemWidth : + data.my[ 0 ] === "right" ? + data.elemWidth : + 0, + atOffset = data.at[ 0 ] === "left" ? + data.targetWidth : + data.at[ 0 ] === "right" ? + -data.targetWidth : + 0, + offset = -2 * data.offset[ 0 ], + newOverRight, + newOverLeft; + + if ( overLeft < 0 ) { + newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - + outerWidth - withinOffset; + if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) { + position.left += myOffset + atOffset + offset; + } + } else if ( overRight > 0 ) { + newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + + atOffset + offset - offsetLeft; + if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) { + position.left += myOffset + atOffset + offset; + } + } + }, + top: function( position, data ) { + var within = data.within, + withinOffset = within.offset.top + within.scrollTop, + outerHeight = within.height, + offsetTop = within.isWindow ? within.scrollTop : within.offset.top, + collisionPosTop = position.top - data.collisionPosition.marginTop, + overTop = collisionPosTop - offsetTop, + overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop, + top = data.my[ 1 ] === "top", + myOffset = top ? + -data.elemHeight : + data.my[ 1 ] === "bottom" ? + data.elemHeight : + 0, + atOffset = data.at[ 1 ] === "top" ? + data.targetHeight : + data.at[ 1 ] === "bottom" ? + -data.targetHeight : + 0, + offset = -2 * data.offset[ 1 ], + newOverTop, + newOverBottom; + if ( overTop < 0 ) { + newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - + outerHeight - withinOffset; + if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) { + position.top += myOffset + atOffset + offset; + } + } else if ( overBottom > 0 ) { + newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + + offset - offsetTop; + if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) { + position.top += myOffset + atOffset + offset; + } + } + } + }, + flipfit: { + left: function() { + $.ui.position.flip.left.apply( this, arguments ); + $.ui.position.fit.left.apply( this, arguments ); + }, + top: function() { + $.ui.position.flip.top.apply( this, arguments ); + $.ui.position.fit.top.apply( this, arguments ); + } + } +}; + +} )(); + +var position = $.ui.position; + + +/*! + * jQuery UI :data 1.13.2 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: :data Selector +//>>group: Core +//>>description: Selects elements which have data stored under the specified key. +//>>docs: http://api.jqueryui.com/data-selector/ + + +var data = $.extend( $.expr.pseudos, { + data: $.expr.createPseudo ? + $.expr.createPseudo( function( dataName ) { + return function( elem ) { + return !!$.data( elem, dataName ); + }; + } ) : + + // Support: jQuery <1.8 + function( elem, i, match ) { + return !!$.data( elem, match[ 3 ] ); + } +} ); + +/*! + * jQuery UI Disable Selection 1.13.2 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: disableSelection +//>>group: Core +//>>description: Disable selection of text content within the set of matched elements. +//>>docs: http://api.jqueryui.com/disableSelection/ + +// This file is deprecated + +var disableSelection = $.fn.extend( { + disableSelection: ( function() { + var eventType = "onselectstart" in document.createElement( "div" ) ? + "selectstart" : + "mousedown"; + + return function() { + return this.on( eventType + ".ui-disableSelection", function( event ) { + event.preventDefault(); + } ); + }; + } )(), + + enableSelection: function() { + return this.off( ".ui-disableSelection" ); + } +} ); + + + +// Create a local jQuery because jQuery Color relies on it and the +// global may not exist with AMD and a custom build (#10199). +// This module is a noop if used as a regular AMD module. +// eslint-disable-next-line no-unused-vars +var jQuery = $; + + +/*! + * jQuery Color Animations v2.2.0 + * https://github.com/jquery/jquery-color + * + * Copyright OpenJS Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + * Date: Sun May 10 09:02:36 2020 +0200 + */ + + + + var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor " + + "borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor", + + class2type = {}, + toString = class2type.toString, + + // plusequals test for += 100 -= 100 + rplusequals = /^([\-+])=\s*(\d+\.?\d*)/, + + // a set of RE's that can match strings and generate color tuples. + stringParsers = [ { + re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, + parse: function( execResult ) { + return [ + execResult[ 1 ], + execResult[ 2 ], + execResult[ 3 ], + execResult[ 4 ] + ]; + } + }, { + re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, + parse: function( execResult ) { + return [ + execResult[ 1 ] * 2.55, + execResult[ 2 ] * 2.55, + execResult[ 3 ] * 2.55, + execResult[ 4 ] + ]; + } + }, { + + // this regex ignores A-F because it's compared against an already lowercased string + re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})?/, + parse: function( execResult ) { + return [ + parseInt( execResult[ 1 ], 16 ), + parseInt( execResult[ 2 ], 16 ), + parseInt( execResult[ 3 ], 16 ), + execResult[ 4 ] ? + ( parseInt( execResult[ 4 ], 16 ) / 255 ).toFixed( 2 ) : + 1 + ]; + } + }, { + + // this regex ignores A-F because it's compared against an already lowercased string + re: /#([a-f0-9])([a-f0-9])([a-f0-9])([a-f0-9])?/, + parse: function( execResult ) { + return [ + parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ), + parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ), + parseInt( execResult[ 3 ] + execResult[ 3 ], 16 ), + execResult[ 4 ] ? + ( parseInt( execResult[ 4 ] + execResult[ 4 ], 16 ) / 255 ) + .toFixed( 2 ) : + 1 + ]; + } + }, { + re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/, + space: "hsla", + parse: function( execResult ) { + return [ + execResult[ 1 ], + execResult[ 2 ] / 100, + execResult[ 3 ] / 100, + execResult[ 4 ] + ]; + } + } ], + + // jQuery.Color( ) + color = jQuery.Color = function( color, green, blue, alpha ) { + return new jQuery.Color.fn.parse( color, green, blue, alpha ); + }, + spaces = { + rgba: { + props: { + red: { + idx: 0, + type: "byte" + }, + green: { + idx: 1, + type: "byte" + }, + blue: { + idx: 2, + type: "byte" + } + } + }, + + hsla: { + props: { + hue: { + idx: 0, + type: "degrees" + }, + saturation: { + idx: 1, + type: "percent" + }, + lightness: { + idx: 2, + type: "percent" + } + } + } + }, + propTypes = { + "byte": { + floor: true, + max: 255 + }, + "percent": { + max: 1 + }, + "degrees": { + mod: 360, + floor: true + } + }, + support = color.support = {}, + + // element for support tests + supportElem = jQuery( "

    " )[ 0 ], + + // colors = jQuery.Color.names + colors, + + // local aliases of functions called often + each = jQuery.each; + +// determine rgba support immediately +supportElem.style.cssText = "background-color:rgba(1,1,1,.5)"; +support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1; + +// define cache name and alpha properties +// for rgba and hsla spaces +each( spaces, function( spaceName, space ) { + space.cache = "_" + spaceName; + space.props.alpha = { + idx: 3, + type: "percent", + def: 1 + }; +} ); + +// Populate the class2type map +jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ), + function( _i, name ) { + class2type[ "[object " + name + "]" ] = name.toLowerCase(); + } ); + +function getType( obj ) { + if ( obj == null ) { + return obj + ""; + } + + return typeof obj === "object" ? + class2type[ toString.call( obj ) ] || "object" : + typeof obj; +} + +function clamp( value, prop, allowEmpty ) { + var type = propTypes[ prop.type ] || {}; + + if ( value == null ) { + return ( allowEmpty || !prop.def ) ? null : prop.def; + } + + // ~~ is an short way of doing floor for positive numbers + value = type.floor ? ~~value : parseFloat( value ); + + // IE will pass in empty strings as value for alpha, + // which will hit this case + if ( isNaN( value ) ) { + return prop.def; + } + + if ( type.mod ) { + + // we add mod before modding to make sure that negatives values + // get converted properly: -10 -> 350 + return ( value + type.mod ) % type.mod; + } + + // for now all property types without mod have min and max + return Math.min( type.max, Math.max( 0, value ) ); +} + +function stringParse( string ) { + var inst = color(), + rgba = inst._rgba = []; + + string = string.toLowerCase(); + + each( stringParsers, function( _i, parser ) { + var parsed, + match = parser.re.exec( string ), + values = match && parser.parse( match ), + spaceName = parser.space || "rgba"; + + if ( values ) { + parsed = inst[ spaceName ]( values ); + + // if this was an rgba parse the assignment might happen twice + // oh well.... + inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ]; + rgba = inst._rgba = parsed._rgba; + + // exit each( stringParsers ) here because we matched + return false; + } + } ); + + // Found a stringParser that handled it + if ( rgba.length ) { + + // if this came from a parsed string, force "transparent" when alpha is 0 + // chrome, (and maybe others) return "transparent" as rgba(0,0,0,0) + if ( rgba.join() === "0,0,0,0" ) { + jQuery.extend( rgba, colors.transparent ); + } + return inst; + } + + // named colors + return colors[ string ]; +} + +color.fn = jQuery.extend( color.prototype, { + parse: function( red, green, blue, alpha ) { + if ( red === undefined ) { + this._rgba = [ null, null, null, null ]; + return this; + } + if ( red.jquery || red.nodeType ) { + red = jQuery( red ).css( green ); + green = undefined; + } + + var inst = this, + type = getType( red ), + rgba = this._rgba = []; + + // more than 1 argument specified - assume ( red, green, blue, alpha ) + if ( green !== undefined ) { + red = [ red, green, blue, alpha ]; + type = "array"; + } + + if ( type === "string" ) { + return this.parse( stringParse( red ) || colors._default ); + } + + if ( type === "array" ) { + each( spaces.rgba.props, function( _key, prop ) { + rgba[ prop.idx ] = clamp( red[ prop.idx ], prop ); + } ); + return this; + } + + if ( type === "object" ) { + if ( red instanceof color ) { + each( spaces, function( _spaceName, space ) { + if ( red[ space.cache ] ) { + inst[ space.cache ] = red[ space.cache ].slice(); + } + } ); + } else { + each( spaces, function( _spaceName, space ) { + var cache = space.cache; + each( space.props, function( key, prop ) { + + // if the cache doesn't exist, and we know how to convert + if ( !inst[ cache ] && space.to ) { + + // if the value was null, we don't need to copy it + // if the key was alpha, we don't need to copy it either + if ( key === "alpha" || red[ key ] == null ) { + return; + } + inst[ cache ] = space.to( inst._rgba ); + } + + // this is the only case where we allow nulls for ALL properties. + // call clamp with alwaysAllowEmpty + inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true ); + } ); + + // everything defined but alpha? + if ( inst[ cache ] && jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) { + + // use the default of 1 + if ( inst[ cache ][ 3 ] == null ) { + inst[ cache ][ 3 ] = 1; + } + + if ( space.from ) { + inst._rgba = space.from( inst[ cache ] ); + } + } + } ); + } + return this; + } + }, + is: function( compare ) { + var is = color( compare ), + same = true, + inst = this; + + each( spaces, function( _, space ) { + var localCache, + isCache = is[ space.cache ]; + if ( isCache ) { + localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || []; + each( space.props, function( _, prop ) { + if ( isCache[ prop.idx ] != null ) { + same = ( isCache[ prop.idx ] === localCache[ prop.idx ] ); + return same; + } + } ); + } + return same; + } ); + return same; + }, + _space: function() { + var used = [], + inst = this; + each( spaces, function( spaceName, space ) { + if ( inst[ space.cache ] ) { + used.push( spaceName ); + } + } ); + return used.pop(); + }, + transition: function( other, distance ) { + var end = color( other ), + spaceName = end._space(), + space = spaces[ spaceName ], + startColor = this.alpha() === 0 ? color( "transparent" ) : this, + start = startColor[ space.cache ] || space.to( startColor._rgba ), + result = start.slice(); + + end = end[ space.cache ]; + each( space.props, function( _key, prop ) { + var index = prop.idx, + startValue = start[ index ], + endValue = end[ index ], + type = propTypes[ prop.type ] || {}; + + // if null, don't override start value + if ( endValue === null ) { + return; + } + + // if null - use end + if ( startValue === null ) { + result[ index ] = endValue; + } else { + if ( type.mod ) { + if ( endValue - startValue > type.mod / 2 ) { + startValue += type.mod; + } else if ( startValue - endValue > type.mod / 2 ) { + startValue -= type.mod; + } + } + result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop ); + } + } ); + return this[ spaceName ]( result ); + }, + blend: function( opaque ) { + + // if we are already opaque - return ourself + if ( this._rgba[ 3 ] === 1 ) { + return this; + } + + var rgb = this._rgba.slice(), + a = rgb.pop(), + blend = color( opaque )._rgba; + + return color( jQuery.map( rgb, function( v, i ) { + return ( 1 - a ) * blend[ i ] + a * v; + } ) ); + }, + toRgbaString: function() { + var prefix = "rgba(", + rgba = jQuery.map( this._rgba, function( v, i ) { + if ( v != null ) { + return v; + } + return i > 2 ? 1 : 0; + } ); + + if ( rgba[ 3 ] === 1 ) { + rgba.pop(); + prefix = "rgb("; + } + + return prefix + rgba.join() + ")"; + }, + toHslaString: function() { + var prefix = "hsla(", + hsla = jQuery.map( this.hsla(), function( v, i ) { + if ( v == null ) { + v = i > 2 ? 1 : 0; + } + + // catch 1 and 2 + if ( i && i < 3 ) { + v = Math.round( v * 100 ) + "%"; + } + return v; + } ); + + if ( hsla[ 3 ] === 1 ) { + hsla.pop(); + prefix = "hsl("; + } + return prefix + hsla.join() + ")"; + }, + toHexString: function( includeAlpha ) { + var rgba = this._rgba.slice(), + alpha = rgba.pop(); + + if ( includeAlpha ) { + rgba.push( ~~( alpha * 255 ) ); + } + + return "#" + jQuery.map( rgba, function( v ) { + + // default to 0 when nulls exist + v = ( v || 0 ).toString( 16 ); + return v.length === 1 ? "0" + v : v; + } ).join( "" ); + }, + toString: function() { + return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString(); + } +} ); +color.fn.parse.prototype = color.fn; + +// hsla conversions adapted from: +// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021 + +function hue2rgb( p, q, h ) { + h = ( h + 1 ) % 1; + if ( h * 6 < 1 ) { + return p + ( q - p ) * h * 6; + } + if ( h * 2 < 1 ) { + return q; + } + if ( h * 3 < 2 ) { + return p + ( q - p ) * ( ( 2 / 3 ) - h ) * 6; + } + return p; +} + +spaces.hsla.to = function( rgba ) { + if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) { + return [ null, null, null, rgba[ 3 ] ]; + } + var r = rgba[ 0 ] / 255, + g = rgba[ 1 ] / 255, + b = rgba[ 2 ] / 255, + a = rgba[ 3 ], + max = Math.max( r, g, b ), + min = Math.min( r, g, b ), + diff = max - min, + add = max + min, + l = add * 0.5, + h, s; + + if ( min === max ) { + h = 0; + } else if ( r === max ) { + h = ( 60 * ( g - b ) / diff ) + 360; + } else if ( g === max ) { + h = ( 60 * ( b - r ) / diff ) + 120; + } else { + h = ( 60 * ( r - g ) / diff ) + 240; + } + + // chroma (diff) == 0 means greyscale which, by definition, saturation = 0% + // otherwise, saturation is based on the ratio of chroma (diff) to lightness (add) + if ( diff === 0 ) { + s = 0; + } else if ( l <= 0.5 ) { + s = diff / add; + } else { + s = diff / ( 2 - add ); + } + return [ Math.round( h ) % 360, s, l, a == null ? 1 : a ]; +}; + +spaces.hsla.from = function( hsla ) { + if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) { + return [ null, null, null, hsla[ 3 ] ]; + } + var h = hsla[ 0 ] / 360, + s = hsla[ 1 ], + l = hsla[ 2 ], + a = hsla[ 3 ], + q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s, + p = 2 * l - q; + + return [ + Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ), + Math.round( hue2rgb( p, q, h ) * 255 ), + Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ), + a + ]; +}; + + +each( spaces, function( spaceName, space ) { + var props = space.props, + cache = space.cache, + to = space.to, + from = space.from; + + // makes rgba() and hsla() + color.fn[ spaceName ] = function( value ) { + + // generate a cache for this space if it doesn't exist + if ( to && !this[ cache ] ) { + this[ cache ] = to( this._rgba ); + } + if ( value === undefined ) { + return this[ cache ].slice(); + } + + var ret, + type = getType( value ), + arr = ( type === "array" || type === "object" ) ? value : arguments, + local = this[ cache ].slice(); + + each( props, function( key, prop ) { + var val = arr[ type === "object" ? key : prop.idx ]; + if ( val == null ) { + val = local[ prop.idx ]; + } + local[ prop.idx ] = clamp( val, prop ); + } ); + + if ( from ) { + ret = color( from( local ) ); + ret[ cache ] = local; + return ret; + } else { + return color( local ); + } + }; + + // makes red() green() blue() alpha() hue() saturation() lightness() + each( props, function( key, prop ) { + + // alpha is included in more than one space + if ( color.fn[ key ] ) { + return; + } + color.fn[ key ] = function( value ) { + var local, cur, match, fn, + vtype = getType( value ); + + if ( key === "alpha" ) { + fn = this._hsla ? "hsla" : "rgba"; + } else { + fn = spaceName; + } + local = this[ fn ](); + cur = local[ prop.idx ]; + + if ( vtype === "undefined" ) { + return cur; + } + + if ( vtype === "function" ) { + value = value.call( this, cur ); + vtype = getType( value ); + } + if ( value == null && prop.empty ) { + return this; + } + if ( vtype === "string" ) { + match = rplusequals.exec( value ); + if ( match ) { + value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 ); + } + } + local[ prop.idx ] = value; + return this[ fn ]( local ); + }; + } ); +} ); + +// add cssHook and .fx.step function for each named hook. +// accept a space separated string of properties +color.hook = function( hook ) { + var hooks = hook.split( " " ); + each( hooks, function( _i, hook ) { + jQuery.cssHooks[ hook ] = { + set: function( elem, value ) { + var parsed, curElem, + backgroundColor = ""; + + if ( value !== "transparent" && ( getType( value ) !== "string" || ( parsed = stringParse( value ) ) ) ) { + value = color( parsed || value ); + if ( !support.rgba && value._rgba[ 3 ] !== 1 ) { + curElem = hook === "backgroundColor" ? elem.parentNode : elem; + while ( + ( backgroundColor === "" || backgroundColor === "transparent" ) && + curElem && curElem.style + ) { + try { + backgroundColor = jQuery.css( curElem, "backgroundColor" ); + curElem = curElem.parentNode; + } catch ( e ) { + } + } + + value = value.blend( backgroundColor && backgroundColor !== "transparent" ? + backgroundColor : + "_default" ); + } + + value = value.toRgbaString(); + } + try { + elem.style[ hook ] = value; + } catch ( e ) { + + // wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit' + } + } + }; + jQuery.fx.step[ hook ] = function( fx ) { + if ( !fx.colorInit ) { + fx.start = color( fx.elem, hook ); + fx.end = color( fx.end ); + fx.colorInit = true; + } + jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) ); + }; + } ); + +}; + +color.hook( stepHooks ); + +jQuery.cssHooks.borderColor = { + expand: function( value ) { + var expanded = {}; + + each( [ "Top", "Right", "Bottom", "Left" ], function( _i, part ) { + expanded[ "border" + part + "Color" ] = value; + } ); + return expanded; + } +}; + +// Basic color names only. +// Usage of any of the other color names requires adding yourself or including +// jquery.color.svg-names.js. +colors = jQuery.Color.names = { + + // 4.1. Basic color keywords + aqua: "#00ffff", + black: "#000000", + blue: "#0000ff", + fuchsia: "#ff00ff", + gray: "#808080", + green: "#008000", + lime: "#00ff00", + maroon: "#800000", + navy: "#000080", + olive: "#808000", + purple: "#800080", + red: "#ff0000", + silver: "#c0c0c0", + teal: "#008080", + white: "#ffffff", + yellow: "#ffff00", + + // 4.2.3. "transparent" color keyword + transparent: [ null, null, null, 0 ], + + _default: "#ffffff" +}; + + +/*! + * jQuery UI Effects 1.13.2 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Effects Core +//>>group: Effects +/* eslint-disable max-len */ +//>>description: Extends the internal jQuery effects. Includes morphing and easing. Required by all other effects. +/* eslint-enable max-len */ +//>>docs: http://api.jqueryui.com/category/effects-core/ +//>>demos: http://jqueryui.com/effect/ + + +var dataSpace = "ui-effects-", + dataSpaceStyle = "ui-effects-style", + dataSpaceAnimated = "ui-effects-animated"; + +$.effects = { + effect: {} +}; + +/******************************************************************************/ +/****************************** CLASS ANIMATIONS ******************************/ +/******************************************************************************/ +( function() { + +var classAnimationActions = [ "add", "remove", "toggle" ], + shorthandStyles = { + border: 1, + borderBottom: 1, + borderColor: 1, + borderLeft: 1, + borderRight: 1, + borderTop: 1, + borderWidth: 1, + margin: 1, + padding: 1 + }; + +$.each( + [ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], + function( _, prop ) { + $.fx.step[ prop ] = function( fx ) { + if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) { + jQuery.style( fx.elem, prop, fx.end ); + fx.setAttr = true; + } + }; + } +); + +function camelCase( string ) { + return string.replace( /-([\da-z])/gi, function( all, letter ) { + return letter.toUpperCase(); + } ); +} + +function getElementStyles( elem ) { + var key, len, + style = elem.ownerDocument.defaultView ? + elem.ownerDocument.defaultView.getComputedStyle( elem, null ) : + elem.currentStyle, + styles = {}; + + if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) { + len = style.length; + while ( len-- ) { + key = style[ len ]; + if ( typeof style[ key ] === "string" ) { + styles[ camelCase( key ) ] = style[ key ]; + } + } + + // Support: Opera, IE <9 + } else { + for ( key in style ) { + if ( typeof style[ key ] === "string" ) { + styles[ key ] = style[ key ]; + } + } + } + + return styles; +} + +function styleDifference( oldStyle, newStyle ) { + var diff = {}, + name, value; + + for ( name in newStyle ) { + value = newStyle[ name ]; + if ( oldStyle[ name ] !== value ) { + if ( !shorthandStyles[ name ] ) { + if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) { + diff[ name ] = value; + } + } + } + } + + return diff; +} + +// Support: jQuery <1.8 +if ( !$.fn.addBack ) { + $.fn.addBack = function( selector ) { + return this.add( selector == null ? + this.prevObject : this.prevObject.filter( selector ) + ); + }; +} + +$.effects.animateClass = function( value, duration, easing, callback ) { + var o = $.speed( duration, easing, callback ); + + return this.queue( function() { + var animated = $( this ), + baseClass = animated.attr( "class" ) || "", + applyClassChange, + allAnimations = o.children ? animated.find( "*" ).addBack() : animated; + + // Map the animated objects to store the original styles. + allAnimations = allAnimations.map( function() { + var el = $( this ); + return { + el: el, + start: getElementStyles( this ) + }; + } ); + + // Apply class change + applyClassChange = function() { + $.each( classAnimationActions, function( i, action ) { + if ( value[ action ] ) { + animated[ action + "Class" ]( value[ action ] ); + } + } ); + }; + applyClassChange(); + + // Map all animated objects again - calculate new styles and diff + allAnimations = allAnimations.map( function() { + this.end = getElementStyles( this.el[ 0 ] ); + this.diff = styleDifference( this.start, this.end ); + return this; + } ); + + // Apply original class + animated.attr( "class", baseClass ); + + // Map all animated objects again - this time collecting a promise + allAnimations = allAnimations.map( function() { + var styleInfo = this, + dfd = $.Deferred(), + opts = $.extend( {}, o, { + queue: false, + complete: function() { + dfd.resolve( styleInfo ); + } + } ); + + this.el.animate( this.diff, opts ); + return dfd.promise(); + } ); + + // Once all animations have completed: + $.when.apply( $, allAnimations.get() ).done( function() { + + // Set the final class + applyClassChange(); + + // For each animated element, + // clear all css properties that were animated + $.each( arguments, function() { + var el = this.el; + $.each( this.diff, function( key ) { + el.css( key, "" ); + } ); + } ); + + // This is guarnteed to be there if you use jQuery.speed() + // it also handles dequeuing the next anim... + o.complete.call( animated[ 0 ] ); + } ); + } ); +}; + +$.fn.extend( { + addClass: ( function( orig ) { + return function( classNames, speed, easing, callback ) { + return speed ? + $.effects.animateClass.call( this, + { add: classNames }, speed, easing, callback ) : + orig.apply( this, arguments ); + }; + } )( $.fn.addClass ), + + removeClass: ( function( orig ) { + return function( classNames, speed, easing, callback ) { + return arguments.length > 1 ? + $.effects.animateClass.call( this, + { remove: classNames }, speed, easing, callback ) : + orig.apply( this, arguments ); + }; + } )( $.fn.removeClass ), + + toggleClass: ( function( orig ) { + return function( classNames, force, speed, easing, callback ) { + if ( typeof force === "boolean" || force === undefined ) { + if ( !speed ) { + + // Without speed parameter + return orig.apply( this, arguments ); + } else { + return $.effects.animateClass.call( this, + ( force ? { add: classNames } : { remove: classNames } ), + speed, easing, callback ); + } + } else { + + // Without force parameter + return $.effects.animateClass.call( this, + { toggle: classNames }, force, speed, easing ); + } + }; + } )( $.fn.toggleClass ), + + switchClass: function( remove, add, speed, easing, callback ) { + return $.effects.animateClass.call( this, { + add: add, + remove: remove + }, speed, easing, callback ); + } +} ); + +} )(); + +/******************************************************************************/ +/*********************************** EFFECTS **********************************/ +/******************************************************************************/ + +( function() { + +if ( $.expr && $.expr.pseudos && $.expr.pseudos.animated ) { + $.expr.pseudos.animated = ( function( orig ) { + return function( elem ) { + return !!$( elem ).data( dataSpaceAnimated ) || orig( elem ); + }; + } )( $.expr.pseudos.animated ); +} + +if ( $.uiBackCompat !== false ) { + $.extend( $.effects, { + + // Saves a set of properties in a data storage + save: function( element, set ) { + var i = 0, length = set.length; + for ( ; i < length; i++ ) { + if ( set[ i ] !== null ) { + element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] ); + } + } + }, + + // Restores a set of previously saved properties from a data storage + restore: function( element, set ) { + var val, i = 0, length = set.length; + for ( ; i < length; i++ ) { + if ( set[ i ] !== null ) { + val = element.data( dataSpace + set[ i ] ); + element.css( set[ i ], val ); + } + } + }, + + setMode: function( el, mode ) { + if ( mode === "toggle" ) { + mode = el.is( ":hidden" ) ? "show" : "hide"; + } + return mode; + }, + + // Wraps the element around a wrapper that copies position properties + createWrapper: function( element ) { + + // If the element is already wrapped, return it + if ( element.parent().is( ".ui-effects-wrapper" ) ) { + return element.parent(); + } + + // Wrap the element + var props = { + width: element.outerWidth( true ), + height: element.outerHeight( true ), + "float": element.css( "float" ) + }, + wrapper = $( "

    " ) + .addClass( "ui-effects-wrapper" ) + .css( { + fontSize: "100%", + background: "transparent", + border: "none", + margin: 0, + padding: 0 + } ), + + // Store the size in case width/height are defined in % - Fixes #5245 + size = { + width: element.width(), + height: element.height() + }, + active = document.activeElement; + + // Support: Firefox + // Firefox incorrectly exposes anonymous content + // https://bugzilla.mozilla.org/show_bug.cgi?id=561664 + try { + // eslint-disable-next-line no-unused-expressions + active.id; + } catch ( e ) { + active = document.body; + } + + element.wrap( wrapper ); + + // Fixes #7595 - Elements lose focus when wrapped. + if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { + $( active ).trigger( "focus" ); + } + + // Hotfix for jQuery 1.4 since some change in wrap() seems to actually + // lose the reference to the wrapped element + wrapper = element.parent(); + + // Transfer positioning properties to the wrapper + if ( element.css( "position" ) === "static" ) { + wrapper.css( { position: "relative" } ); + element.css( { position: "relative" } ); + } else { + $.extend( props, { + position: element.css( "position" ), + zIndex: element.css( "z-index" ) + } ); + $.each( [ "top", "left", "bottom", "right" ], function( i, pos ) { + props[ pos ] = element.css( pos ); + if ( isNaN( parseInt( props[ pos ], 10 ) ) ) { + props[ pos ] = "auto"; + } + } ); + element.css( { + position: "relative", + top: 0, + left: 0, + right: "auto", + bottom: "auto" + } ); + } + element.css( size ); + + return wrapper.css( props ).show(); + }, + + removeWrapper: function( element ) { + var active = document.activeElement; + + if ( element.parent().is( ".ui-effects-wrapper" ) ) { + element.parent().replaceWith( element ); + + // Fixes #7595 - Elements lose focus when wrapped. + if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) { + $( active ).trigger( "focus" ); + } + } + + return element; + } + } ); +} + +$.extend( $.effects, { + version: "1.13.2", + + define: function( name, mode, effect ) { + if ( !effect ) { + effect = mode; + mode = "effect"; + } + + $.effects.effect[ name ] = effect; + $.effects.effect[ name ].mode = mode; + + return effect; + }, + + scaledDimensions: function( element, percent, direction ) { + if ( percent === 0 ) { + return { + height: 0, + width: 0, + outerHeight: 0, + outerWidth: 0 + }; + } + + var x = direction !== "horizontal" ? ( ( percent || 100 ) / 100 ) : 1, + y = direction !== "vertical" ? ( ( percent || 100 ) / 100 ) : 1; + + return { + height: element.height() * y, + width: element.width() * x, + outerHeight: element.outerHeight() * y, + outerWidth: element.outerWidth() * x + }; + + }, + + clipToBox: function( animation ) { + return { + width: animation.clip.right - animation.clip.left, + height: animation.clip.bottom - animation.clip.top, + left: animation.clip.left, + top: animation.clip.top + }; + }, + + // Injects recently queued functions to be first in line (after "inprogress") + unshift: function( element, queueLength, count ) { + var queue = element.queue(); + + if ( queueLength > 1 ) { + queue.splice.apply( queue, + [ 1, 0 ].concat( queue.splice( queueLength, count ) ) ); + } + element.dequeue(); + }, + + saveStyle: function( element ) { + element.data( dataSpaceStyle, element[ 0 ].style.cssText ); + }, + + restoreStyle: function( element ) { + element[ 0 ].style.cssText = element.data( dataSpaceStyle ) || ""; + element.removeData( dataSpaceStyle ); + }, + + mode: function( element, mode ) { + var hidden = element.is( ":hidden" ); + + if ( mode === "toggle" ) { + mode = hidden ? "show" : "hide"; + } + if ( hidden ? mode === "hide" : mode === "show" ) { + mode = "none"; + } + return mode; + }, + + // Translates a [top,left] array into a baseline value + getBaseline: function( origin, original ) { + var y, x; + + switch ( origin[ 0 ] ) { + case "top": + y = 0; + break; + case "middle": + y = 0.5; + break; + case "bottom": + y = 1; + break; + default: + y = origin[ 0 ] / original.height; + } + + switch ( origin[ 1 ] ) { + case "left": + x = 0; + break; + case "center": + x = 0.5; + break; + case "right": + x = 1; + break; + default: + x = origin[ 1 ] / original.width; + } + + return { + x: x, + y: y + }; + }, + + // Creates a placeholder element so that the original element can be made absolute + createPlaceholder: function( element ) { + var placeholder, + cssPosition = element.css( "position" ), + position = element.position(); + + // Lock in margins first to account for form elements, which + // will change margin if you explicitly set height + // see: http://jsfiddle.net/JZSMt/3/ https://bugs.webkit.org/show_bug.cgi?id=107380 + // Support: Safari + element.css( { + marginTop: element.css( "marginTop" ), + marginBottom: element.css( "marginBottom" ), + marginLeft: element.css( "marginLeft" ), + marginRight: element.css( "marginRight" ) + } ) + .outerWidth( element.outerWidth() ) + .outerHeight( element.outerHeight() ); + + if ( /^(static|relative)/.test( cssPosition ) ) { + cssPosition = "absolute"; + + placeholder = $( "<" + element[ 0 ].nodeName + ">" ).insertAfter( element ).css( { + + // Convert inline to inline block to account for inline elements + // that turn to inline block based on content (like img) + display: /^(inline|ruby)/.test( element.css( "display" ) ) ? + "inline-block" : + "block", + visibility: "hidden", + + // Margins need to be set to account for margin collapse + marginTop: element.css( "marginTop" ), + marginBottom: element.css( "marginBottom" ), + marginLeft: element.css( "marginLeft" ), + marginRight: element.css( "marginRight" ), + "float": element.css( "float" ) + } ) + .outerWidth( element.outerWidth() ) + .outerHeight( element.outerHeight() ) + .addClass( "ui-effects-placeholder" ); + + element.data( dataSpace + "placeholder", placeholder ); + } + + element.css( { + position: cssPosition, + left: position.left, + top: position.top + } ); + + return placeholder; + }, + + removePlaceholder: function( element ) { + var dataKey = dataSpace + "placeholder", + placeholder = element.data( dataKey ); + + if ( placeholder ) { + placeholder.remove(); + element.removeData( dataKey ); + } + }, + + // Removes a placeholder if it exists and restores + // properties that were modified during placeholder creation + cleanUp: function( element ) { + $.effects.restoreStyle( element ); + $.effects.removePlaceholder( element ); + }, + + setTransition: function( element, list, factor, value ) { + value = value || {}; + $.each( list, function( i, x ) { + var unit = element.cssUnit( x ); + if ( unit[ 0 ] > 0 ) { + value[ x ] = unit[ 0 ] * factor + unit[ 1 ]; + } + } ); + return value; + } +} ); + +// Return an effect options object for the given parameters: +function _normalizeArguments( effect, options, speed, callback ) { + + // Allow passing all options as the first parameter + if ( $.isPlainObject( effect ) ) { + options = effect; + effect = effect.effect; + } + + // Convert to an object + effect = { effect: effect }; + + // Catch (effect, null, ...) + if ( options == null ) { + options = {}; + } + + // Catch (effect, callback) + if ( typeof options === "function" ) { + callback = options; + speed = null; + options = {}; + } + + // Catch (effect, speed, ?) + if ( typeof options === "number" || $.fx.speeds[ options ] ) { + callback = speed; + speed = options; + options = {}; + } + + // Catch (effect, options, callback) + if ( typeof speed === "function" ) { + callback = speed; + speed = null; + } + + // Add options to effect + if ( options ) { + $.extend( effect, options ); + } + + speed = speed || options.duration; + effect.duration = $.fx.off ? 0 : + typeof speed === "number" ? speed : + speed in $.fx.speeds ? $.fx.speeds[ speed ] : + $.fx.speeds._default; + + effect.complete = callback || options.complete; + + return effect; +} + +function standardAnimationOption( option ) { + + // Valid standard speeds (nothing, number, named speed) + if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) { + return true; + } + + // Invalid strings - treat as "normal" speed + if ( typeof option === "string" && !$.effects.effect[ option ] ) { + return true; + } + + // Complete callback + if ( typeof option === "function" ) { + return true; + } + + // Options hash (but not naming an effect) + if ( typeof option === "object" && !option.effect ) { + return true; + } + + // Didn't match any standard API + return false; +} + +$.fn.extend( { + effect: function( /* effect, options, speed, callback */ ) { + var args = _normalizeArguments.apply( this, arguments ), + effectMethod = $.effects.effect[ args.effect ], + defaultMode = effectMethod.mode, + queue = args.queue, + queueName = queue || "fx", + complete = args.complete, + mode = args.mode, + modes = [], + prefilter = function( next ) { + var el = $( this ), + normalizedMode = $.effects.mode( el, mode ) || defaultMode; + + // Sentinel for duck-punching the :animated pseudo-selector + el.data( dataSpaceAnimated, true ); + + // Save effect mode for later use, + // we can't just call $.effects.mode again later, + // as the .show() below destroys the initial state + modes.push( normalizedMode ); + + // See $.uiBackCompat inside of run() for removal of defaultMode in 1.14 + if ( defaultMode && ( normalizedMode === "show" || + ( normalizedMode === defaultMode && normalizedMode === "hide" ) ) ) { + el.show(); + } + + if ( !defaultMode || normalizedMode !== "none" ) { + $.effects.saveStyle( el ); + } + + if ( typeof next === "function" ) { + next(); + } + }; + + if ( $.fx.off || !effectMethod ) { + + // Delegate to the original method (e.g., .show()) if possible + if ( mode ) { + return this[ mode ]( args.duration, complete ); + } else { + return this.each( function() { + if ( complete ) { + complete.call( this ); + } + } ); + } + } + + function run( next ) { + var elem = $( this ); + + function cleanup() { + elem.removeData( dataSpaceAnimated ); + + $.effects.cleanUp( elem ); + + if ( args.mode === "hide" ) { + elem.hide(); + } + + done(); + } + + function done() { + if ( typeof complete === "function" ) { + complete.call( elem[ 0 ] ); + } + + if ( typeof next === "function" ) { + next(); + } + } + + // Override mode option on a per element basis, + // as toggle can be either show or hide depending on element state + args.mode = modes.shift(); + + if ( $.uiBackCompat !== false && !defaultMode ) { + if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) { + + // Call the core method to track "olddisplay" properly + elem[ mode ](); + done(); + } else { + effectMethod.call( elem[ 0 ], args, done ); + } + } else { + if ( args.mode === "none" ) { + + // Call the core method to track "olddisplay" properly + elem[ mode ](); + done(); + } else { + effectMethod.call( elem[ 0 ], args, cleanup ); + } + } + } + + // Run prefilter on all elements first to ensure that + // any showing or hiding happens before placeholder creation, + // which ensures that any layout changes are correctly captured. + return queue === false ? + this.each( prefilter ).each( run ) : + this.queue( queueName, prefilter ).queue( queueName, run ); + }, + + show: ( function( orig ) { + return function( option ) { + if ( standardAnimationOption( option ) ) { + return orig.apply( this, arguments ); + } else { + var args = _normalizeArguments.apply( this, arguments ); + args.mode = "show"; + return this.effect.call( this, args ); + } + }; + } )( $.fn.show ), + + hide: ( function( orig ) { + return function( option ) { + if ( standardAnimationOption( option ) ) { + return orig.apply( this, arguments ); + } else { + var args = _normalizeArguments.apply( this, arguments ); + args.mode = "hide"; + return this.effect.call( this, args ); + } + }; + } )( $.fn.hide ), + + toggle: ( function( orig ) { + return function( option ) { + if ( standardAnimationOption( option ) || typeof option === "boolean" ) { + return orig.apply( this, arguments ); + } else { + var args = _normalizeArguments.apply( this, arguments ); + args.mode = "toggle"; + return this.effect.call( this, args ); + } + }; + } )( $.fn.toggle ), + + cssUnit: function( key ) { + var style = this.css( key ), + val = []; + + $.each( [ "em", "px", "%", "pt" ], function( i, unit ) { + if ( style.indexOf( unit ) > 0 ) { + val = [ parseFloat( style ), unit ]; + } + } ); + return val; + }, + + cssClip: function( clipObj ) { + if ( clipObj ) { + return this.css( "clip", "rect(" + clipObj.top + "px " + clipObj.right + "px " + + clipObj.bottom + "px " + clipObj.left + "px)" ); + } + return parseClip( this.css( "clip" ), this ); + }, + + transfer: function( options, done ) { + var element = $( this ), + target = $( options.to ), + targetFixed = target.css( "position" ) === "fixed", + body = $( "body" ), + fixTop = targetFixed ? body.scrollTop() : 0, + fixLeft = targetFixed ? body.scrollLeft() : 0, + endPosition = target.offset(), + animation = { + top: endPosition.top - fixTop, + left: endPosition.left - fixLeft, + height: target.innerHeight(), + width: target.innerWidth() + }, + startPosition = element.offset(), + transfer = $( "
    " ); + + transfer + .appendTo( "body" ) + .addClass( options.className ) + .css( { + top: startPosition.top - fixTop, + left: startPosition.left - fixLeft, + height: element.innerHeight(), + width: element.innerWidth(), + position: targetFixed ? "fixed" : "absolute" + } ) + .animate( animation, options.duration, options.easing, function() { + transfer.remove(); + if ( typeof done === "function" ) { + done(); + } + } ); + } +} ); + +function parseClip( str, element ) { + var outerWidth = element.outerWidth(), + outerHeight = element.outerHeight(), + clipRegex = /^rect\((-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto)\)$/, + values = clipRegex.exec( str ) || [ "", 0, outerWidth, outerHeight, 0 ]; + + return { + top: parseFloat( values[ 1 ] ) || 0, + right: values[ 2 ] === "auto" ? outerWidth : parseFloat( values[ 2 ] ), + bottom: values[ 3 ] === "auto" ? outerHeight : parseFloat( values[ 3 ] ), + left: parseFloat( values[ 4 ] ) || 0 + }; +} + +$.fx.step.clip = function( fx ) { + if ( !fx.clipInit ) { + fx.start = $( fx.elem ).cssClip(); + if ( typeof fx.end === "string" ) { + fx.end = parseClip( fx.end, fx.elem ); + } + fx.clipInit = true; + } + + $( fx.elem ).cssClip( { + top: fx.pos * ( fx.end.top - fx.start.top ) + fx.start.top, + right: fx.pos * ( fx.end.right - fx.start.right ) + fx.start.right, + bottom: fx.pos * ( fx.end.bottom - fx.start.bottom ) + fx.start.bottom, + left: fx.pos * ( fx.end.left - fx.start.left ) + fx.start.left + } ); +}; + +} )(); + +/******************************************************************************/ +/*********************************** EASING ***********************************/ +/******************************************************************************/ + +( function() { + +// Based on easing equations from Robert Penner (http://www.robertpenner.com/easing) + +var baseEasings = {}; + +$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) { + baseEasings[ name ] = function( p ) { + return Math.pow( p, i + 2 ); + }; +} ); + +$.extend( baseEasings, { + Sine: function( p ) { + return 1 - Math.cos( p * Math.PI / 2 ); + }, + Circ: function( p ) { + return 1 - Math.sqrt( 1 - p * p ); + }, + Elastic: function( p ) { + return p === 0 || p === 1 ? p : + -Math.pow( 2, 8 * ( p - 1 ) ) * Math.sin( ( ( p - 1 ) * 80 - 7.5 ) * Math.PI / 15 ); + }, + Back: function( p ) { + return p * p * ( 3 * p - 2 ); + }, + Bounce: function( p ) { + var pow2, + bounce = 4; + + while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {} + return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 ); + } +} ); + +$.each( baseEasings, function( name, easeIn ) { + $.easing[ "easeIn" + name ] = easeIn; + $.easing[ "easeOut" + name ] = function( p ) { + return 1 - easeIn( 1 - p ); + }; + $.easing[ "easeInOut" + name ] = function( p ) { + return p < 0.5 ? + easeIn( p * 2 ) / 2 : + 1 - easeIn( p * -2 + 2 ) / 2; + }; +} ); + +} )(); + +var effect = $.effects; + + +/*! + * jQuery UI Effects Blind 1.13.2 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Blind Effect +//>>group: Effects +//>>description: Blinds the element. +//>>docs: http://api.jqueryui.com/blind-effect/ +//>>demos: http://jqueryui.com/effect/ + + +var effectsEffectBlind = $.effects.define( "blind", "hide", function( options, done ) { + var map = { + up: [ "bottom", "top" ], + vertical: [ "bottom", "top" ], + down: [ "top", "bottom" ], + left: [ "right", "left" ], + horizontal: [ "right", "left" ], + right: [ "left", "right" ] + }, + element = $( this ), + direction = options.direction || "up", + start = element.cssClip(), + animate = { clip: $.extend( {}, start ) }, + placeholder = $.effects.createPlaceholder( element ); + + animate.clip[ map[ direction ][ 0 ] ] = animate.clip[ map[ direction ][ 1 ] ]; + + if ( options.mode === "show" ) { + element.cssClip( animate.clip ); + if ( placeholder ) { + placeholder.css( $.effects.clipToBox( animate ) ); + } + + animate.clip = start; + } + + if ( placeholder ) { + placeholder.animate( $.effects.clipToBox( animate ), options.duration, options.easing ); + } + + element.animate( animate, { + queue: false, + duration: options.duration, + easing: options.easing, + complete: done + } ); +} ); + + +/*! + * jQuery UI Effects Bounce 1.13.2 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Bounce Effect +//>>group: Effects +//>>description: Bounces an element horizontally or vertically n times. +//>>docs: http://api.jqueryui.com/bounce-effect/ +//>>demos: http://jqueryui.com/effect/ + + +var effectsEffectBounce = $.effects.define( "bounce", function( options, done ) { + var upAnim, downAnim, refValue, + element = $( this ), + + // Defaults: + mode = options.mode, + hide = mode === "hide", + show = mode === "show", + direction = options.direction || "up", + distance = options.distance, + times = options.times || 5, + + // Number of internal animations + anims = times * 2 + ( show || hide ? 1 : 0 ), + speed = options.duration / anims, + easing = options.easing, + + // Utility: + ref = ( direction === "up" || direction === "down" ) ? "top" : "left", + motion = ( direction === "up" || direction === "left" ), + i = 0, + + queuelen = element.queue().length; + + $.effects.createPlaceholder( element ); + + refValue = element.css( ref ); + + // Default distance for the BIGGEST bounce is the outer Distance / 3 + if ( !distance ) { + distance = element[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3; + } + + if ( show ) { + downAnim = { opacity: 1 }; + downAnim[ ref ] = refValue; + + // If we are showing, force opacity 0 and set the initial position + // then do the "first" animation + element + .css( "opacity", 0 ) + .css( ref, motion ? -distance * 2 : distance * 2 ) + .animate( downAnim, speed, easing ); + } + + // Start at the smallest distance if we are hiding + if ( hide ) { + distance = distance / Math.pow( 2, times - 1 ); + } + + downAnim = {}; + downAnim[ ref ] = refValue; + + // Bounces up/down/left/right then back to 0 -- times * 2 animations happen here + for ( ; i < times; i++ ) { + upAnim = {}; + upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; + + element + .animate( upAnim, speed, easing ) + .animate( downAnim, speed, easing ); + + distance = hide ? distance * 2 : distance / 2; + } + + // Last Bounce when Hiding + if ( hide ) { + upAnim = { opacity: 0 }; + upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance; + + element.animate( upAnim, speed, easing ); + } + + element.queue( done ); + + $.effects.unshift( element, queuelen, anims + 1 ); +} ); + + +/*! + * jQuery UI Effects Clip 1.13.2 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Clip Effect +//>>group: Effects +//>>description: Clips the element on and off like an old TV. +//>>docs: http://api.jqueryui.com/clip-effect/ +//>>demos: http://jqueryui.com/effect/ + + +var effectsEffectClip = $.effects.define( "clip", "hide", function( options, done ) { + var start, + animate = {}, + element = $( this ), + direction = options.direction || "vertical", + both = direction === "both", + horizontal = both || direction === "horizontal", + vertical = both || direction === "vertical"; + + start = element.cssClip(); + animate.clip = { + top: vertical ? ( start.bottom - start.top ) / 2 : start.top, + right: horizontal ? ( start.right - start.left ) / 2 : start.right, + bottom: vertical ? ( start.bottom - start.top ) / 2 : start.bottom, + left: horizontal ? ( start.right - start.left ) / 2 : start.left + }; + + $.effects.createPlaceholder( element ); + + if ( options.mode === "show" ) { + element.cssClip( animate.clip ); + animate.clip = start; + } + + element.animate( animate, { + queue: false, + duration: options.duration, + easing: options.easing, + complete: done + } ); + +} ); + + +/*! + * jQuery UI Effects Drop 1.13.2 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Drop Effect +//>>group: Effects +//>>description: Moves an element in one direction and hides it at the same time. +//>>docs: http://api.jqueryui.com/drop-effect/ +//>>demos: http://jqueryui.com/effect/ + + +var effectsEffectDrop = $.effects.define( "drop", "hide", function( options, done ) { + + var distance, + element = $( this ), + mode = options.mode, + show = mode === "show", + direction = options.direction || "left", + ref = ( direction === "up" || direction === "down" ) ? "top" : "left", + motion = ( direction === "up" || direction === "left" ) ? "-=" : "+=", + oppositeMotion = ( motion === "+=" ) ? "-=" : "+=", + animation = { + opacity: 0 + }; + + $.effects.createPlaceholder( element ); + + distance = options.distance || + element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ) / 2; + + animation[ ref ] = motion + distance; + + if ( show ) { + element.css( animation ); + + animation[ ref ] = oppositeMotion + distance; + animation.opacity = 1; + } + + // Animate + element.animate( animation, { + queue: false, + duration: options.duration, + easing: options.easing, + complete: done + } ); +} ); + + +/*! + * jQuery UI Effects Explode 1.13.2 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Explode Effect +//>>group: Effects +/* eslint-disable max-len */ +//>>description: Explodes an element in all directions into n pieces. Implodes an element to its original wholeness. +/* eslint-enable max-len */ +//>>docs: http://api.jqueryui.com/explode-effect/ +//>>demos: http://jqueryui.com/effect/ + + +var effectsEffectExplode = $.effects.define( "explode", "hide", function( options, done ) { + + var i, j, left, top, mx, my, + rows = options.pieces ? Math.round( Math.sqrt( options.pieces ) ) : 3, + cells = rows, + element = $( this ), + mode = options.mode, + show = mode === "show", + + // Show and then visibility:hidden the element before calculating offset + offset = element.show().css( "visibility", "hidden" ).offset(), + + // Width and height of a piece + width = Math.ceil( element.outerWidth() / cells ), + height = Math.ceil( element.outerHeight() / rows ), + pieces = []; + + // Children animate complete: + function childComplete() { + pieces.push( this ); + if ( pieces.length === rows * cells ) { + animComplete(); + } + } + + // Clone the element for each row and cell. + for ( i = 0; i < rows; i++ ) { // ===> + top = offset.top + i * height; + my = i - ( rows - 1 ) / 2; + + for ( j = 0; j < cells; j++ ) { // ||| + left = offset.left + j * width; + mx = j - ( cells - 1 ) / 2; + + // Create a clone of the now hidden main element that will be absolute positioned + // within a wrapper div off the -left and -top equal to size of our pieces + element + .clone() + .appendTo( "body" ) + .wrap( "
    " ) + .css( { + position: "absolute", + visibility: "visible", + left: -j * width, + top: -i * height + } ) + + // Select the wrapper - make it overflow: hidden and absolute positioned based on + // where the original was located +left and +top equal to the size of pieces + .parent() + .addClass( "ui-effects-explode" ) + .css( { + position: "absolute", + overflow: "hidden", + width: width, + height: height, + left: left + ( show ? mx * width : 0 ), + top: top + ( show ? my * height : 0 ), + opacity: show ? 0 : 1 + } ) + .animate( { + left: left + ( show ? 0 : mx * width ), + top: top + ( show ? 0 : my * height ), + opacity: show ? 1 : 0 + }, options.duration || 500, options.easing, childComplete ); + } + } + + function animComplete() { + element.css( { + visibility: "visible" + } ); + $( pieces ).remove(); + done(); + } +} ); + + +/*! + * jQuery UI Effects Fade 1.13.2 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Fade Effect +//>>group: Effects +//>>description: Fades the element. +//>>docs: http://api.jqueryui.com/fade-effect/ +//>>demos: http://jqueryui.com/effect/ + + +var effectsEffectFade = $.effects.define( "fade", "toggle", function( options, done ) { + var show = options.mode === "show"; + + $( this ) + .css( "opacity", show ? 0 : 1 ) + .animate( { + opacity: show ? 1 : 0 + }, { + queue: false, + duration: options.duration, + easing: options.easing, + complete: done + } ); +} ); + + +/*! + * jQuery UI Effects Fold 1.13.2 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Fold Effect +//>>group: Effects +//>>description: Folds an element first horizontally and then vertically. +//>>docs: http://api.jqueryui.com/fold-effect/ +//>>demos: http://jqueryui.com/effect/ + + +var effectsEffectFold = $.effects.define( "fold", "hide", function( options, done ) { + + // Create element + var element = $( this ), + mode = options.mode, + show = mode === "show", + hide = mode === "hide", + size = options.size || 15, + percent = /([0-9]+)%/.exec( size ), + horizFirst = !!options.horizFirst, + ref = horizFirst ? [ "right", "bottom" ] : [ "bottom", "right" ], + duration = options.duration / 2, + + placeholder = $.effects.createPlaceholder( element ), + + start = element.cssClip(), + animation1 = { clip: $.extend( {}, start ) }, + animation2 = { clip: $.extend( {}, start ) }, + + distance = [ start[ ref[ 0 ] ], start[ ref[ 1 ] ] ], + + queuelen = element.queue().length; + + if ( percent ) { + size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ]; + } + animation1.clip[ ref[ 0 ] ] = size; + animation2.clip[ ref[ 0 ] ] = size; + animation2.clip[ ref[ 1 ] ] = 0; + + if ( show ) { + element.cssClip( animation2.clip ); + if ( placeholder ) { + placeholder.css( $.effects.clipToBox( animation2 ) ); + } + + animation2.clip = start; + } + + // Animate + element + .queue( function( next ) { + if ( placeholder ) { + placeholder + .animate( $.effects.clipToBox( animation1 ), duration, options.easing ) + .animate( $.effects.clipToBox( animation2 ), duration, options.easing ); + } + + next(); + } ) + .animate( animation1, duration, options.easing ) + .animate( animation2, duration, options.easing ) + .queue( done ); + + $.effects.unshift( element, queuelen, 4 ); +} ); + + +/*! + * jQuery UI Effects Highlight 1.13.2 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Highlight Effect +//>>group: Effects +//>>description: Highlights the background of an element in a defined color for a custom duration. +//>>docs: http://api.jqueryui.com/highlight-effect/ +//>>demos: http://jqueryui.com/effect/ + + +var effectsEffectHighlight = $.effects.define( "highlight", "show", function( options, done ) { + var element = $( this ), + animation = { + backgroundColor: element.css( "backgroundColor" ) + }; + + if ( options.mode === "hide" ) { + animation.opacity = 0; + } + + $.effects.saveStyle( element ); + + element + .css( { + backgroundImage: "none", + backgroundColor: options.color || "#ffff99" + } ) + .animate( animation, { + queue: false, + duration: options.duration, + easing: options.easing, + complete: done + } ); +} ); + + +/*! + * jQuery UI Effects Size 1.13.2 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Size Effect +//>>group: Effects +//>>description: Resize an element to a specified width and height. +//>>docs: http://api.jqueryui.com/size-effect/ +//>>demos: http://jqueryui.com/effect/ + + +var effectsEffectSize = $.effects.define( "size", function( options, done ) { + + // Create element + var baseline, factor, temp, + element = $( this ), + + // Copy for children + cProps = [ "fontSize" ], + vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ], + hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ], + + // Set options + mode = options.mode, + restore = mode !== "effect", + scale = options.scale || "both", + origin = options.origin || [ "middle", "center" ], + position = element.css( "position" ), + pos = element.position(), + original = $.effects.scaledDimensions( element ), + from = options.from || original, + to = options.to || $.effects.scaledDimensions( element, 0 ); + + $.effects.createPlaceholder( element ); + + if ( mode === "show" ) { + temp = from; + from = to; + to = temp; + } + + // Set scaling factor + factor = { + from: { + y: from.height / original.height, + x: from.width / original.width + }, + to: { + y: to.height / original.height, + x: to.width / original.width + } + }; + + // Scale the css box + if ( scale === "box" || scale === "both" ) { + + // Vertical props scaling + if ( factor.from.y !== factor.to.y ) { + from = $.effects.setTransition( element, vProps, factor.from.y, from ); + to = $.effects.setTransition( element, vProps, factor.to.y, to ); + } + + // Horizontal props scaling + if ( factor.from.x !== factor.to.x ) { + from = $.effects.setTransition( element, hProps, factor.from.x, from ); + to = $.effects.setTransition( element, hProps, factor.to.x, to ); + } + } + + // Scale the content + if ( scale === "content" || scale === "both" ) { + + // Vertical props scaling + if ( factor.from.y !== factor.to.y ) { + from = $.effects.setTransition( element, cProps, factor.from.y, from ); + to = $.effects.setTransition( element, cProps, factor.to.y, to ); + } + } + + // Adjust the position properties based on the provided origin points + if ( origin ) { + baseline = $.effects.getBaseline( origin, original ); + from.top = ( original.outerHeight - from.outerHeight ) * baseline.y + pos.top; + from.left = ( original.outerWidth - from.outerWidth ) * baseline.x + pos.left; + to.top = ( original.outerHeight - to.outerHeight ) * baseline.y + pos.top; + to.left = ( original.outerWidth - to.outerWidth ) * baseline.x + pos.left; + } + delete from.outerHeight; + delete from.outerWidth; + element.css( from ); + + // Animate the children if desired + if ( scale === "content" || scale === "both" ) { + + vProps = vProps.concat( [ "marginTop", "marginBottom" ] ).concat( cProps ); + hProps = hProps.concat( [ "marginLeft", "marginRight" ] ); + + // Only animate children with width attributes specified + // TODO: is this right? should we include anything with css width specified as well + element.find( "*[width]" ).each( function() { + var child = $( this ), + childOriginal = $.effects.scaledDimensions( child ), + childFrom = { + height: childOriginal.height * factor.from.y, + width: childOriginal.width * factor.from.x, + outerHeight: childOriginal.outerHeight * factor.from.y, + outerWidth: childOriginal.outerWidth * factor.from.x + }, + childTo = { + height: childOriginal.height * factor.to.y, + width: childOriginal.width * factor.to.x, + outerHeight: childOriginal.height * factor.to.y, + outerWidth: childOriginal.width * factor.to.x + }; + + // Vertical props scaling + if ( factor.from.y !== factor.to.y ) { + childFrom = $.effects.setTransition( child, vProps, factor.from.y, childFrom ); + childTo = $.effects.setTransition( child, vProps, factor.to.y, childTo ); + } + + // Horizontal props scaling + if ( factor.from.x !== factor.to.x ) { + childFrom = $.effects.setTransition( child, hProps, factor.from.x, childFrom ); + childTo = $.effects.setTransition( child, hProps, factor.to.x, childTo ); + } + + if ( restore ) { + $.effects.saveStyle( child ); + } + + // Animate children + child.css( childFrom ); + child.animate( childTo, options.duration, options.easing, function() { + + // Restore children + if ( restore ) { + $.effects.restoreStyle( child ); + } + } ); + } ); + } + + // Animate + element.animate( to, { + queue: false, + duration: options.duration, + easing: options.easing, + complete: function() { + + var offset = element.offset(); + + if ( to.opacity === 0 ) { + element.css( "opacity", from.opacity ); + } + + if ( !restore ) { + element + .css( "position", position === "static" ? "relative" : position ) + .offset( offset ); + + // Need to save style here so that automatic style restoration + // doesn't restore to the original styles from before the animation. + $.effects.saveStyle( element ); + } + + done(); + } + } ); + +} ); + + +/*! + * jQuery UI Effects Scale 1.13.2 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Scale Effect +//>>group: Effects +//>>description: Grows or shrinks an element and its content. +//>>docs: http://api.jqueryui.com/scale-effect/ +//>>demos: http://jqueryui.com/effect/ + + +var effectsEffectScale = $.effects.define( "scale", function( options, done ) { + + // Create element + var el = $( this ), + mode = options.mode, + percent = parseInt( options.percent, 10 ) || + ( parseInt( options.percent, 10 ) === 0 ? 0 : ( mode !== "effect" ? 0 : 100 ) ), + + newOptions = $.extend( true, { + from: $.effects.scaledDimensions( el ), + to: $.effects.scaledDimensions( el, percent, options.direction || "both" ), + origin: options.origin || [ "middle", "center" ] + }, options ); + + // Fade option to support puff + if ( options.fade ) { + newOptions.from.opacity = 1; + newOptions.to.opacity = 0; + } + + $.effects.effect.size.call( this, newOptions, done ); +} ); + + +/*! + * jQuery UI Effects Puff 1.13.2 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Puff Effect +//>>group: Effects +//>>description: Creates a puff effect by scaling the element up and hiding it at the same time. +//>>docs: http://api.jqueryui.com/puff-effect/ +//>>demos: http://jqueryui.com/effect/ + + +var effectsEffectPuff = $.effects.define( "puff", "hide", function( options, done ) { + var newOptions = $.extend( true, {}, options, { + fade: true, + percent: parseInt( options.percent, 10 ) || 150 + } ); + + $.effects.effect.scale.call( this, newOptions, done ); +} ); + + +/*! + * jQuery UI Effects Pulsate 1.13.2 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Pulsate Effect +//>>group: Effects +//>>description: Pulsates an element n times by changing the opacity to zero and back. +//>>docs: http://api.jqueryui.com/pulsate-effect/ +//>>demos: http://jqueryui.com/effect/ + + +var effectsEffectPulsate = $.effects.define( "pulsate", "show", function( options, done ) { + var element = $( this ), + mode = options.mode, + show = mode === "show", + hide = mode === "hide", + showhide = show || hide, + + // Showing or hiding leaves off the "last" animation + anims = ( ( options.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ), + duration = options.duration / anims, + animateTo = 0, + i = 1, + queuelen = element.queue().length; + + if ( show || !element.is( ":visible" ) ) { + element.css( "opacity", 0 ).show(); + animateTo = 1; + } + + // Anims - 1 opacity "toggles" + for ( ; i < anims; i++ ) { + element.animate( { opacity: animateTo }, duration, options.easing ); + animateTo = 1 - animateTo; + } + + element.animate( { opacity: animateTo }, duration, options.easing ); + + element.queue( done ); + + $.effects.unshift( element, queuelen, anims + 1 ); +} ); + + +/*! + * jQuery UI Effects Shake 1.13.2 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Shake Effect +//>>group: Effects +//>>description: Shakes an element horizontally or vertically n times. +//>>docs: http://api.jqueryui.com/shake-effect/ +//>>demos: http://jqueryui.com/effect/ + + +var effectsEffectShake = $.effects.define( "shake", function( options, done ) { + + var i = 1, + element = $( this ), + direction = options.direction || "left", + distance = options.distance || 20, + times = options.times || 3, + anims = times * 2 + 1, + speed = Math.round( options.duration / anims ), + ref = ( direction === "up" || direction === "down" ) ? "top" : "left", + positiveMotion = ( direction === "up" || direction === "left" ), + animation = {}, + animation1 = {}, + animation2 = {}, + + queuelen = element.queue().length; + + $.effects.createPlaceholder( element ); + + // Animation + animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance; + animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2; + animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2; + + // Animate + element.animate( animation, speed, options.easing ); + + // Shakes + for ( ; i < times; i++ ) { + element + .animate( animation1, speed, options.easing ) + .animate( animation2, speed, options.easing ); + } + + element + .animate( animation1, speed, options.easing ) + .animate( animation, speed / 2, options.easing ) + .queue( done ); + + $.effects.unshift( element, queuelen, anims + 1 ); +} ); + + +/*! + * jQuery UI Effects Slide 1.13.2 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Slide Effect +//>>group: Effects +//>>description: Slides an element in and out of the viewport. +//>>docs: http://api.jqueryui.com/slide-effect/ +//>>demos: http://jqueryui.com/effect/ + + +var effectsEffectSlide = $.effects.define( "slide", "show", function( options, done ) { + var startClip, startRef, + element = $( this ), + map = { + up: [ "bottom", "top" ], + down: [ "top", "bottom" ], + left: [ "right", "left" ], + right: [ "left", "right" ] + }, + mode = options.mode, + direction = options.direction || "left", + ref = ( direction === "up" || direction === "down" ) ? "top" : "left", + positiveMotion = ( direction === "up" || direction === "left" ), + distance = options.distance || + element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ), + animation = {}; + + $.effects.createPlaceholder( element ); + + startClip = element.cssClip(); + startRef = element.position()[ ref ]; + + // Define hide animation + animation[ ref ] = ( positiveMotion ? -1 : 1 ) * distance + startRef; + animation.clip = element.cssClip(); + animation.clip[ map[ direction ][ 1 ] ] = animation.clip[ map[ direction ][ 0 ] ]; + + // Reverse the animation if we're showing + if ( mode === "show" ) { + element.cssClip( animation.clip ); + element.css( ref, animation[ ref ] ); + animation.clip = startClip; + animation[ ref ] = startRef; + } + + // Actually animate + element.animate( animation, { + queue: false, + duration: options.duration, + easing: options.easing, + complete: done + } ); +} ); + + +/*! + * jQuery UI Effects Transfer 1.13.2 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Transfer Effect +//>>group: Effects +//>>description: Displays a transfer effect from one element to another. +//>>docs: http://api.jqueryui.com/transfer-effect/ +//>>demos: http://jqueryui.com/effect/ + + +var effect; +if ( $.uiBackCompat !== false ) { + effect = $.effects.define( "transfer", function( options, done ) { + $( this ).transfer( options, done ); + } ); +} +var effectsEffectTransfer = effect; + + +/*! + * jQuery UI Focusable 1.13.2 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: :focusable Selector +//>>group: Core +//>>description: Selects elements which can be focused. +//>>docs: http://api.jqueryui.com/focusable-selector/ + + +// Selectors +$.ui.focusable = function( element, hasTabindex ) { + var map, mapName, img, focusableIfVisible, fieldset, + nodeName = element.nodeName.toLowerCase(); + + if ( "area" === nodeName ) { + map = element.parentNode; + mapName = map.name; + if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) { + return false; + } + img = $( "img[usemap='#" + mapName + "']" ); + return img.length > 0 && img.is( ":visible" ); + } + + if ( /^(input|select|textarea|button|object)$/.test( nodeName ) ) { + focusableIfVisible = !element.disabled; + + if ( focusableIfVisible ) { + + // Form controls within a disabled fieldset are disabled. + // However, controls within the fieldset's legend do not get disabled. + // Since controls generally aren't placed inside legends, we skip + // this portion of the check. + fieldset = $( element ).closest( "fieldset" )[ 0 ]; + if ( fieldset ) { + focusableIfVisible = !fieldset.disabled; + } + } + } else if ( "a" === nodeName ) { + focusableIfVisible = element.href || hasTabindex; + } else { + focusableIfVisible = hasTabindex; + } + + return focusableIfVisible && $( element ).is( ":visible" ) && visible( $( element ) ); +}; + +// Support: IE 8 only +// IE 8 doesn't resolve inherit to visible/hidden for computed values +function visible( element ) { + var visibility = element.css( "visibility" ); + while ( visibility === "inherit" ) { + element = element.parent(); + visibility = element.css( "visibility" ); + } + return visibility === "visible"; +} + +$.extend( $.expr.pseudos, { + focusable: function( element ) { + return $.ui.focusable( element, $.attr( element, "tabindex" ) != null ); + } +} ); + +var focusable = $.ui.focusable; + + + +// Support: IE8 Only +// IE8 does not support the form attribute and when it is supplied. It overwrites the form prop +// with a string, so we need to find the proper form. +var form = $.fn._form = function() { + return typeof this[ 0 ].form === "string" ? this.closest( "form" ) : $( this[ 0 ].form ); +}; + + +/*! + * jQuery UI Form Reset Mixin 1.13.2 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Form Reset Mixin +//>>group: Core +//>>description: Refresh input widgets when their form is reset +//>>docs: http://api.jqueryui.com/form-reset-mixin/ + + +var formResetMixin = $.ui.formResetMixin = { + _formResetHandler: function() { + var form = $( this ); + + // Wait for the form reset to actually happen before refreshing + setTimeout( function() { + var instances = form.data( "ui-form-reset-instances" ); + $.each( instances, function() { + this.refresh(); + } ); + } ); + }, + + _bindFormResetHandler: function() { + this.form = this.element._form(); + if ( !this.form.length ) { + return; + } + + var instances = this.form.data( "ui-form-reset-instances" ) || []; + if ( !instances.length ) { + + // We don't use _on() here because we use a single event handler per form + this.form.on( "reset.ui-form-reset", this._formResetHandler ); + } + instances.push( this ); + this.form.data( "ui-form-reset-instances", instances ); + }, + + _unbindFormResetHandler: function() { + if ( !this.form.length ) { + return; + } + + var instances = this.form.data( "ui-form-reset-instances" ); + instances.splice( $.inArray( this, instances ), 1 ); + if ( instances.length ) { + this.form.data( "ui-form-reset-instances", instances ); + } else { + this.form + .removeData( "ui-form-reset-instances" ) + .off( "reset.ui-form-reset" ); + } + } +}; + + +/*! + * jQuery UI Support for jQuery core 1.8.x and newer 1.13.2 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + * + */ + +//>>label: jQuery 1.8+ Support +//>>group: Core +//>>description: Support version 1.8.x and newer of jQuery core + + +// Support: jQuery 1.9.x or older +// $.expr[ ":" ] is deprecated. +if ( !$.expr.pseudos ) { + $.expr.pseudos = $.expr[ ":" ]; +} + +// Support: jQuery 1.11.x or older +// $.unique has been renamed to $.uniqueSort +if ( !$.uniqueSort ) { + $.uniqueSort = $.unique; +} + +// Support: jQuery 2.2.x or older. +// This method has been defined in jQuery 3.0.0. +// Code from https://github.com/jquery/jquery/blob/e539bac79e666bba95bba86d690b4e609dca2286/src/selector/escapeSelector.js +if ( !$.escapeSelector ) { + + // CSS string/identifier serialization + // https://drafts.csswg.org/cssom/#common-serializing-idioms + var rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g; + + var fcssescape = function( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; + }; + + $.escapeSelector = function( sel ) { + return ( sel + "" ).replace( rcssescape, fcssescape ); + }; +} + +// Support: jQuery 3.4.x or older +// These methods have been defined in jQuery 3.5.0. +if ( !$.fn.even || !$.fn.odd ) { + $.fn.extend( { + even: function() { + return this.filter( function( i ) { + return i % 2 === 0; + } ); + }, + odd: function() { + return this.filter( function( i ) { + return i % 2 === 1; + } ); + } + } ); +} + +; +/*! + * jQuery UI Keycode 1.13.2 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Keycode +//>>group: Core +//>>description: Provide keycodes as keynames +//>>docs: http://api.jqueryui.com/jQuery.ui.keyCode/ + + +var keycode = $.ui.keyCode = { + BACKSPACE: 8, + COMMA: 188, + DELETE: 46, + DOWN: 40, + END: 35, + ENTER: 13, + ESCAPE: 27, + HOME: 36, + LEFT: 37, + PAGE_DOWN: 34, + PAGE_UP: 33, + PERIOD: 190, + RIGHT: 39, + SPACE: 32, + TAB: 9, + UP: 38 +}; + + +/*! + * jQuery UI Labels 1.13.2 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: labels +//>>group: Core +//>>description: Find all the labels associated with a given input +//>>docs: http://api.jqueryui.com/labels/ + + +var labels = $.fn.labels = function() { + var ancestor, selector, id, labels, ancestors; + + if ( !this.length ) { + return this.pushStack( [] ); + } + + // Check control.labels first + if ( this[ 0 ].labels && this[ 0 ].labels.length ) { + return this.pushStack( this[ 0 ].labels ); + } + + // Support: IE <= 11, FF <= 37, Android <= 2.3 only + // Above browsers do not support control.labels. Everything below is to support them + // as well as document fragments. control.labels does not work on document fragments + labels = this.eq( 0 ).parents( "label" ); + + // Look for the label based on the id + id = this.attr( "id" ); + if ( id ) { + + // We don't search against the document in case the element + // is disconnected from the DOM + ancestor = this.eq( 0 ).parents().last(); + + // Get a full set of top level ancestors + ancestors = ancestor.add( ancestor.length ? ancestor.siblings() : this.siblings() ); + + // Create a selector for the label based on the id + selector = "label[for='" + $.escapeSelector( id ) + "']"; + + labels = labels.add( ancestors.find( selector ).addBack( selector ) ); + + } + + // Return whatever we have found for labels + return this.pushStack( labels ); +}; + + +/*! + * jQuery UI Scroll Parent 1.13.2 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: scrollParent +//>>group: Core +//>>description: Get the closest ancestor element that is scrollable. +//>>docs: http://api.jqueryui.com/scrollParent/ + + +var scrollParent = $.fn.scrollParent = function( includeHidden ) { + var position = this.css( "position" ), + excludeStaticParent = position === "absolute", + overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/, + scrollParent = this.parents().filter( function() { + var parent = $( this ); + if ( excludeStaticParent && parent.css( "position" ) === "static" ) { + return false; + } + return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) + + parent.css( "overflow-x" ) ); + } ).eq( 0 ); + + return position === "fixed" || !scrollParent.length ? + $( this[ 0 ].ownerDocument || document ) : + scrollParent; +}; + + +/*! + * jQuery UI Tabbable 1.13.2 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: :tabbable Selector +//>>group: Core +//>>description: Selects elements which can be tabbed to. +//>>docs: http://api.jqueryui.com/tabbable-selector/ + + +var tabbable = $.extend( $.expr.pseudos, { + tabbable: function( element ) { + var tabIndex = $.attr( element, "tabindex" ), + hasTabindex = tabIndex != null; + return ( !hasTabindex || tabIndex >= 0 ) && $.ui.focusable( element, hasTabindex ); + } +} ); + + +/*! + * jQuery UI Unique ID 1.13.2 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: uniqueId +//>>group: Core +//>>description: Functions to generate and remove uniqueId's +//>>docs: http://api.jqueryui.com/uniqueId/ + + +var uniqueId = $.fn.extend( { + uniqueId: ( function() { + var uuid = 0; + + return function() { + return this.each( function() { + if ( !this.id ) { + this.id = "ui-id-" + ( ++uuid ); + } + } ); + }; + } )(), + + removeUniqueId: function() { + return this.each( function() { + if ( /^ui-id-\d+$/.test( this.id ) ) { + $( this ).removeAttr( "id" ); + } + } ); + } +} ); + + +/*! + * jQuery UI Accordion 1.13.2 + * http://jqueryui.com + * + * Copyright jQuery Foundation and other contributors + * Released under the MIT license. + * http://jquery.org/license + */ + +//>>label: Accordion +//>>group: Widgets +/* eslint-disable max-len */ +//>>description: Displays collapsible content panels for presenting information in a limited amount of space. +/* eslint-enable max-len */ +//>>docs: http://api.jqueryui.com/accordion/ +//>>demos: http://jqueryui.com/accordion/ +//>>css.structure: ../../themes/base/core.css +//>>css.structure: ../../themes/base/accordion.css +//>>css.theme: ../../themes/base/theme.css + + +var widgetsAccordion = $.widget( "ui.accordion", { + version: "1.13.2", + options: { + active: 0, + animate: {}, + classes: { + "ui-accordion-header": "ui-corner-top", + "ui-accordion-header-collapsed": "ui-corner-all", + "ui-accordion-content": "ui-corner-bottom" + }, + collapsible: false, + event: "click", + header: function( elem ) { + return elem.find( "> li > :first-child" ).add( elem.find( "> :not(li)" ).even() ); + }, + heightStyle: "auto", + icons: { + activeHeader: "ui-icon-triangle-1-s", + header: "ui-icon-triangle-1-e" + }, + + // Callbacks + activate: null, + beforeActivate: null + }, + + hideProps: { + borderTopWidth: "hide", + borderBottomWidth: "hide", + paddingTop: "hide", + paddingBottom: "hide", + height: "hide" + }, + + showProps: { + borderTopWidth: "show", + borderBottomWidth: "show", + paddingTop: "show", + paddingBottom: "show", + height: "show" + }, + + _create: function() { + var options = this.options; + + this.prevShow = this.prevHide = $(); + this._addClass( "ui-accordion", "ui-widget ui-helper-reset" ); + this.element.attr( "role", "tablist" ); + + // Don't allow collapsible: false and active: false / null + if ( !options.collapsible && ( options.active === false || options.active == null ) ) { + options.active = 0; + } + + this._processPanels(); + + // handle negative values + if ( options.active < 0 ) { + options.active += this.headers.length; + } + this._refresh(); + }, + + _getCreateEventData: function() { + return { + header: this.active, + panel: !this.active.length ? $() : this.active.next() + }; + }, + + _createIcons: function() { + var icon, children, + icons = this.options.icons; + + if ( icons ) { + icon = $( "" ); + this._addClass( icon, "ui-accordion-header-icon", "ui-icon " + icons.header ); + icon.prependTo( this.headers ); + children = this.active.children( ".ui-accordion-header-icon" ); + this._removeClass( children, icons.header ) + ._addClass( children, null, icons.activeHeader ) + ._addClass( this.headers, "ui-accordion-icons" ); + } + }, + + _destroyIcons: function() { + this._removeClass( this.headers, "ui-accordion-icons" ); + this.headers.children( ".ui-accordion-header-icon" ).remove(); + }, + + _destroy: function() { + var contents; + + // Clean up main element + this.element.removeAttr( "role" ); + + // Clean up headers + this.headers + .removeAttr( "role aria-expanded aria-selected aria-controls tabIndex" ) + .removeUniqueId(); + + this._destroyIcons(); + + // Clean up content panels + contents = this.headers.next() + .css( "display", "" ) + .removeAttr( "role aria-hidden aria-labelledby" ) + .removeUniqueId(); + + if ( this.options.heightStyle !== "content" ) { + contents.css( "height", "" ); + } + }, + + _setOption: function( key, value ) { + if ( key === "active" ) { + + // _activate() will handle invalid values and update this.options + this._activate( value ); + return; + } + + if ( key === "event" ) { + if ( this.options.event ) { + this._off( this.headers, this.options.event ); + } + this._setupEvents( value ); + } + + this._super( key, value ); + + // Setting collapsible: false while collapsed; open first panel + if ( key === "collapsible" && !value && this.options.active === false ) { + this._activate( 0 ); + } + + if ( key === "icons" ) { + this._destroyIcons(); + if ( value ) { + this._createIcons(); + } + } + }, + + _setOptionDisabled: function( value ) { + this._super( value ); + + this.element.attr( "aria-disabled", value ); + + // Support: IE8 Only + // #5332 / #6059 - opacity doesn't cascade to positioned elements in IE + // so we need to add the disabled class to the headers and panels + this._toggleClass( null, "ui-state-disabled", !!value ); + this._toggleClass( this.headers.add( this.headers.next() ), null, "ui-state-disabled", + !!value ); + }, + + _keydown: function( event ) { + if ( event.altKey || event.ctrlKey ) { + return; + } + + var keyCode = $.ui.keyCode, + length = this.headers.length, + currentIndex = this.headers.index( event.target ), + toFocus = false; + + switch ( event.keyCode ) { + case keyCode.RIGHT: + case keyCode.DOWN: + toFocus = this.headers[ ( currentIndex + 1 ) % length ]; + break; + case keyCode.LEFT: + case keyCode.UP: + toFocus = this.headers[ ( currentIndex - 1 + length ) % length ]; + break; + case keyCode.SPACE: + case keyCode.ENTER: + this._eventHandler( event ); + break; + case keyCode.HOME: + toFocus = this.headers[ 0 ]; + break; + case keyCode.END: + toFocus = this.headers[ length - 1 ]; + break; + } + + if ( toFocus ) { + $( event.target ).attr( "tabIndex", -1 ); + $( toFocus ).attr( "tabIndex", 0 ); + $( toFocus ).trigger( "focus" ); + event.preventDefault(); + } + }, + + _panelKeyDown: function( event ) { + if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) { + $( event.currentTarget ).prev().trigger( "focus" ); + } + }, + + refresh: function() { + var options = this.options; + this._processPanels(); + + // Was collapsed or no panel + if ( ( options.active === false && options.collapsible === true ) || + !this.headers.length ) { + options.active = false; + this.active = $(); + + // active false only when collapsible is true + } else if ( options.active === false ) { + this._activate( 0 ); + + // was active, but active panel is gone + } else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) { + + // all remaining panel are disabled + if ( this.headers.length === this.headers.find( ".ui-state-disabled" ).length ) { + options.active = false; + this.active = $(); + + // activate previous panel + } else { + this._activate( Math.max( 0, options.active - 1 ) ); + } + + // was active, active panel still exists + } else { + + // make sure active index is correct + options.active = this.headers.index( this.active ); + } + + this._destroyIcons(); + + this._refresh(); + }, + + _processPanels: function() { + var prevHeaders = this.headers, + prevPanels = this.panels; + + if ( typeof this.options.header === "function" ) { + this.headers = this.options.header( this.element ); + } else { + this.headers = this.element.find( this.options.header ); + } + this._addClass( this.headers, "ui-accordion-header ui-accordion-header-collapsed", + "ui-state-default" ); + + this.panels = this.headers.next().filter( ":not(.ui-accordion-content-active)" ).hide(); + this._addClass( this.panels, "ui-accordion-content", "ui-helper-reset ui-widget-content" ); + + // Avoid memory leaks (#10056) + if ( prevPanels ) { + this._off( prevHeaders.not( this.headers ) ); + this._off( prevPanels.not( this.panels ) ); + } + }, + + _refresh: function() { + var maxHeight, + options = this.options, + heightStyle = options.heightStyle, + parent = this.element.parent(); + + this.active = this._findActive( options.active ); + this._addClass( this.active, "ui-accordion-header-active", "ui-state-active" ) + ._removeClass( this.active, "ui-accordion-header-collapsed" ); + this._addClass( this.active.next(), "ui-accordion-content-active" ); + this.active.next().show(); + + this.headers + .attr( "role", "tab" ) + .each( function() { + var header = $( this ), + headerId = header.uniqueId().attr( "id" ), + panel = header.next(), + panelId = panel.uniqueId().attr( "id" ); + header.attr( "aria-controls", panelId ); + panel.attr( "aria-labelledby", headerId ); + } ) + .next() + .attr( "role", "tabpanel" ); + + this.headers + .not( this.active ) + .attr( { + "aria-selected": "false", + "aria-expanded": "false", + tabIndex: -1 + } ) + .next() + .attr( { + "aria-hidden": "true" + } ) + .hide(); + + // Make sure at least one header is in the tab order + if ( !this.active.length ) { + this.headers.eq( 0 ).attr( "tabIndex", 0 ); + } else { + this.active.attr( { + "aria-selected": "true", + "aria-expanded": "true", + tabIndex: 0 + } ) + .next() + .attr( { + "aria-hidden": "false" + } ); + } + + this._createIcons(); + + this._setupEvents( options.event ); + + if ( heightStyle === "fill" ) { + maxHeight = parent.height(); + this.element.siblings( ":visible" ).each( function() { + var elem = $( this ), + position = elem.css( "position" ); + + if ( position === "absolute" || position === "fixed" ) { + return; + } + maxHeight -= elem.outerHeight( true ); + } ); + + this.headers.each( function() { + maxHeight -= $( this ).outerHeight( true ); + } ); + + this.headers.next() + .each( function() { + $( this ).height( Math.max( 0, maxHeight - + $( this ).innerHeight() + $( this ).height() ) ); + } ) + .css( "overflow", "auto" ); + } else if ( heightStyle === "auto" ) { + maxHeight = 0; + this.headers.next() + .each( function() { + var isVisible = $( this ).is( ":visible" ); + if ( !isVisible ) { + $( this ).show(); + } + maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() ); + if ( !isVisible ) { + $( this ).hide(); + } + } ) + .height( maxHeight ); + } + }, + + _activate: function( index ) { + var active = this._findActive( index )[ 0 ]; + + // Trying to activate the already active panel + if ( active === this.active[ 0 ] ) { + return; + } + + // Trying to collapse, simulate a click on the currently active header + active = active || this.active[ 0 ]; + + this._eventHandler( { + target: active, + currentTarget: active, + preventDefault: $.noop + } ); + }, + + _findActive: function( selector ) { + return typeof selector === "number" ? this.headers.eq( selector ) : $(); + }, + + _setupEvents: function( event ) { + var events = { + keydown: "_keydown" + }; + if ( event ) { + $.each( event.split( " " ), function( index, eventName ) { + events[ eventName ] = "_eventHandler"; + } ); + } + + this._off( this.headers.add( this.headers.next() ) ); + this._on( this.headers, events ); + this._on( this.headers.next(), { keydown: "_panelKeyDown" } ); + this._hoverable( this.headers ); + this._focusable( this.headers ); + }, + + _eventHandler: function( event ) { + var activeChildren, clickedChildren, + options = this.options, + active = this.active, + clicked = $( event.currentTarget ), + clickedIsActive = clicked[ 0 ] === active[ 0 ], + collapsing = clickedIsActive && options.collapsible, + toShow = collapsing ? $() : clicked.next(), + toHide = active.next(), + eventData = { + oldHeader: active, + oldPanel: toHide, + newHeader: collapsing ? $() : clicked, + newPanel: toShow + }; + + event.preventDefault(); + + if ( + + // click on active header, but not collapsible + ( clickedIsActive && !options.collapsible ) || + + // allow canceling activation + ( this._trigger( "beforeActivate", event, eventData ) === false ) ) { + return; + } + + options.active = collapsing ? false : this.headers.index( clicked ); + + // When the call to ._toggle() comes after the class changes + // it causes a very odd bug in IE 8 (see #6720) + this.active = clickedIsActive ? $() : clicked; + this._toggle( eventData ); + + // Switch classes + // corner classes on the previously active header stay after the animation + this._removeClass( active, "ui-accordion-header-active", "ui-state-active" ); + if ( options.icons ) { + activeChildren = active.children( ".ui-accordion-header-icon" ); + this._removeClass( activeChildren, null, options.icons.activeHeader ) + ._addClass( activeChildren, null, options.icons.header ); + } + + if ( !clickedIsActive ) { + this._removeClass( clicked, "ui-accordion-header-collapsed" ) + ._addClass( clicked, "ui-accordion-header-active", "ui-state-active" ); + if ( options.icons ) { + clickedChildren = clicked.children( ".ui-accordion-header-icon" ); + this._removeClass( clickedChildren, null, options.icons.header ) + ._addClass( clickedChildren, null, options.icons.activeHeader ); + } + + this._addClass( clicked.next(), "ui-accordion-content-active" ); + } + }, + + _toggle: function( data ) { + var toShow = data.newPanel, + toHide = this.prevShow.length ? this.prevShow : data.oldPanel; + + // Handle activating a panel during the animation for another activation + this.prevShow.add( this.prevHide ).stop( true, true ); + this.prevShow = toShow; + this.prevHide = toHide; + + if ( this.options.animate ) { + this._animate( toShow, toHide, data ); + } else { + toHide.hide(); + toShow.show(); + this._toggleComplete( data ); + } + + toHide.attr( { + "aria-hidden": "true" + } ); + toHide.prev().attr( { + "aria-selected": "false", + "aria-expanded": "false" + } ); + + // if we're switching panels, remove the old header from the tab order + // if we're opening from collapsed state, remove the previous header from the tab order + // if we're collapsing, then keep the collapsing header in the tab order + if ( toShow.length && toHide.length ) { + toHide.prev().attr( { + "tabIndex": -1, + "aria-expanded": "false" + } ); + } else if ( toShow.length ) { + this.headers.filter( function() { + return parseInt( $( this ).attr( "tabIndex" ), 10 ) === 0; + } ) + .attr( "tabIndex", -1 ); + } + + toShow + .attr( "aria-hidden", "false" ) + .prev() + .attr( { + "aria-selected": "true", + "aria-expanded": "true", + tabIndex: 0 + } ); + }, + + _animate: function( toShow, toHide, data ) { + var total, easing, duration, + that = this, + adjust = 0, + boxSizing = toShow.css( "box-sizing" ), + down = toShow.length && + ( !toHide.length || ( toShow.index() < toHide.index() ) ), + animate = this.options.animate || {}, + options = down && animate.down || animate, + complete = function() { + that._toggleComplete( data ); + }; + + if ( typeof options === "number" ) { + duration = options; + } + if ( typeof options === "string" ) { + easing = options; + } + + // fall back from options to animation in case of partial down settings + easing = easing || options.easing || animate.easing; + duration = duration || options.duration || animate.duration; + + if ( !toHide.length ) { + return toShow.animate( this.showProps, duration, easing, complete ); + } + if ( !toShow.length ) { + return toHide.animate( this.hideProps, duration, easing, complete ); + } + + total = toShow.show().outerHeight(); + toHide.animate( this.hideProps, { + duration: duration, + easing: easing, + step: function( now, fx ) { + fx.now = Math.round( now ); + } + } ); + toShow + .hide() + .animate( this.showProps, { + duration: duration, + easing: easing, + complete: complete, + step: function( now, fx ) { + fx.now = Math.round( now ); + if ( fx.prop !== "height" ) { + if ( boxSizing === "content-box" ) { + adjust += fx.now; + } + } else if ( that.options.heightStyle !== "content" ) { + fx.now = Math.round( total - toHide.outerHeight() - adjust ); + adjust = 0; + } + } + } ); + }, + + _toggleComplete: function( data ) { + var toHide = data.oldPanel, + prev = toHide.prev(); + + this._removeClass( toHide, "ui-accordion-content-active" ); + this._removeClass( prev, "ui-accordion-header-active" ) + ._addClass( prev, "ui-accordion-header-collapsed" ); + + // Work around for rendering bug in IE (#5421) + if ( toHide.length ) { + toHide.parent()[ 0 ].className = toHide.parent()[ 0 ].className; + } + this._trigger( "activate", null, data ); + } +} ); + + + +var safeActiveElement = $.ui.safeActiveElement = function( document ) { + var activeElement; + + // Support: IE 9 only + // IE9 throws an "Unspecified error" accessing document.activeElement from an