diff --git a/dist/css/plate-map.css b/dist/css/plate-map.css
new file mode 100644
index 0000000..f44a69c
--- /dev/null
+++ b/dist/css/plate-map.css
@@ -0,0 +1,491 @@
+@import url(http://fonts.googleapis.com/css?family=Roboto);
+
+.plate-setup-container {
+ width: 1024px;
+ height: 768px;
+ position: relative;
+ float: left;
+}
+
+.plate-setup-wrapper {
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;
+ flex-direction: column;
+ background-color: #f5f5f5;
+}
+
+.plate-setup-top-section {
+ height: 540px;
+ top: 0;
+ left: 0;
+ right: 0;
+ position: absolute;
+}
+
+.plate-setup-top-left {
+ width: 674px;
+ top: 0;
+ bottom: 0;
+ position: absolute;
+}
+
+.plate-setup-top-right {
+ left: 674px;
+ top: 0;
+ bottom: 0;
+ right: 0;
+ position: absolute;
+}
+
+.plate-setup-overlay-container {
+ height: 32px;
+ top: 10px;
+ left: 16px;
+ right: 16px;
+ position: inherit;
+ background-color: #464646;
+ border-radius: 2px;
+ display: flex;
+ justify-content: space-between;
+ align-items: baseline;
+ vertical-align: middle;
+}
+
+.plate-setup-overlay-radio-container {
+ width: 32px;
+ height: 32px;
+}
+
+.plate-setup-overlay-text-container {
+ color: white;
+ font-size: 12px;
+ line-height: 30px;
+ height: 32px;
+ font-family: "Roboto", Arial, sans-serif;
+ margin: 2px 8px;
+ flex: 1 1 auto;
+}
+
+.plate-setup-overlay-button-container, .plate-setup-overlay-bottom-button-container {
+ flex: 0 0 auto;
+ display: flex;
+ flex: 1 1 0;
+}
+
+.plate-setup-button {
+ height: 23px;
+ font-family: "Roboto", Arial, sans-serif;
+ font-size: 12px;
+ border: none;
+ background-color: white;
+ border-radius: 2px;
+ margin-right: 4px;
+ flex: 1 0 0;
+ white-space: nowrap;
+}
+
+.plate-setup-clicked-button {
+ height: 23px;
+ font-family: "Roboto", Arial, sans-serif;
+ font-size: 12px;
+ border: none;
+ background-color: aquamarine;
+ border-radius: 2px;
+ margin-right: 4px;
+ flex: 1 0 0;
+ white-space: nowrap;
+}
+
+
+.plate-setup-canvas-container {
+ top: 52px;
+ left: 16px;
+ right: 16px;
+ bottom: 10px;
+ position: absolute;
+}
+
+.plate-setup-tab-container {
+ position: absolute;
+ top:10px;
+ left:10px;
+ bottom: 10px;
+ right: 10px;
+ background-color: white;
+ border: solid 1px #e1e1e1;
+}
+
+.plate-setup-tab-head {
+ left: 0;
+ right: 0;
+ height: 23px;
+ border-bottom: solid 1px #e1e1e1;
+ background-color: #f5f5f5;
+ display: flex;
+}
+
+.plate-setup-tab {
+ height: 23px;
+ background-color: #ebebeb;
+ border-right: solid 1px #e1e1e1;
+ cursor: pointer;
+ font-family: "Roboto", Arial, sans-serif;
+ font-size: 10px;
+ text-align: center;
+ padding: 5px;
+ box-sizing: border-box;
+ flex: 1 1 auto;
+ white-space: nowrap;
+ overflow: hidden;
+}
+
+.plate-setup-tab:last-child {
+ border-right: none;
+}
+
+.plate-setup-tab-selected {
+ height: 24px;
+ background-color: white;
+ color: #00506e;
+ flex-shrink: 0;
+}
+
+.plate-setup-tab-data-container {
+ left: 0;
+ right: 0;
+ height: 442px;
+ border-bottom: solid 1px #e1e1e1;
+ position: absolute;
+ font-family: "Roboto", Arial, sans-serif;
+}
+
+.plate-setup-data-div {
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;
+ position: absolute;
+ background-color: white;
+ overflow: auto;
+}
+
+.plate-setup-well-attr-container {
+ top: 472px;
+ left: 0;
+ right: 0;
+ height: 20px;
+ box-sizing: border-box;
+ padding: 0px 16px;
+ color: #00506e;
+ text-align: center;
+ position: absolute;
+ font-size: 10px;
+ font-family: "Roboto", Arial, sans-serif;
+}
+
+.plate-setup-preset-container {
+ top: 490px;
+ left: 0;
+ right: 0;
+ height: 22px;
+ position: absolute;
+ box-sizing: border-box;
+ padding: 0px 16px;
+ text-align: center;
+ display: flex;
+ justify-content: center;
+}
+
+.plate-setup-prest-tab {
+ display: inline-block;
+ flex-basis: 50px;
+ padding: 0 5px;
+ margin: 0 1px;
+ height: 20px;
+ background-color: white;
+ border: solid 1px #e1e1e1;
+ border-radius: 2px;
+ cursor: pointer;
+ font-family: "Roboto", Arial, sans-serif;
+ font-size: 10px;
+ text-align: center;
+}
+
+.plate-setup-prest-tab-selected {
+ display: inline-block;
+ flex-basis: 50px;
+ padding: 0 5px;
+ margin: 0 1px;
+ height: 20px;
+ background-color: #e1e1e1;
+ border: solid 1px #e1e1e1;
+ border-radius: 2px;
+ cursor: pointer;
+ font-family: "Roboto", Arial, sans-serif;
+ font-size: 11px;
+ text-align: center;
+ color: #00506e;
+}
+
+.plate-setup-prest-tab-div {
+ padding-top: 3px;
+}
+
+.plate-setup-tab-default-field {
+ display: flex;
+ padding: 10px 16px 0 16px;
+}
+
+.plate-setup-tab-field-left-side {
+ width: 32px;
+ padding-top: 16px;
+}
+
+.plate-setup-tab-field-right-side {
+ flex: 1;
+}
+
+.plate-setup-tab-name {
+ font-family: "Roboto", Arial, sans-serif;
+ font-size: 12px;
+ display: inline-block;
+ line-height: 16px;
+}
+
+.plate-setup-tab-name-singleSelect {
+ font-family: "Roboto", Arial, sans-serif;
+ font-size: 12px;
+ margin-top: 5px;
+}
+
+
+.plate-setup-tab-name-missing {
+ height: 20px;
+ font-family: "Roboto", Arial, sans-serif;
+ font-size: 12px;
+ background: red;
+}
+
+
+.plate-setup-tab-field-container, .plate-setup-tab-field-container-singleSelect {
+ width: 100%;
+ display: flex;
+}
+
+.plate-setup-tab-input, .plate-setup-tab-select-field, .plate-setup-tab-multiplex-single-select-field {
+ height: 28px;
+ flex: 1 1 auto;
+ width: 30px;
+ margin: auto;
+}
+
+.plate-setup-tab-multiselect-field {
+ min-height: 28px;
+ flex: 1 1 auto;
+ width: 30px;
+}
+
+.plate-setup-tab-label-select-field, .plate-setup-tab-unit {
+ width: 130px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ height: 28px;
+ box-sizing: border-box;
+ padding-left: 5px;
+}
+
+.plate-setup-tab-unit {
+ font-family: "Roboto", Arial, sans-serif;
+ line-height: 26px;
+ color: #444;
+ white-space: nowrap;
+}
+
+.plate-setup-tab-check-box {
+ cursor: pointer;
+ border: 1px solid gray;
+ display: inline-block;
+ height: 16px;
+ width: 16px;
+ text-align: center;
+ line-height: 16px;
+}
+
+.plate-setup-bottom-control-container {
+ top: 0;
+ left: 0;
+ right: 0;
+ height: 32px;
+ background-color: #464646;
+ position: absolute;
+ display: flex;
+ justify-content:space-between;
+ align-items: baseline;
+ vertical-align: middle;
+}
+
+.plate-setup-bottom-container {
+ top: 540px;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ position: absolute;
+ background-color: #e1e1e1;
+}
+
+.plate-setup-bottom-table-container {
+ top: 32px;
+ left: 0;
+ bottom: 0;
+ right: 0;
+ position: absolute;
+ overflow: auto;
+}
+
+
+.plate-setup-bottom-table {
+ font-family: "Roboto", Arial, sans-serif;
+ font-size: 14px;
+ border-collapse: collapse;
+ width: 100%;
+}
+
+.plate-setup-bottom-table th {
+ border: solid #c2c2c2 1px;
+ padding: 5px 10px;
+ font-weight: bold;
+ font-size: 12px;
+ text-align: left;
+}
+
+.plate-setup-bottom-table td {
+ border: solid #c2c2c2 1px;
+ padding: 5px 10px;
+ background-color: white;
+}
+
+.plate-setup-color-text {
+ font-size: 14px;
+ border: none;
+ border-radius: 2px;
+ padding: 3px 15px;
+ background-color: WHITE;
+ margin-right: 4px;
+}
+
+.plate-setup-bottom-id {
+ width: 40px;
+ text-align: center;
+ background-image: linear-gradient(to right, rgba(255,255,255,0.3), transparent)
+}
+
+input.invalid {
+ background-color: pink;
+}
+
+.plate-setup-remove-all-button-container {
+ text-align: left;
+}
+
+.plate-setup-remove-all-button{
+ width: 100%;
+ font-family: "Roboto", Arial, sans-serif;
+ font-size: 12px;
+ text-overflow: ellipsis;
+ text-align: left;
+ white-space: nowrap;
+ border: 1px solid #aaa;
+ border-top: none;
+ color: #444;
+ background-color: #fff;
+ background-image: linear-gradient(to top, #eee 0%, #fff 50%);
+}
+/* Modal Content */
+
+.modal {
+ display: none; /* Hidden by default */
+ position: fixed; /* Stay in place */
+ z-index: 2000; /* Sit on top */
+ padding-top: 100px; /* Location of the box */
+ left: 0;
+ top: 0;
+ width: 100%; /* Full width */
+ height: 100%; /* Full height */
+ overflow: auto; /* Enable scroll if needed */
+ background-color: rgb(0,0,0); /* Fallback color */
+ background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
+}
+
+.modal-content {
+ font-family: 'Roboto', sans-serif;
+ font-size: 14px;
+ background-color: #fefefe;
+ margin: auto;
+ padding: 20px;
+ border: 1px solid #888;
+}
+
+.delete-dialog .modal-content {
+ width: 550px;
+}
+
+.modal-content > * {
+ width: 100%;
+}
+
+.dialog-buttons {
+ margin-top: 10px;
+ display: inline-block;
+ text-align: right;
+}
+
+.dialog-buttons button {
+ margin-left: 4px;
+}
+
+.plate-popout-table {
+ border-collapse: collapse;
+ width: 100%;
+ border: 1px solid black;
+ padding: 5px;
+}
+
+.plate-popout-th {
+ text-align: left;
+ background-color: white;
+ color: black;
+ font-size: 12px;
+ border: 1px solid black;
+ padding: 5px;
+}
+
+.plate-popout-tr:hover {
+ background-color: #f5f5f5;
+ border: 1px solid black;
+ padding: 5px;
+}
+
+.plate-popout-td {
+ text-align: left;
+ font-size: 11px;
+ border: 1px solid black;
+ padding: 5px;
+}
+
+.plate-field-warning-image{
+ vertical-align: baseline;
+ margin: 0px 0 0px;
+}
+
+.pop-out-text {
+ position: fixed;
+ display: none;
+ background: white;
+ border: 1px solid;
+ float: left;
+ margin-top: -44px;
+ z-Index: 99999 !important;
+}
diff --git a/dist/css/plate-map.min.css b/dist/css/plate-map.min.css
new file mode 100644
index 0000000..d7ff6e2
--- /dev/null
+++ b/dist/css/plate-map.min.css
@@ -0,0 +1,2 @@
+@import url(http://fonts.googleapis.com/css?family=Roboto);.plate-setup-container{width:1024px;height:768px;position:relative;float:left}.plate-setup-wrapper{position:absolute;top:0;left:0;bottom:0;right:0;flex-direction:column;background-color:#f5f5f5}.plate-setup-top-section{height:540px;top:0;left:0;right:0;position:absolute}.plate-setup-top-left{width:674px;top:0;bottom:0;position:absolute}.plate-setup-top-right{left:674px;top:0;bottom:0;right:0;position:absolute}.plate-setup-overlay-container{height:32px;top:10px;left:16px;right:16px;position:inherit;background-color:#464646;border-radius:2px;display:flex;justify-content:space-between;align-items:baseline;vertical-align:middle}.plate-setup-overlay-radio-container{width:32px;height:32px}.plate-setup-overlay-text-container{color:#fff;font-size:12px;line-height:30px;height:32px;font-family:Roboto,Arial,sans-serif;margin:2px 8px;flex:1 1 auto}.plate-setup-overlay-bottom-button-container,.plate-setup-overlay-button-container{flex:0 0 auto;display:flex;flex:1 1 0}.plate-setup-button{height:23px;font-family:Roboto,Arial,sans-serif;font-size:12px;border:none;background-color:#fff;border-radius:2px;margin-right:4px;flex:1 0 0;white-space:nowrap}.plate-setup-clicked-button{height:23px;font-family:Roboto,Arial,sans-serif;font-size:12px;border:none;background-color:#7fffd4;border-radius:2px;margin-right:4px;flex:1 0 0;white-space:nowrap}.plate-setup-canvas-container{top:52px;left:16px;right:16px;bottom:10px;position:absolute}.plate-setup-tab-container{position:absolute;top:10px;left:10px;bottom:10px;right:10px;background-color:#fff;border:solid 1px #e1e1e1}.plate-setup-tab-head{left:0;right:0;height:23px;border-bottom:solid 1px #e1e1e1;background-color:#f5f5f5;display:flex}.plate-setup-tab{height:23px;background-color:#ebebeb;border-right:solid 1px #e1e1e1;cursor:pointer;font-family:Roboto,Arial,sans-serif;font-size:10px;text-align:center;padding:5px;box-sizing:border-box;flex:1 1 auto;white-space:nowrap;overflow:hidden}.plate-setup-tab:last-child{border-right:none}.plate-setup-tab-selected{height:24px;background-color:#fff;color:#00506e;flex-shrink:0}.plate-setup-tab-data-container{left:0;right:0;height:442px;border-bottom:solid 1px #e1e1e1;position:absolute;font-family:Roboto,Arial,sans-serif}.plate-setup-data-div{top:0;left:0;bottom:0;right:0;position:absolute;background-color:#fff;overflow:auto}.plate-setup-well-attr-container{top:472px;left:0;right:0;height:20px;box-sizing:border-box;padding:0 16px;color:#00506e;text-align:center;position:absolute;font-size:10px;font-family:Roboto,Arial,sans-serif}.plate-setup-preset-container{top:490px;left:0;right:0;height:22px;position:absolute;box-sizing:border-box;padding:0 16px;text-align:center;display:flex;justify-content:center}.plate-setup-prest-tab{display:inline-block;flex-basis:50px;padding:0 5px;margin:0 1px;height:20px;background-color:#fff;border:solid 1px #e1e1e1;border-radius:2px;cursor:pointer;font-family:Roboto,Arial,sans-serif;font-size:10px;text-align:center}.plate-setup-prest-tab-selected{display:inline-block;flex-basis:50px;padding:0 5px;margin:0 1px;height:20px;background-color:#e1e1e1;border:solid 1px #e1e1e1;border-radius:2px;cursor:pointer;font-family:Roboto,Arial,sans-serif;font-size:11px;text-align:center;color:#00506e}.plate-setup-prest-tab-div{padding-top:3px}.plate-setup-tab-default-field{display:flex;padding:10px 16px 0 16px}.plate-setup-tab-field-left-side{width:32px;padding-top:16px}.plate-setup-tab-field-right-side{flex:1}.plate-setup-tab-name{font-family:Roboto,Arial,sans-serif;font-size:12px;display:inline-block;line-height:16px}.plate-setup-tab-name-singleSelect{font-family:Roboto,Arial,sans-serif;font-size:12px;margin-top:5px}.plate-setup-tab-name-missing{height:20px;font-family:Roboto,Arial,sans-serif;font-size:12px;background:red}.plate-setup-tab-field-container,.plate-setup-tab-field-container-singleSelect{width:100%;display:flex}.plate-setup-tab-input,.plate-setup-tab-multiplex-single-select-field,.plate-setup-tab-select-field{height:28px;flex:1 1 auto;width:30px;margin:auto}.plate-setup-tab-multiselect-field{min-height:28px;flex:1 1 auto;width:30px}.plate-setup-tab-label-select-field,.plate-setup-tab-unit{width:130px;overflow:hidden;text-overflow:ellipsis;height:28px;box-sizing:border-box;padding-left:5px}.plate-setup-tab-unit{font-family:Roboto,Arial,sans-serif;line-height:26px;color:#444;white-space:nowrap}.plate-setup-tab-check-box{cursor:pointer;border:1px solid gray;display:inline-block;height:16px;width:16px;text-align:center;line-height:16px}.plate-setup-bottom-control-container{top:0;left:0;right:0;height:32px;background-color:#464646;position:absolute;display:flex;justify-content:space-between;align-items:baseline;vertical-align:middle}.plate-setup-bottom-container{top:540px;left:0;right:0;bottom:0;position:absolute;background-color:#e1e1e1}.plate-setup-bottom-table-container{top:32px;left:0;bottom:0;right:0;position:absolute;overflow:auto}.plate-setup-bottom-table{font-family:Roboto,Arial,sans-serif;font-size:14px;border-collapse:collapse;width:100%}.plate-setup-bottom-table th{border:solid #c2c2c2 1px;padding:5px 10px;font-weight:700;font-size:12px;text-align:left}.plate-setup-bottom-table td{border:solid #c2c2c2 1px;padding:5px 10px;background-color:#fff}.plate-setup-color-text{font-size:14px;border:none;border-radius:2px;padding:3px 15px;background-color:#fff;margin-right:4px}.plate-setup-bottom-id{width:40px;text-align:center;background-image:linear-gradient(to right,rgba(255,255,255,.3),transparent)}input.invalid{background-color:pink}.plate-setup-remove-all-button-container{text-align:left}.plate-setup-remove-all-button{width:100%;font-family:Roboto,Arial,sans-serif;font-size:12px;text-overflow:ellipsis;text-align:left;white-space:nowrap;border:1px solid #aaa;border-top:none;color:#444;background-color:#fff;background-image:linear-gradient(to top,#eee 0,#fff 50%)}.modal{display:none;position:fixed;z-index:2000;padding-top:100px;left:0;top:0;width:100%;height:100%;overflow:auto;background-color:#000;background-color:rgba(0,0,0,.4)}.modal-content{font-family:Roboto,sans-serif;font-size:14px;background-color:#fefefe;margin:auto;padding:20px;border:1px solid #888}.delete-dialog .modal-content{width:550px}.modal-content>*{width:100%}.dialog-buttons{margin-top:10px;display:inline-block;text-align:right}.dialog-buttons button{margin-left:4px}.plate-popout-table{border-collapse:collapse;width:100%;border:1px solid #000;padding:5px}.plate-popout-th{text-align:left;background-color:#fff;color:#000;font-size:12px;border:1px solid #000;padding:5px}.plate-popout-tr:hover{background-color:#f5f5f5;border:1px solid #000;padding:5px}.plate-popout-td{text-align:left;font-size:11px;border:1px solid #000;padding:5px}.plate-field-warning-image{vertical-align:baseline;margin:0 0 0}.pop-out-text{position:fixed;display:none;background:#fff;border:1px solid;float:left;margin-top:-44px;z-Index:99999!important}
+/*# sourceMappingURL=plate-map.min.css.map */
\ No newline at end of file
diff --git a/dist/css/plate-map.min.css.map b/dist/css/plate-map.min.css.map
new file mode 100644
index 0000000..1d3e613
--- /dev/null
+++ b/dist/css/plate-map.min.css.map
@@ -0,0 +1 @@
+{"version":3,"sources":["plate-layout.css"],"names":[],"mappings":"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","file":"plate-map.min.css","sourcesContent":["@import url(http://fonts.googleapis.com/css?family=Roboto);\n\n.plate-setup-container {\n width: 1024px;\n height: 768px;\n position: relative;\n float: left;\n}\n\n.plate-setup-wrapper {\n position: absolute;\n top: 0;\n left: 0;\n bottom: 0;\n right: 0;\n flex-direction: column;\n background-color: #f5f5f5;\n}\n\n.plate-setup-top-section {\n height: 540px;\n top: 0;\n left: 0;\n right: 0;\n position: absolute;\n}\n\n.plate-setup-top-left {\n width: 674px;\n top: 0;\n bottom: 0;\n position: absolute;\n}\n\n.plate-setup-top-right {\n left: 674px;\n top: 0;\n bottom: 0;\n right: 0;\n position: absolute;\n}\n\n.plate-setup-overlay-container {\n height: 32px;\n top: 10px;\n left: 16px;\n right: 16px;\n position: inherit;\n background-color: #464646;\n border-radius: 2px;\n display: flex;\n justify-content: space-between;\n align-items: baseline;\n vertical-align: middle;\n}\n\n.plate-setup-overlay-radio-container {\n width: 32px;\n height: 32px;\n}\n\n.plate-setup-overlay-text-container {\n color: white;\n font-size: 12px;\n line-height: 30px;\n height: 32px;\n font-family: \"Roboto\", Arial, sans-serif;\n margin: 2px 8px;\n flex: 1 1 auto;\n}\n\n.plate-setup-overlay-button-container, .plate-setup-overlay-bottom-button-container {\n flex: 0 0 auto;\n display: flex;\n flex: 1 1 0;\n}\n\n.plate-setup-button {\n height: 23px;\n font-family: \"Roboto\", Arial, sans-serif;\n font-size: 12px;\n border: none;\n background-color: white;\n border-radius: 2px;\n margin-right: 4px;\n flex: 1 0 0;\n white-space: nowrap;\n}\n\n.plate-setup-clicked-button {\n height: 23px;\n font-family: \"Roboto\", Arial, sans-serif;\n font-size: 12px;\n border: none;\n background-color: aquamarine;\n border-radius: 2px;\n margin-right: 4px;\n flex: 1 0 0;\n white-space: nowrap;\n}\n\n\n.plate-setup-canvas-container {\n top: 52px;\n left: 16px;\n right: 16px;\n bottom: 10px;\n position: absolute;\n}\n\n.plate-setup-tab-container {\n position: absolute;\n top:10px;\n left:10px;\n bottom: 10px;\n right: 10px;\n background-color: white;\n border: solid 1px #e1e1e1;\n}\n\n.plate-setup-tab-head {\n left: 0;\n right: 0;\n height: 23px;\n border-bottom: solid 1px #e1e1e1;\n background-color: #f5f5f5;\n display: flex;\n}\n\n.plate-setup-tab {\n height: 23px;\n background-color: #ebebeb;\n border-right: solid 1px #e1e1e1;\n cursor: pointer;\n font-family: \"Roboto\", Arial, sans-serif;\n font-size: 10px;\n text-align: center;\n padding: 5px;\n box-sizing: border-box;\n flex: 1 1 auto;\n white-space: nowrap;\n overflow: hidden;\n}\n\n.plate-setup-tab:last-child {\n border-right: none;\n}\n\n.plate-setup-tab-selected {\n height: 24px;\n background-color: white;\n color: #00506e;\n flex-shrink: 0;\n}\n\n.plate-setup-tab-data-container {\n left: 0;\n right: 0;\n height: 442px;\n border-bottom: solid 1px #e1e1e1;\n position: absolute;\n font-family: \"Roboto\", Arial, sans-serif;\n}\n\n.plate-setup-data-div {\n top: 0;\n left: 0;\n bottom: 0;\n right: 0;\n position: absolute;\n background-color: white;\n overflow: auto;\n}\n\n.plate-setup-well-attr-container {\n top: 472px;\n left: 0;\n right: 0;\n height: 20px;\n box-sizing: border-box;\n padding: 0px 16px;\n color: #00506e;\n text-align: center;\n position: absolute;\n font-size: 10px;\n font-family: \"Roboto\", Arial, sans-serif;\n}\n\n.plate-setup-preset-container {\n top: 490px;\n left: 0;\n right: 0;\n height: 22px;\n position: absolute;\n box-sizing: border-box;\n padding: 0px 16px;\n text-align: center;\n display: flex;\n justify-content: center;\n}\n\n.plate-setup-prest-tab {\n display: inline-block;\n flex-basis: 50px;\n padding: 0 5px;\n margin: 0 1px;\n height: 20px;\n background-color: white;\n border: solid 1px #e1e1e1;\n border-radius: 2px;\n cursor: pointer;\n font-family: \"Roboto\", Arial, sans-serif;\n font-size: 10px;\n text-align: center;\n}\n\n.plate-setup-prest-tab-selected {\n display: inline-block;\n flex-basis: 50px;\n padding: 0 5px;\n margin: 0 1px;\n height: 20px;\n background-color: #e1e1e1;\n border: solid 1px #e1e1e1;\n border-radius: 2px;\n cursor: pointer;\n font-family: \"Roboto\", Arial, sans-serif;\n font-size: 11px;\n text-align: center;\n color: #00506e;\n}\n\n.plate-setup-prest-tab-div {\n padding-top: 3px;\n}\n\n.plate-setup-tab-default-field {\n display: flex;\n padding: 10px 16px 0 16px;\n}\n\n.plate-setup-tab-field-left-side {\n width: 32px;\n padding-top: 16px;\n}\n\n.plate-setup-tab-field-right-side {\n flex: 1;\n}\n\n.plate-setup-tab-name {\n font-family: \"Roboto\", Arial, sans-serif;\n font-size: 12px;\n display: inline-block;\n line-height: 16px;\n}\n\n.plate-setup-tab-name-singleSelect {\n font-family: \"Roboto\", Arial, sans-serif;\n font-size: 12px;\n margin-top: 5px;\n}\n\n\n.plate-setup-tab-name-missing {\n height: 20px;\n font-family: \"Roboto\", Arial, sans-serif;\n font-size: 12px;\n background: red;\n}\n\n\n.plate-setup-tab-field-container, .plate-setup-tab-field-container-singleSelect {\n width: 100%;\n display: flex;\n}\n\n.plate-setup-tab-input, .plate-setup-tab-select-field, .plate-setup-tab-multiplex-single-select-field {\n height: 28px;\n flex: 1 1 auto;\n width: 30px;\n margin: auto;\n}\n\n.plate-setup-tab-multiselect-field {\n min-height: 28px;\n flex: 1 1 auto;\n width: 30px;\n}\n\n.plate-setup-tab-label-select-field, .plate-setup-tab-unit {\n width: 130px;\n overflow: hidden;\n text-overflow: ellipsis;\n height: 28px;\n box-sizing: border-box;\n padding-left: 5px;\n}\n\n.plate-setup-tab-unit {\n font-family: \"Roboto\", Arial, sans-serif;\n line-height: 26px;\n color: #444;\n white-space: nowrap;\n}\n\n.plate-setup-tab-check-box {\n cursor: pointer;\n border: 1px solid gray;\n display: inline-block;\n height: 16px;\n width: 16px;\n text-align: center;\n line-height: 16px;\n}\n\n.plate-setup-bottom-control-container {\n top: 0;\n left: 0;\n right: 0;\n height: 32px;\n background-color: #464646;\n position: absolute;\n display: flex;\n justify-content:space-between;\n align-items: baseline;\n vertical-align: middle;\n}\n\n.plate-setup-bottom-container {\n top: 540px;\n left: 0;\n right: 0;\n bottom: 0;\n position: absolute;\n background-color: #e1e1e1;\n}\n\n.plate-setup-bottom-table-container {\n top: 32px;\n left: 0;\n bottom: 0;\n right: 0;\n position: absolute;\n overflow: auto;\n}\n\n\n.plate-setup-bottom-table {\n font-family: \"Roboto\", Arial, sans-serif;\n font-size: 14px;\n border-collapse: collapse;\n width: 100%;\n}\n\n.plate-setup-bottom-table th {\n border: solid #c2c2c2 1px;\n padding: 5px 10px;\n font-weight: bold;\n font-size: 12px;\n text-align: left;\n}\n\n.plate-setup-bottom-table td {\n border: solid #c2c2c2 1px;\n padding: 5px 10px;\n background-color: white;\n}\n\n.plate-setup-color-text {\n font-size: 14px;\n border: none;\n border-radius: 2px;\n padding: 3px 15px;\n background-color: WHITE;\n margin-right: 4px;\n}\n\n.plate-setup-bottom-id {\n width: 40px;\n text-align: center;\n background-image: linear-gradient(to right, rgba(255,255,255,0.3), transparent)\n}\n\ninput.invalid {\n background-color: pink;\n}\n\n.plate-setup-remove-all-button-container {\n text-align: left;\n}\n\n.plate-setup-remove-all-button{\n width: 100%;\n font-family: \"Roboto\", Arial, sans-serif;\n font-size: 12px;\n text-overflow: ellipsis;\n text-align: left;\n white-space: nowrap;\n border: 1px solid #aaa;\n border-top: none;\n color: #444;\n background-color: #fff;\n background-image: linear-gradient(to top, #eee 0%, #fff 50%);\n}\n/* Modal Content */\n\n.modal {\n display: none; /* Hidden by default */\n position: fixed; /* Stay in place */\n z-index: 2000; /* Sit on top */\n padding-top: 100px; /* Location of the box */\n left: 0;\n top: 0;\n width: 100%; /* Full width */\n height: 100%; /* Full height */\n overflow: auto; /* Enable scroll if needed */\n background-color: rgb(0,0,0); /* Fallback color */\n background-color: rgba(0,0,0,0.4); /* Black w/ opacity */\n}\n\n.modal-content {\n font-family: 'Roboto', sans-serif;\n font-size: 14px;\n background-color: #fefefe;\n margin: auto;\n padding: 20px;\n border: 1px solid #888;\n}\n\n.delete-dialog .modal-content {\n width: 550px;\n}\n\n.modal-content > * {\n width: 100%;\n}\n\n.dialog-buttons {\n margin-top: 10px;\n display: inline-block;\n text-align: right;\n}\n\n.dialog-buttons button {\n margin-left: 4px;\n}\n\n.plate-popout-table {\n border-collapse: collapse;\n width: 100%;\n border: 1px solid black;\n padding: 5px;\n}\n\n.plate-popout-th {\n text-align: left;\n background-color: white;\n color: black;\n font-size: 12px;\n border: 1px solid black;\n padding: 5px;\n}\n\n.plate-popout-tr:hover {\n background-color: #f5f5f5;\n border: 1px solid black;\n padding: 5px;\n}\n\n.plate-popout-td {\n text-align: left;\n font-size: 11px;\n border: 1px solid black;\n padding: 5px;\n}\n\n.plate-field-warning-image{\n vertical-align: baseline;\n margin: 0px 0 0px;\n}\n\n.pop-out-text {\n position: fixed;\n display: none;\n background: white;\n border: 1px solid;\n float: left;\n margin-top: -44px;\n z-Index: 99999 !important;\n}\n"]}
\ No newline at end of file
diff --git a/dist/js/plate-map.js b/dist/js/plate-map.js
new file mode 100755
index 0000000..a675c85
--- /dev/null
+++ b/dist/js/plate-map.js
@@ -0,0 +1,4390 @@
+var plateLayOutWidget = plateLayOutWidget || {};
+
+(function($, fabric) {
+
+ plateLayOutWidget.addDataOnChange = function() {
+ // This object is invoked when something in the tab fields change
+ return {
+
+ _addAllData: function(data) {
+ // Method to add data when something changes in the tabs. Its going to be tricky , just starting.
+ if (this.allSelectedObjects) {
+ var noOfSelectedObjects = this.allSelectedObjects.length;
+ var wells = [];
+ for (var objectIndex = 0; objectIndex < noOfSelectedObjects; objectIndex++) {
+ var tile = this.allSelectedObjects[objectIndex];
+ var well;
+ if (tile.index in this.engine.derivative) {
+ well = this.engine.derivative[tile.index];
+ } else {
+ well = $.extend(true, {}, this.defaultWell);
+ this.engine.derivative[tile.index] = well;
+ }
+ var processedData = this.processWellData(data, well, noOfSelectedObjects, wells);
+ wells = processedData.wells;
+ well = processedData.well;
+ var empty = this.engine.wellEmpty(well);
+ if (empty) {
+ if (this.emptyWellWithDefaultVal && this.disableAddDeleteWell) {
+ var wellCopy = JSON.parse(JSON.stringify(well));
+ var defaultValue = this.emptyWellWithDefaultVal;
+ for (var key in defaultValue) {
+ if (key in wellCopy) {
+ wellCopy[key] = defaultValue[key];
+ this._applyFieldData(key, defaultValue[key]);
+ }
+ }
+ this.engine.derivative[tile.index] = wellCopy;
+ } else {
+ delete this.engine.derivative[tile.index];
+ }
+ }
+ }
+ }
+ // update multiplex remove all field
+ this._getAllMultipleVal(wells);
+ this.applyFieldWarning(wells);
+ // create well when default field is sent for the cases when user delete all fields during disabledNewDeleteWell mode
+ this._colorMixer();
+ this.derivativeChange();
+ },
+
+ processWellData: function(newData, curWell, noOfSelectedObjects, wellList) {
+
+ if (!wellList) {
+ wellList = [];
+ }
+ for (var id in newData) {
+ var v;
+ if (newData[id] !== undefined && newData[id] !== null) {
+ if (newData[id].multi) {
+ var curData = newData[id];
+ var preData = curWell[id];
+ var newDt = this._getMultiData(preData, curData, id, noOfSelectedObjects);
+ // need to replace newData
+ v = JSON.parse(JSON.stringify(newDt));
+ } else {
+ v = JSON.parse(JSON.stringify(newData[id]));
+ }
+ } else {
+ v = JSON.parse(JSON.stringify(newData[id]));
+ }
+ curWell[id] = v;
+ wellList.push(curWell);
+ }
+
+ return {
+ well: curWell,
+ wells: wellList
+ }
+ },
+
+ _getMultiData: function(preData, curData, fieldId, noOfSelectedObjects) {
+ var addNew = curData.added;
+ var removed = curData.removed;
+ if (addNew) {
+ if (preData) {
+ if (addNew.value) {
+ var add = true;
+ for (var listIdx in preData) {
+ var multiplexData = preData[listIdx];
+ // for cases when the add new data exist in well
+ if (multiplexData[fieldId].toString() === addNew.id.toString()) {
+ add = false;
+ // update subfield value
+ preData = preData.map(function(val) {
+ if (val[fieldId].toString() === addNew.id.toString()) {
+ for (var subFieldId in val) {
+ // over write previous data if only one well is selected
+ if (subFieldId in addNew.value && subFieldId !== fieldId) {
+ if (noOfSelectedObjects === 1) {
+ val[subFieldId] = addNew.value[subFieldId];
+ } else if (addNew.value[subFieldId]) {
+ val[subFieldId] = addNew.value[subFieldId];
+ }
+ }
+ }
+ }
+ return val;
+ })
+ }
+ }
+ if (add) {
+ preData.push(addNew.value);
+ }
+ } else if (preData.indexOf(addNew) < 0) {
+ preData.push(addNew);
+ }
+ } else {
+ preData = [];
+ if (addNew.value) {
+ preData.push(addNew.value);
+ } else if (addNew) {
+ preData.push(addNew);
+ }
+ }
+ }
+
+ var removeListIndex = function(preData, removeIndex) {
+ var newPreData = [];
+ for (var idx in preData) {
+ if (parseInt(idx) !== parseInt(removeIndex)) {
+ newPreData.push(preData[idx]);
+ }
+ }
+ return newPreData;
+ };
+
+ if (removed) {
+ var removeIndex;
+ // for multiplex field
+ if (removed.value) {
+ for (var listIdx in preData) {
+ var multiplexData = preData[listIdx];
+ if (multiplexData[fieldId].toString() === removed.id.toString()) {
+ removeIndex = listIdx;
+ }
+ }
+ // remove nested element
+ preData = removeListIndex(preData, removeIndex);
+ } else {
+ if (preData) {
+ removeIndex = preData.indexOf(removed);
+ if (removeIndex >= 0) {
+ preData = removeListIndex(preData, removeIndex);
+ }
+ }
+ }
+ }
+ if (preData && (preData.length == 0)) {
+ preData = null;
+ }
+ return preData
+ },
+
+ _colorMixer: function() {
+ if (!this.undoRedoActive) {
+ var data = this.createObject();
+ this.addToUndoRedo(data);
+ }
+ this.engine.searchAndStack();
+ this.engine.applyColors();
+ this.mainFabricCanvas.renderAll();
+ },
+
+ derivativeChange: function() {
+ this._trigger("updateWells", null, this.createObject());
+ },
+
+ createObject: function() {
+ var derivative = $.extend(true, {}, this.engine.derivative);
+ var checkboxes = this.globalSelectedAttributes.slice();
+ var selectedAreas = this.selectedAreas.slice();
+ var focalWell = this.focalWell;
+
+ return {
+ "derivative": derivative,
+ "checkboxes": checkboxes,
+ "selectedAreas": selectedAreas,
+ "focalWell": focalWell,
+ "requiredField": this.requiredField
+ };
+ }
+ };
+ }
+})(jQuery, fabric);
+var plateLayOutWidget = plateLayOutWidget || {};
+
+(function($, fabric) {
+
+ plateLayOutWidget.addDataToFields = function() {
+
+ return {
+
+ _addDataToTabFields: function(values) {
+ // Configure how data is added to tab fields
+ for (var id in values) {
+ this._applyFieldData(id, values[id]);
+ }
+ },
+
+ _applyFieldData: function(id, v) {
+ this.fieldMap[id].setValue(v);
+ }
+ }
+ }
+})(jQuery, fabric)
+var plateLayOutWidget = plateLayOutWidget || {};
+
+(function($, fabric) {
+
+ plateLayOutWidget.addTabData = function() {
+
+ return {
+
+ fieldList: [],
+ fieldMap: {},
+ autoId: 1,
+
+ _addTabData: function() {
+ // Here we may need more changes because attributes format likely to change
+ var tabData = this.options.attributes.tabs;
+ var that = this;
+ this.requiredField = [];
+ var multiplexFieldArray = [];
+ tabData.forEach(function(tab, tabPointer) {
+ if (tab["fields"]) {
+ var tabFields = tab["fields"];
+ var fieldArray = [];
+ var fieldArrayIndex = 0;
+ // Now we look for fields in the json
+ for (var field in tabFields) {
+ var data = tabFields[field];
+
+ if (!data.id) {
+ data.id = "Auto" + that.autoId++;
+ console.log("Field autoassigned id " + data.id);
+ }
+ if (!data.type) {
+ data.type = "text";
+ console.log("Field " + data.id + " autoassigned type " + data.type);
+ }
+
+ var field_val;
+ if (data.type === "multiplex") {
+ field_val = that._makeMultiplexField(data, tabPointer, fieldArray);
+ multiplexFieldArray.push(field_val);
+ } else {
+ field_val = that._makeRegularField(data, tabPointer, fieldArray, true);
+ if (data.type === "multiselect") {
+ multiplexFieldArray.push(field_val);
+ }
+ }
+ ;
+ }
+
+ that.allDataTabs[tabPointer]["fields"] = fieldArray;
+ } else {
+ console.log("unknown format in field initialization");
+ }
+ });
+ that.multipleFieldList = multiplexFieldArray;
+ },
+
+ _makeSubField: function(data, tabPointer, fieldArray) {
+ var that = this;
+ if (!data.id) {
+ data.id = "Auto" + that.autoId++;
+ console.log("Field autoassigned id " + data.id);
+ }
+ if (!data.type) {
+ data.type = "text";
+ console.log("Field " + data.id + " autoassigned type " + data.type);
+ }
+ var wrapperDiv = that._createElement("
").addClass("plate-setup-tab-default-field");
+ var wrapperDivLeftSide = that._createElement("
").addClass("plate-setup-tab-field-left-side");
+ var wrapperDivRightSide = that._createElement("
").addClass("plate-setup-tab-field-right-side");
+ var nameContainer = that._createElement("
").addClass("plate-setup-tab-name").text(data.name);
+ var fieldContainer = that._createElement("
").addClass("plate-setup-tab-field-container");
+
+ $(wrapperDivRightSide).append(nameContainer);
+ $(wrapperDivRightSide).append(fieldContainer);
+ $(wrapperDiv).append(wrapperDivLeftSide);
+ $(wrapperDiv).append(wrapperDivRightSide);
+ $(that.allDataTabs[tabPointer]).append(wrapperDiv);
+
+ var field = {
+ id: data.id,
+ name: data.name,
+ root: wrapperDiv,
+ data: data,
+ required: data.required || false
+ };
+
+ fieldArray.push(field);
+ that.fieldMap[data.id] = field;
+
+ return field;
+ },
+
+ _makeRegularField: function(data, tabPointer, fieldArray, checkbox) {
+ var that = this;
+ var wrapperDiv = that._createElement("
").addClass("plate-setup-tab-default-field");
+ var wrapperDivLeftSide = that._createElement("
").addClass("plate-setup-tab-field-left-side");
+ var wrapperDivRightSide = that._createElement("
").addClass("plate-setup-tab-field-right-side ");
+ var nameContainer = that._createElement("
").addClass("plate-setup-tab-name").text(data.name);
+ var fieldContainer = that._createElement("
").addClass("plate-setup-tab-field-container");
+
+ wrapperDivRightSide.append(nameContainer);
+ wrapperDivRightSide.append(fieldContainer);
+ wrapperDiv.append(wrapperDivLeftSide);
+ wrapperDiv.append(wrapperDivRightSide);
+ that.allDataTabs[tabPointer].append(wrapperDiv);
+
+ var field = {
+ id: data.id,
+ name: data.name,
+ root: wrapperDiv,
+ data: data,
+ required: data.required
+ };
+
+ if (field.required) {
+ that.requiredField.push(field.id);
+ }
+
+ fieldArray.push(field);
+ that.fieldList.push(field);
+ that.fieldMap[field.id] = field;
+
+ // Adding checkbox
+ if (checkbox) {
+ that._addCheckBox(field);
+ }
+ that._createField(field);
+
+ field.onChange = function() {
+ var v = field.getValue();
+ var data = {};
+ data[field.id] = v;
+ that._addAllData(data);
+ };
+ return field;
+ },
+
+ _makeMultiplexField: function(data, tabPointer, fieldArray) {
+ var that = this;
+ var wrapperDiv = that._createElement("
").addClass("plate-setup-tab-default-field");
+ var wrapperDivLeftSide = that._createElement("
").addClass("plate-setup-tab-field-left-side");
+ var wrapperDivRightSide = that._createElement("
").addClass("plate-setup-tab-field-right-side ");
+ var nameContainer = that._createElement("
").addClass("plate-setup-tab-name").text(data.name);
+ var fieldContainer = that._createElement("
").addClass("plate-setup-tab-field-container");
+
+ wrapperDivRightSide.append(nameContainer);
+ wrapperDivRightSide.append(fieldContainer);
+ wrapperDiv.append(wrapperDivLeftSide);
+ wrapperDiv.append(wrapperDivRightSide);
+ that.allDataTabs[tabPointer].append(wrapperDiv);
+
+ var field = {
+ id: data.id,
+ name: data.name,
+ root: wrapperDiv,
+ data: data,
+ required: data.required
+ };
+
+ fieldArray.push(field);
+ that.fieldList.push(field);
+ that.fieldMap[data.id] = field;
+
+ var subFieldList = [];
+ //create subfields
+ var requiredSubField = [];
+ for (var subFieldKey in data.multiplexFields) {
+ var subFieldData = data.multiplexFields[subFieldKey];
+ var subField = that._makeSubField(subFieldData, tabPointer, fieldArray);
+ subFieldList.push(subField);
+
+ // stores required subField
+ if (subFieldData.required) {
+ requiredSubField.push(subField.id);
+ }
+ }
+
+ //store required field
+ if (field.required || requiredSubField.length) {
+ this.requiredField.push({
+ multiplexId: field.id,
+ subFields: requiredSubField
+ });
+ }
+
+ field.subFieldList = subFieldList;
+ that._createField(field);
+ that._addCheckBox(field);
+
+ subFieldList.forEach(function(subfield) {
+ subfield.mainMultiplexField = field;
+ fieldArray.push(subfield);
+ that._createField(subfield);
+ that._addCheckBox(subfield);
+ delete that.defaultWell[subfield.id];
+ // overwrite subField setvalue
+ subfield.onChange = function() {
+ var v = subfield.getValue();
+ var mainRefField = subfield.mainMultiplexField;
+ var curId = mainRefField.singleSelectValue();
+ //var curDataLs = mainRefField.detailData;
+ var curVal = {};
+ curVal[mainRefField.id] = curId;
+ //append subfields
+ curVal[subfield.id] = v;
+ var returnVal = {
+ id: curId,
+ value: curVal
+ };
+
+ field._changeMultiFieldValue(returnVal, null);
+ var curDataLs = mainRefField.detailData;
+ if (curDataLs !== null) {
+ curId = mainRefField.singleSelectValue();
+ curDataLs = curDataLs.map(function(curData) {
+ if (curData[mainRefField.id] === curId) {
+ curData[subfield.id] = v;
+ }
+ return curData;
+ });
+ }
+ mainRefField.detailData = curDataLs;
+ };
+
+ });
+
+ field.getValue = function() {
+ var v = field.input.val();
+ if (v.length) {
+ return v;
+ }
+ return null;
+ };
+
+ return field;
+ }
+ }
+ }
+
+})(jQuery, fabric);
+
+var plateLayOutWidget = plateLayOutWidget || {};
+
+(function($, fabric) {
+
+ plateLayOutWidget.addWarningMsg = function() {
+ // For those check boxes associated with every field in the tab
+ return {
+ fieldWarningMsg: function(field, text, include) {
+ var that = this;
+ var imgId = "fieldWarning" + field.id;
+ var img = $("").html(that._assets.warningImg).attr("id", imgId).addClass("plate-field-warning-image");
+ //field.root.find(".plate-setup-tab-name").append(' ')
+ if (include) {
+ if (field.root.find("#" + imgId).length <= 0) {
+ field.root.find(".plate-setup-tab-name").text(" " + field.name);
+ field.root.find(".plate-setup-tab-name").prepend(img);
+
+ var popText = $("
").addClass("pop-out-text");
+ popText.text(text);
+ field.root.find(".plate-setup-tab-name").append(popText);
+
+ $("#" + imgId).hover(function(e) {
+ popText[0].style.display = 'flex';
+ }, function() {
+ popText.hide();
+ });
+ }
+
+
+ } else {
+ if (field.root.find("#" + imgId).length > 0) {
+ field.root.find(".plate-setup-tab-name").text(field.name);
+ $("#" + imgId).remove();
+ }
+ }
+ },
+
+ removeWarningMsg: function(field, text, include) {
+ var that = this;
+ var imgId = "fieldWarning" + field.id;
+ var img = $("").html(that._assets.warningImg).attr("id", imgId).addClass("plate-field-warning-image");
+ //field.root.find(".plate-setup-tab-name").append(' ')
+ if (include) {
+ field.root.find(".plate-setup-tab-name").append(img);
+
+ var popText = $("
").addClass("pop-out-text");
+ popText.text(text);
+ field.root.find(".plate-setup-tab-name").append(popText);
+
+ $("#" + imgId).hover(function(e) {
+ popText[0].style.display = 'inline-block';
+ }, function() {
+ popText.hide();
+ });
+
+ } else {
+ $("#" + imgId).remove();
+ if (field.root.find("#" + imgId).length > 0) {
+ //field.root.find(".plate-setup-tab-name").remove(img);
+ $("#" + imgId).remove();
+ }
+ }
+ },
+
+ applyFieldWarning: function(wells) {
+ var that = this;
+ var req = 0;
+ var fill = 0;
+ var fieldData = {};
+ that.fieldList.forEach(function(field) {
+ fieldData[field.id] = [];
+ });
+ wells.forEach(function(well) {
+ if (!that.engine.wellEmpty(well)) {
+ for (var fieldId in fieldData) {
+ if (fieldId in well) {
+ fieldData[fieldId].push(well[fieldId]);
+ } else {
+ fieldData[fieldId].push(null);
+ }
+ }
+ }
+ });
+ for (var i = 0; i < that.fieldList.length; i++) {
+ var field = that.fieldList[i];
+ if (field.applyMultiplexSubFieldColor) {
+ field.applyMultiplexSubFieldColor(fieldData[field.id]);
+ } else {
+ if (field.required) {
+ var include = false;
+ fieldData[field.id].forEach(function(val) {
+ // for multiselect
+ if (val instanceof Array) {
+ if (val.length === 0) {
+ include = true;
+ }
+ } else {
+ if (val === null) {
+ include = true;
+ }
+ }
+ });
+ //field.root.find(".plate-setup-tab-name").css("background", color);
+ that.fieldWarningMsg(field, "required field", include);
+ }
+ }
+ }
+ }
+ }
+ }
+})(jQuery, fabric);
+var plateLayOutWidget = plateLayOutWidget || {};
+
+(function($, fabric) {
+
+ plateLayOutWidget.bottomTable = function() {
+ // for bottom table
+ return {
+ _bottomScreen: function() {
+ this.bottomContainer = this._createElement("
").addClass("plate-setup-bottom-container");
+ this.bottomTableContainer = this._createElement("
").addClass("plate-setup-bottom-table-container");
+ this.bottomTable = this._createElement("").addClass("plate-setup-bottom-table");
+ this.bottomTableContainer.append(this.bottomTable);
+ this.bottomContainer.append(this.bottomTableContainer);
+ this.container.append(this.bottomContainer);
+ },
+
+ addBottomTableHeadings: function() {
+
+ this.bottomRow = this._createElement(" ");
+
+ var singleField = this._createElement(" ")
+ .text("Group");
+ this.bottomRow.prepend(singleField);
+ // Now we append all the captions at the place.
+ this.bottomTable.empty();
+ this.bottomTable.append(this.bottomRow);
+
+ this.rowCounter = 1;
+
+ for (var i = 0; i < this.globalSelectedAttributes.length; i++) {
+ var attr = this.globalSelectedAttributes[i];
+ var field = this.fieldMap[attr];
+ var singleField = this._createElement(" ").text(field.name);
+ this.bottomRow.append(singleField);
+ this.rowCounter = this.rowCounter + 1;
+ }
+
+ this.adjustFieldWidth(this.bottomRow);
+ },
+
+ tileAttrText: function(tile, attr) {
+ var well = this.engine.derivative[tile.index];
+ var field = this.fieldMap[attr];
+ return field.getText(well[attr]);
+ },
+
+ addBottomTableRow: function(color, singleStack) {
+ var that = this;
+ var modelTile = this.allTiles[singleStack[0]];
+ var row = this._createElement(" ");
+ var plateIdDiv = this._createElement(" ").addClass("plate-setup-bottom-id");
+ var numberText = this._createElement(" ");
+ numberText.addClass("plate-setup-color-text");
+ numberText.text(color);
+ plateIdDiv.append(numberText);
+
+ numberText.click(function(evt) {
+ var addressToSelect = singleStack.map(function(addressIdx) {
+ return that.indexToAddress(addressIdx)
+ });
+ if (evt.ctrlKey) {
+ that.getSelectedAddress().forEach(function(val) {
+ if (addressToSelect.indexOf(val) < 0) {
+ addressToSelect.push(val);
+ }
+ })
+ }
+ that.setSelectedWell(addressToSelect);
+ that._trigger("selectedWells", null, {selectedAddress: that.getSelectedAddress()});
+ });
+
+ if (color > 0) {
+ color = ((color - 1) % (this.colorPairs.length - 1)) + 1;
+ }
+ var colorStops = this.colorPairs[color];
+
+ plateIdDiv.css("background", "linear-gradient(to right, " + colorStops[0] + " , " + colorStops[1] + ")");
+
+ row.append(plateIdDiv);
+
+ for (var i = 0; i < this.globalSelectedAttributes.length; i++) {
+ var attr = this.globalSelectedAttributes[i];
+ var text = this.tileAttrText(modelTile, attr);
+ var dataDiv = this._createElement(" ").text(text);
+ row.append(dataDiv);
+ }
+ this.bottomTable.append(row);
+ this.adjustFieldWidth(row);
+ },
+
+ bottomForFirstTime: function() {
+ this.addBottomTableHeadings();
+ // This is executed for the very first time.. !
+ var row = this._createElement(" ");
+
+ var colorStops = this.colorPairs[0];
+ var plateIdDiv = this._createElement(" ");
+ plateIdDiv.css("background", "-webkit-linear-gradient(left, " + colorStops[0] + " , " + colorStops[1] + ")");
+ row.append(plateIdDiv);
+ this.bottomTable.append(row);
+ this.createExportButton();
+ },
+
+ adjustFieldWidth: function(row) {
+
+ var length = this.rowCounter;
+ if ((length) * 150 > 1024) {
+ row.css("width", (length) * 152 + "px");
+ }
+ },
+
+ downloadCSV: function(csv, filename) {
+ var csvFile;
+ var downloadLink;
+
+ // CSV file
+ csvFile = new Blob([csv], {
+ type: "text/csv"
+ });
+
+ // Download link
+ downloadLink = document.createElement("a");
+
+ // File name
+ downloadLink.download = filename;
+
+ // Create a link to the file
+ downloadLink.href = window.URL.createObjectURL(csvFile);
+
+ // Hide download link
+ downloadLink.style.display = "none";
+
+ // Add the link to DOM
+ document.body.appendChild(downloadLink);
+
+ // Click download link
+ downloadLink.click();
+ },
+
+ exportData: function(format) {
+ var data = [];
+ var rows = document.querySelectorAll("table tr");
+
+ var colorLocMap = {};
+ var colorLocIdxMap = this.engine.stackUpWithColor;
+ var dim = this.getDimensions();
+ var that = this;
+ for (var colorIdx in colorLocIdxMap) {
+ colorLocMap[colorIdx] = colorLocIdxMap[colorIdx].map(function(locIdx) {
+ return that.indexToAddress(locIdx, dim);
+ })
+ }
+
+ for (var i = 0; i < rows.length; i++) {
+ var row = [],
+ cols = rows[i].querySelectorAll("td, th");
+
+ for (var j = 0; j < cols.length; j++) {
+ var v = "";
+ if (cols[j].innerText) {
+ if (format === "csv") {
+ v = '"' + cols[j].innerText.replace(/"/g, '""') + '"';
+ } else {
+ v = cols[j].innerText;
+ }
+ }
+ row.push(v);
+
+ // add location column
+ if (i === 0 && j === 0) {
+ if (format === "csv") {
+ row.push('"Location"');
+ } else if (format === 'clipboard') {
+ row.push("Location");
+ }
+
+ }
+ if (i !== 0 && j === 0) {
+ var loc = '';
+ if (colorLocMap[parseInt(cols[j].innerText)]) {
+ if (format === "csv") {
+ loc = '"' + colorLocMap[parseInt(cols[j].innerText)].join(",") + '"';
+ } else if (format === 'clipboard') {
+ loc = colorLocMap[parseInt(cols[j].innerText)].join(",");
+ }
+ }
+ row.push(loc);
+ }
+ }
+
+ if (format === "csv") {
+ data.push(row.join(","));
+ } else if (format === 'clipboard') {
+ data.push(row.join("\t"));
+ //data.push(row); // for text type
+ }
+
+ }
+ if (format === "csv") {
+ // Download CSV file
+ this.downloadCSV(data.join("\n"), 'table.csv');
+ } else if (format === 'clipboard') {
+ //return formatTableToString(data); // for text type
+ return data.join("\n");
+ }
+ },
+
+ createExportButton: function() {
+ var that = this;
+ var overlayContainer = $("").addClass("plate-setup-bottom-control-container");
+
+ var descriptionDiv = $("
").addClass("plate-setup-overlay-text-container");
+ descriptionDiv.text("Color groups");
+ overlayContainer.append(descriptionDiv);
+
+ var buttonContainer = $("
").addClass("plate-setup-overlay-bottom-button-container");
+
+ // create export csv option
+ var exportButton = $("
").addClass("plate-setup-button");
+ exportButton.text("Export CSV");
+ buttonContainer.append(exportButton);
+
+ exportButton.click(function() {
+ that.exportData('csv');
+ exportButton.text("Exported");
+ exportButton[0].classList.remove("plate-setup-button");
+ exportButton.addClass("plate-setup-clicked-button");
+ setTimeout(resetExportText, 3000);
+ });
+
+ function resetExportText() {
+ exportButton.text("Export CSV");
+ exportButton[0].classList.remove("plate-setup-clicked-button");
+ exportButton.addClass("plate-setup-button");
+ }
+
+ // creat clipboard option, CLipboard is an external js file located in vendor/asset/javascripts
+ var clipboardButton = $("
").addClass("plate-setup-button");
+ clipboardButton.text("Copy To Clipboard");
+ buttonContainer.append(clipboardButton);
+
+ var clipboard = new ClipboardJS(clipboardButton.get(0), {
+ text: function() {
+ return that.exportData("clipboard");
+ }
+ });
+
+ clipboard.on('success', function(e) {
+ clipboardButton.text("Copied as tab-delimited format");
+ clipboardButton[0].classList.remove("plate-setup-button");
+ clipboardButton.addClass("plate-setup-clicked-button");
+ setTimeout(resetClipboardText, 3000);
+ });
+
+ function resetClipboardText() {
+ clipboardButton.text("Copy To Clipboard");
+ clipboardButton[0].classList.remove("plate-setup-clicked-button");
+ clipboardButton.addClass("plate-setup-button");
+ }
+
+ clipboard.on('error', function(e) {
+ clipboardButton.text("Failed to copy table to clipboard: browser may be incompatible");
+ setTimeout(resetClipboardText, 3000);
+ });
+
+ overlayContainer.append(buttonContainer);
+ this.bottomContainer.prepend(overlayContainer);
+ }
+ };
+ }
+})(jQuery, fabric);
+var plateLayOutWidget = plateLayOutWidget || {};
+
+(function($, fabric) {
+
+ plateLayOutWidget.canvas = function() {
+ //
+ return {
+
+ allSelectedObjects: null, // Contains all the selected objets, when click and drag.
+
+ allPreviouslySelectedObjects: null,
+
+ colorPointer: 0,
+
+ goldenRatio: 0.618033988749895,
+
+ _createCanvas: function() {
+ this.normalCanvas = this._createElement("
").attr("id", "DNAcanvas");
+ $(this.canvasContainer).append(this.normalCanvas);
+ },
+
+ _initiateFabricCanvas: function() {
+ var w = this.canvasContainer.width();
+ var h = this.canvasContainer.height();
+
+ this._setCanvasArea(w, h);
+
+ this.mainFabricCanvas = new fabric.Canvas('DNAcanvas', {
+ backgroundColor: '#f5f5f5',
+ selection: false,
+ stateful: false,
+ hoverCursor: "pointer",
+ renderOnAddRemove: false,
+ })
+ .setWidth(w)
+ .setHeight(h);
+ },
+
+ };
+ }
+})(jQuery, fabric);
+var plateLayOutWidget = plateLayOutWidget || {};
+
+(function($, fabric) {
+
+ plateLayOutWidget.checkBox = function() {
+ // For those check boxes associated with every field in the tab
+ return {
+
+ globalSelectedAttributes: [],
+
+ _addCheckBox: function(field) {
+ var checkImage = $("").html(this._assets.dontImg).addClass("plate-setup-tab-check-box bg-light")
+ .data("clicked", false);
+ checkImage.data("linkedFieldId", field.id);
+ field.root.find(".plate-setup-tab-field-left-side").empty().append(checkImage);
+ this._applyCheckboxHandler(checkImage); // Adding handler for change the image when clicked
+ field.checkbox = checkImage;
+ },
+
+ _applyCheckboxHandler: function(checkBoxImage) {
+ // We add checkbox handler here, thing is it s not checkbox , its an image and we change
+ // source
+ var that = this;
+ checkBoxImage.click(function(evt, machineClick) {
+ var checkBox = $(this);
+
+ var changes = {};
+ changes[checkBox.data("linkedFieldId")] = !checkBox.data("clicked");
+
+ that.changeCheckboxes(changes);
+ });
+ },
+
+ changeSubFieldsCheckboxes: function(field, changes) {
+ var that = this;
+ var subFieldToInclude = [];
+
+ field.subFieldList.forEach(function(subField) {
+ var checkImage = subField.checkbox;
+ var fieldId = checkImage.data("linkedFieldId");
+ var clicked = checkImage.data("clicked");
+ if (fieldId in changes) {
+ clicked = Boolean(changes[fieldId]);
+ }
+ checkImage.data("clicked", clicked);
+ if (clicked) {
+ checkImage.html(that._assets.doImg);
+ subFieldToInclude.push(subField.id);
+ } else {
+ checkImage.html(that._assets.dontImg);
+ }
+ });
+ return subFieldToInclude;
+ },
+
+ changeCheckboxes: function(changes) {
+ var gsa = [];
+ var multiplexCheckedSubField = {};
+ for (var i = 0; i < this.fieldList.length; i++) {
+ var field = this.fieldList[i];
+ if (field.checkbox) {
+ if (field.subFieldList) {
+ multiplexCheckedSubField[field.id] = this.changeSubFieldsCheckboxes(field, changes);
+ }
+
+ var checkImage = field.checkbox;
+ var fieldId = checkImage.data("linkedFieldId");
+ var clicked = checkImage.data("clicked");
+ if (fieldId in changes) {
+ clicked = Boolean(changes[fieldId]);
+ }
+ checkImage.data("clicked", clicked);
+ if (clicked) {
+ gsa.push(fieldId);
+ checkImage.html(this._assets.doImg);
+ } else {
+ checkImage.html(this._assets.dontImg);
+ }
+ }
+ }
+ this.globalSelectedMultiplexSubfield = multiplexCheckedSubField;
+ this.globalSelectedAttributes = gsa;
+ this._clearPresetSelection();
+ this._colorMixer();
+ },
+
+ setSubFieldCheckboxes: function(field, fieldIds) {
+ var that = this;
+ var subFieldToInclude = [];
+ field.subFieldList.forEach(function(subField) {
+ var checkImage = subField.checkbox;
+ var fieldId = checkImage.data("linkedFieldId");
+ var clicked = fieldIds.indexOf(fieldId) >= 0;
+ checkImage.data("clicked", clicked);
+ if (clicked) {
+ checkImage.html(that._assets.doImg);
+ subFieldToInclude.push(subField.id);
+ } else {
+ checkImage.html(that._assets.dontImg);
+ }
+ });
+ return subFieldToInclude;
+ },
+
+ setCheckboxes: function(fieldIds) {
+ fieldIds = fieldIds || [];
+ var gsa = [];
+ var multiplexCheckedSubField = {};
+
+ for (var i = 0; i < this.fieldList.length; i++) {
+ var field = this.fieldList[i];
+ if (field.checkbox) {
+ // special handling for multiplex field
+ if (field.subFieldList) {
+ multiplexCheckedSubField[field.id] = this.setSubFieldCheckboxes(field, fieldIds);
+ }
+
+ var checkImage = field.checkbox;
+ var fieldId = checkImage.data("linkedFieldId");
+ var clicked = fieldIds.indexOf(fieldId) >= 0;
+ checkImage.data("clicked", clicked);
+ if (clicked) {
+ gsa.push(fieldId);
+ checkImage.html(this._assets.doImg);
+ } else {
+
+ checkImage.html(this._assets.dontImg);
+ }
+ }
+ }
+ this.globalSelectedMultiplexSubfield = multiplexCheckedSubField;
+ this.globalSelectedAttributes = gsa;
+ this._clearPresetSelection();
+ this._colorMixer();
+ }
+
+ };
+ }
+})(jQuery, fabric);
+var plateLayOutWidget = plateLayOutWidget || {};
+
+(function($, fabric) {
+
+ plateLayOutWidget.colorManager = function() {
+
+ return {
+ // See these are color pairs for the gradient.
+ colorPairs: [
+ ["#e6e6e6", "#808080"],
+ ["#66e8ff", "#0082c8"],
+ ["#ff7fb1", "#e6194b"],
+ ["#a2ffb1", "#3cb44b"],
+ ["#f784ff", "#911eb4"],
+ ["#ffe897", "#f58231"],
+ ["#6666ff", "#0000FF"],
+ ["#ffff7f", "#ffe119"],
+ ["#acffff", "#46f0f0"],
+ ["#ff98ff", "#f032e6"],
+ ["#ffffa2", "#d2f53c"],
+ ["#ffffff", "#fabebe"],
+ ["#66e6e6", "#008080"],
+ ["#ffffff", "#e6beff"],
+ ["#ffd48e", "#aa6e28"],
+ ["#e66666", "#800000"],
+ ["#ffffff", "#aaffc3"],
+ ["#e6e666", "#808000"],
+ ["#ffffff", "#ffd8b1"],
+ ["#66a9ef", "#004389"],
+ ["#ff6672", "#a7000c"],
+ ["#66db72", "#00750c"],
+ ["#b866db", "#520075"],
+ ["#ffa966", "#b64300"],
+ ["#ffff66", "#c0a200"],
+ ["#6dffff", "#07b1b1"],
+ ["#ff66ff", "#b100a7"],
+ ["#f9ff66", "#93b600"],
+ ["#ffe5e5", "#bb7f7f"],
+ ["#66a7a7", "#004141"],
+ ["#ffe5ff", "#a77fc0"],
+ ["#d19566", "#6b2f00"],
+ ["#ffffef", "#c0bb89"],
+ ["#d1ffea", "#6bc084"],
+ ["#a7a766", "#414100"],
+ ["#ffffd8", "#c09972"],
+ ["#a5ffff", "#3fc1ff"],
+ ["#ffbef0", "#ff588a"],
+ ["#e1fff0", "#7bf38a"],
+ ["#ffc3ff", "#d05df3"],
+ ["#ffffd6", "#ffc170"],
+ ["#a5a5ff", "#3f3fff"],
+ ["#ffffbe", "#ffff58"],
+ ["#ebffff", "#85ffff"],
+ ["#ffd7ff", "#ff71ff"],
+ ["#a5ffff", "#3fbfbf"],
+ ["#ffffcd", "#e9ad67"],
+ ["#ffa5a5", "#bf3f3f"],
+ ["#ffffa5", "#bfbf3f"]
+ ]
+ }
+ }
+
+})(jQuery, fabric);
+var plateLayOutWidget = plateLayOutWidget || {};
+
+(function($, fabric) {
+
+ plateLayOutWidget.createCanvasElements = function() {
+ // this class manages creating all the elements within canvas
+ return {
+
+ scaleFactor: 1,
+
+ baseSizes: {
+ spacing: 48,
+ tile_radius: 22,
+ center_radius_complete: 10,
+ center_radius_incomplete: 14,
+ label_size: 14,
+ label_spacing: 24,
+ text_size: 13,
+ stroke: 0.5,
+ gap: 2
+ },
+
+ _setCanvasArea: function(w, h) {
+ this.scaleFactor = Math.min(
+ h / (this.dimensions.rows * this.baseSizes.spacing + this.baseSizes.label_spacing),
+ w / (this.dimensions.cols * this.baseSizes.spacing + this.baseSizes.label_spacing));
+
+ var sizes = {};
+ for (var prop in this.baseSizes) {
+ sizes[prop] = this.baseSizes[prop] * this.scaleFactor;
+ }
+ this.sizes = sizes;
+ },
+
+ _canvas: function() {
+ // Those 1,2,3 s and A,B,C s
+ this._fixRowAndColumn();
+
+ // All those circles in the canvas.
+ this._putCircles();
+ },
+
+ _fixRowAndColumn: function() {
+ var cols = this.dimensions.cols;
+ var rows = this.dimensions.rows;
+
+ var spacing = this.sizes.spacing;
+ var d1 = this.sizes.label_spacing / 2;
+ var d2 = this.sizes.label_spacing + this.sizes.spacing / 2;
+ var fontSize = this.sizes.label_size;
+
+ // For column
+ var top = d1;
+ var left = d2;
+ for (var i = 1; i <= cols; i++) {
+ var tempFabricText = new fabric.IText(i.toString(), {
+ fill: 'black',
+ originX: 'center',
+ originY: 'center',
+ fontSize: fontSize,
+ top: top,
+ left: left,
+ fontFamily: '"Roboto", Arial, sans-serif',
+ selectable: false,
+ fontWeight: "400"
+ });
+ left += spacing;
+
+ this.mainFabricCanvas.add(tempFabricText);
+ }
+
+ // for row
+ top = d2;
+ left = d1;
+ for (var i = 1; i <= rows; i++) {
+ var tempFabricText = new fabric.IText(this.rowIndex[i - 1], {
+ fill: 'black',
+ originX: 'center',
+ originY: 'center',
+ fontSize: fontSize,
+ top: top,
+ left: left,
+ fontFamily: '"Roboto", Arial, sans-serif',
+ selectable: false,
+ fontWeight: "400"
+ });
+ top += spacing;
+
+ this.mainFabricCanvas.add(tempFabricText);
+ }
+ },
+
+ _putCircles: function() {
+ var cols = this.dimensions.cols;
+ var rows = this.dimensions.rows;
+
+ var tileCounter = 0;
+ for (var row = 0; row < rows; row++) {
+ for (var col = 0; col < cols; col++) {
+ var index = this.allTiles.length;
+ var tile = this._createTile(row, col);
+ tile.index = tileCounter++;
+ this.allTiles.push(tile);
+ this.mainFabricCanvas.add(tile.background);
+ this.mainFabricCanvas.add(tile.highlight);
+ this.mainFabricCanvas.add(tile.circle);
+ this.mainFabricCanvas.add(tile.circleCenter);
+ this.mainFabricCanvas.add(tile.circleText);
+ }
+ }
+
+ this._addLargeRectangleOverlay();
+ this._fabricEvents();
+ },
+
+ _createTile: function(row, col) {
+ var tile = {};
+
+ tile.visible = false;
+ tile.colorIndex = null;
+ tile.row = row;
+ tile.col = col;
+ tile.address = this.rowIndex[row] + (col + 1);
+
+ var top = (row + 1) * this.sizes.spacing;
+ var left = (col + 1) * this.sizes.spacing;
+
+ tile.background = new fabric.Circle({
+ top: top,
+ left: left,
+ radius: this.sizes.tile_radius,
+ originX: 'center',
+ originY: 'center',
+ hasControls: false,
+ hasBorders: false,
+ lockMovementX: true,
+ lockMovementY: true,
+ evented: false,
+ });
+
+ tile.background.setGradient("fill", {
+ type: "radial",
+ x1: this.sizes.tile_radius,
+ x2: this.sizes.tile_radius,
+ y1: this.sizes.tile_radius + this.sizes.gap,
+ y2: this.sizes.tile_radius + this.sizes.gap,
+ r1: this.sizes.tile_radius - this.sizes.gap,
+ r2: this.sizes.tile_radius,
+ colorStops: {
+ 0: 'rgba(0,0,0,0.1)',
+ 1: 'rgba(0,0,0,0.2)'
+ }
+ });
+
+ tile.highlight = new fabric.Rect({
+ originX: 'center',
+ originY: 'center',
+ top: top,
+ left: left,
+ width: this.sizes.spacing,
+ height: this.sizes.spacing,
+ fill: "rgba(0,0,0,0.4)",
+ evented: false,
+ visible: false
+ });
+
+ tile.circle = new fabric.Circle({
+ originX: 'center',
+ originY: 'center',
+ top: top,
+ left: left,
+ radius: this.sizes.tile_radius,
+ stroke: 'gray',
+ strokeWidth: this.sizes.stroke,
+ evented: false,
+ visible: false
+ });
+
+ tile.circleCenter = new fabric.Circle({
+ originX: 'center',
+ originY: 'center',
+ top: top,
+ left: left,
+ radius: this.sizes.center_radius_incomplete,
+ fill: "white",
+ stroke: 'gray',
+ strokeWidth: this.sizes.stroke,
+ evented: false,
+ visible: false
+ });
+
+ tile.circleText = new fabric.IText("", {
+ originX: 'center',
+ originY: 'center',
+ top: top,
+ left: left,
+ fill: 'black',
+ fontFamily: '"Roboto", Arial, sans-serif',
+ fontSize: this.sizes.text_size,
+ lockScalingX: true,
+ lockScalingY: true,
+ evented: false,
+ visible: false
+ });
+
+ return tile;
+ },
+
+ setTileComplete: function(tile, complete) {
+ if (complete) {
+ tile.circleCenter.radius = this.sizes.center_radius_complete;
+ tile.circleText.fill = "black";
+ tile.circleText.fontWeight = 'normal';
+ } else {
+ tile.circleCenter.radius = this.sizes.center_radius_incomplete;
+ tile.circleText.fill = "red";
+ tile.circleText.fontWeight = 'bold';
+ }
+ },
+
+ setTileVisible: function(tile, visible) {
+ tile.visible = visible;
+ tile.circle.visible = tile.visible;
+ tile.circleCenter.visible = tile.visible;
+ tile.circleText.visible = tile.visible;
+ },
+
+ setTileColor: function(tile, color) {
+ this.setTileVisible(tile, true);
+ tile.colorIndex = parseInt(color);
+ tile.circleText.text = String(tile.colorIndex);
+
+ if (color > 0) {
+ color = ((color - 1) % (this.colorPairs.length - 1)) + 1;
+ }
+ var colorStops = this.colorPairs[color];
+
+ tile.circle.setGradient("fill", {
+ y2: 2 * this.sizes.tile_radius,
+ colorStops: colorStops
+ });
+ },
+
+ _addLargeRectangleOverlay: function() {
+
+ this.overLay = new fabric.Rect({
+ width: 632,
+ height: 482,
+ left: 0,
+ top: 0,
+ opacity: 0.0,
+ originX: 'left',
+ originY: 'top',
+ lockMovementY: true,
+ lockMovementX: true,
+ selectable: false
+ });
+
+ this.mainFabricCanvas.add(this.overLay);
+ }
+ };
+ }
+})(jQuery, fabric);
+
+var plateLayOutWidget = plateLayOutWidget || {};
+
+(function($, fabric) {
+
+ plateLayOutWidget.createField = function() {
+ // It creates those fields in the tab , there is 4 types of them.
+ return {
+
+ _createField: function(field) {
+ switch (field.data.type) {
+ case "text":
+ this._createTextField(field);
+ break;
+
+ case "numeric":
+ this._createNumericField(field);
+ break;
+
+ case "select":
+ this._createSelectField(field);
+ break;
+
+ case "multiselect":
+ this._createMultiSelectField(field);
+ break;
+
+ case "boolean":
+ this._createBooleanField(field);
+ break;
+
+ case "multiplex":
+ this._createMultiplexField(field);
+ break;
+ }
+ },
+
+ _createTextField: function(field) {
+ var id = field.id;
+ var that = this;
+ var input = this._createElement(" ").attr("id", id)
+ .addClass("plate-setup-tab-input");
+
+ field.root.find(".plate-setup-tab-field-container").append(input);
+ that.defaultWell[id] = null;
+
+ field.parseValue = function(v) {
+ if (v) {
+ v = String(v);
+ } else {
+ v = null;
+ }
+ return v;
+ };
+
+ field.getValue = function() {
+ var v = input.val().trim();
+ if (v == "") {
+ v = null;
+ }
+ return v;
+ };
+
+ field.setValue = function(v) {
+ input.val(v);
+ };
+
+ field.getText = function(v) {
+ if (v == null) {
+ return "";
+ }
+ return v;
+ };
+
+ field.disabled = function(bool) {
+ field.input.prop("disabled", bool);
+ };
+
+ field.parseText = field.parseValue;
+
+ input.on("input", function(e, generated) {
+ field.onChange();
+ });
+
+ field.input = input;
+ },
+
+ _createOpts: function(config) {
+ var opts = {
+ allowClear: true,
+ placeholder: "select",
+ minimumResultsForSearch: 10
+ };
+ var data_specified = false;
+
+ if (config.options) {
+ opts.data = config.options;
+ data_specified = true;
+ }
+ if (config.ajax) {
+ opts.ajax = ajax;
+ data_specified = true;
+ }
+ if (!data_specified) {
+ throw "Must specify data or ajax";
+ }
+ return opts;
+ },
+
+ _createSelectField: function(field) {
+ var id = field.id;
+ var that = this;
+ var input = this._createElement(" ").attr("id", id)
+ .addClass("plate-setup-tab-select-field");
+
+ field.root.find(".plate-setup-tab-field-container").append(input);
+ that.defaultWell[id] = null;
+
+ var opts = that._createOpts(field.data);
+ var optMap = {};
+ opts.data.forEach(function(opt) {
+ optMap[opt.id] = opt;
+ });
+
+ input.select2(opts);
+
+ field.parseValue = function(value) {
+ var v = value;
+
+ if (v == "") {
+ v = null;
+ }
+ if (v == null) {
+ return null;
+ }
+ if (v in optMap) {
+ return optMap[v].id;
+ } else {
+ throw "Invalid value " + value + " for select field " + id;
+ }
+ };
+
+ field.disabled = function(bool) {
+ field.input.prop("disabled", bool);
+ };
+
+ field.getValue = function() {
+ return input.val();
+ };
+
+ field.setValue = function(v) {
+ input.val(v);
+ input.trigger("change.select2")
+ };
+
+ field.getText = function(v) {
+ if (v == null) {
+ return "";
+ }
+ return optMap[v].text;
+ };
+
+ field.parseText = function(value) {
+ var v = value;
+
+ if (v == "") {
+ v = null;
+ }
+ if (v == null) {
+ return null;
+ }
+ if (v in optMap) {
+ return optMap[v].text;
+ } else {
+ throw "Invalid text value " + value + " for select field " + id;
+ }
+ };
+
+ input.on("change", function(e, generated) {
+ field.onChange();
+ });
+
+
+ input.on('select2:unselect', function (evt) {
+ // Prevent select2 v4.0.6rc1 opening dropdown on unselect
+ input.one('select2:opening', function(e) { e.preventDefault(); });
+ });
+
+ field.input = input;
+ },
+
+ _createMultiSelectField: function(field) {
+ var id = field.id;
+ var that = this;
+ var input = this._createElement(" ").attr("id", id)
+ .addClass("plate-setup-tab-multiselect-field");
+ input.attr("multiple", "multiple");
+
+ field.root.find(".plate-setup-tab-field-container").append(input);
+ that.defaultWell[id] = null;
+
+ var separator = ",";
+ var opts = that._createOpts(field.data);
+ opts.multiple = true;
+ var optMap = {};
+ opts.data.forEach(function(opt) {
+ optMap[opt.id] = opt;
+ });
+ input.select2(opts);
+
+ field.disabled = function(bool) {
+ field.input.prop("disabled", bool);
+ };
+
+ field.parseValue = function(value) {
+ var v = value;
+ if (v && v.length) {
+ v = v.map(function(opt) {
+ if (opt in optMap) {
+ return optMap[opt].id;
+ } else {
+ throw "Invalid value " + opt + " for multiselect field " + id;
+ }
+ });
+ } else {
+ v = null;
+ }
+ return v;
+ };
+
+ field.getValue = function() {
+ var v = input.val();
+ if (v.length) {
+ return v;
+ }
+ return null;
+ };
+
+ field.setValue = function(v) {
+ v = v || [];
+ input.val(v);
+ input.trigger("change.select2");
+ };
+
+ field.getText = function(v) {
+ if (v == null) {
+ return "";
+ }
+ if (v.length > 0) {
+ return v.map(function(v) {
+ return optMap[v].text
+ }).join("; ");
+ }
+ return "";
+ };
+
+ field.multiOnChange = function(added, removed) {
+ if (added) {
+ added = added.id.toString();
+ }
+ if (removed) {
+ removed = removed.id.toString();
+ }
+ var data = {};
+ data[field.id] = {
+ multi: true,
+ added: added,
+ removed: removed
+ };
+
+ that._addAllData(data);
+ };
+
+ field.parseText = function(value) {
+ var v = value;
+ if (v && v.length) {
+ v = v.map(function(opt) {
+ if (opt in optMap) {
+ return optMap[opt].text;
+ } else {
+ throw "Invalid text value " + opt + " for multiselect field " + id;
+ }
+ });
+ } else {
+ v = null;
+ }
+ return v;
+ };
+
+ input.on("select2:select", function (e) {
+ field.multiOnChange(e.params.data, null);
+ });
+
+ input.on("select2:unselect", function (e) {
+ field.multiOnChange(null, e.params.data);
+ // Prevent select2 v4.0.6rc1 opening dropdown on unselect
+ input.one('select2:opening', function(e) { e.preventDefault(); });
+ });
+
+ field.input = input;
+
+ that._createDeleteButton(field);
+ },
+
+ _createNumericField: function(field) {
+ var id = field.id;
+ var data = field.data;
+ var that = this;
+ var input = this._createElement(" ").addClass("plate-setup-tab-input")
+ .attr("placeholder", data.placeholder || "").attr("id", id);
+
+ field.root.find(".plate-setup-tab-field-container").append(input);
+ that.defaultWell[id] = null;
+
+ // Adding unit
+ var units = data.units || [];
+ var defaultUnit = data.defaultUnit || null;
+ var unitInput = null;
+ if (defaultUnit) {
+ if (units.length) {
+ if (units.indexOf(defaultUnit) < 0) {
+ defaultUnit = units[0];
+ }
+ } else {
+ units = [defaultUnit];
+ }
+ } else {
+ if (units.length) {
+ defaultUnit = units[0];
+ }
+ }
+
+ if (units.length) {
+ field.units = units;
+ field.hasUnits = true;
+ field.defaultUnit = defaultUnit;
+ if (units.length == 1) {
+ var unitText = $("
").addClass("plate-setup-tab-unit");
+ unitText.text(defaultUnit);
+ field.root.find(".plate-setup-tab-field-container").append(unitText);
+ } else {
+ unitInput = this._createElement(" ").attr("id", id)
+ .addClass("plate-setup-tab-label-select-field");
+
+ field.root.find(".plate-setup-tab-field-container").append(unitInput);
+
+ var selected = null;
+ var unitData = units.map(function(unit) {
+ var o = {
+ id: unit,
+ text: unit
+ };
+ if (unit == defaultUnit) {
+ selected = unit;
+ }
+ return o;
+ });
+
+ var opts = {
+ data: unitData,
+ allowClear: false,
+ minimumResultsForSearch: 10
+ };
+
+ unitInput.select2(opts);
+ unitInput.val(selected);
+ }
+ }
+
+ field.disabled = function(bool) {
+ field.input.prop("disabled", bool);
+ if (unitInput) {
+ unitInput.prop("disabled", bool);
+ }
+ };
+
+ field.setUnitOpts = function(opts) {
+ field.units = opts || null;
+ field.defaultUnit = null;
+
+ var newUnits = [];
+ var selected = null;
+ if (field.units && field.units.length) {
+ field.defaultUnit = field.units[0];
+ newUnits = field.units.map(function(curUnit) {
+ var cleanUnit = {
+ id: curUnit,
+ text: curUnit
+ };
+ if (curUnit == field.defaultUnit) {
+ selected = curUnit;
+ }
+ return cleanUnit;
+ });
+ }
+
+ var newOpts = {
+ data: newUnits,
+ allowClear: false,
+ minimumResultsForSearch: 10
+ };
+ unitInput.select2("destroy");
+ unitInput.val(null);
+ unitInput.empty();
+ unitInput.select2(newOpts);
+ unitInput.val(selected);
+ };
+
+ field.parseValue = function(value) {
+ var v;
+ if ($.isPlainObject(value)) {
+ if (field.hasUnits) {
+ v = field.parseRegularValue(value.value);
+ if (v === null) {
+ return null;
+ }
+ return {
+ value: v,
+ unit: field.parseUnit(value.unit)
+ };
+ } else {
+ throw "Value must be plain numeric for numeric field " + id;
+ }
+ } else {
+ if (field.hasUnits) {
+ v = field.parseRegularValue(value);
+ if (v === null) {
+ return null;
+ }
+ return {
+ value: v,
+ unit: field.defaultUnit
+ };
+ } else {
+ return field.parseRegularValue(value);
+ }
+ }
+ };
+
+ field.getValue = function() {
+ var v = field.getRegularValue();
+
+ if ((v === null) || isNaN(v)) {
+ return null;
+ } else if (field.hasUnits) {
+ var returnVal = {
+ value: v,
+ unit: field.getUnit()
+ };
+
+ if (field.data.hasMultiplexUnit) {
+ // include unitTypeId and UnitId to returnVal
+ for (var unitTypeKey in field.data.unitMap) {
+ var unitTypeUnits = field.data.unitMap[unitTypeKey];
+ unitTypeUnits.forEach(function(unit) {
+ if (unit.text === returnVal.unit) {
+ returnVal['unitTypeId'] = unitTypeKey;
+ returnVal['unitId'] = unit.id;
+ }
+ })
+ }
+ }
+ return returnVal;
+ } else {
+ return v;
+ }
+ };
+
+ field.setValue = function(value) {
+ if (field.hasUnits) {
+ if ($.isPlainObject(value)) {
+ field.setUnit(value.unit || field.defaultUnit);
+ field.setRegularValue(value.value);
+
+ } else {
+ field.setRegularValue(value);
+ field.setUnit(field.defaultUnit)
+ }
+ } else {
+ field.setRegularValue(value);
+ }
+ };
+
+ field.parseRegularValue = function(value) {
+ if (value == null) {
+ return null;
+ }
+ var v = String(value).trim();
+ if (v === "") {
+ return null;
+ }
+ v = Number(value);
+ if (isNaN(v)) {
+ throw "Invalid value " + value + " for numeric field " + id;
+ }
+ return v;
+ };
+
+ field.getRegularValue = function() {
+ var v = input.val().trim();
+ if (v == "") {
+ v = null;
+ } else {
+ v = Number(v);
+ }
+ return v;
+ };
+
+ field.setRegularValue = function(value) {
+ input.val(value);
+ };
+
+ field.parseUnit = function(unit) {
+ if (unit == null || unit === "") {
+ return field.defaultUnit;
+ }
+ for (var i = 0; i < units.length; i++) {
+ if (unit.toLowerCase() == units[i].toLowerCase()) {
+ return units[i];
+ }
+ }
+ throw "Invalid unit " + unit + " for field " + id;
+ };
+
+ field.getUnit = function() {
+ if (unitInput) {
+ return unitInput.val();
+ } else {
+ return field.defaultUnit;
+ }
+ };
+
+ field.setUnit = function(unit) {
+ if (unitInput) {
+ unit = unit || field.defaultUnit;
+ unitInput.val(unit);
+ unitInput.trigger("change.select2");
+ }
+ };
+
+ // val now contains unit
+ field.getText = function(val) {
+ if (typeof (val) === 'object' && val) {
+ var v = val.value;
+ var u = val.unit;
+ if (v == null) {
+ return "";
+ }
+ v = v.toString();
+ if (!u) {
+ u = defaultUnit;
+ }
+ if (u) {
+ v = v + " " + u;
+ }
+ return v;
+ } else {
+ return field.getRegularText(val);
+ }
+ };
+
+ field.getRegularText = function(v) {
+ if (v == null) {
+ return "";
+ }
+ v = v.toString();
+ return v;
+ };
+
+ field.parseText = function(v) {
+ var textVal = field.parseValue(v);
+ if (textVal && typeof (textVal) === "object") {
+ return textVal.value + textVal.unit;
+ } else if (textVal) {
+ return textVal
+ } else {
+ return null;
+ }
+ };
+
+ input.on("input", function() {
+ var v = field.getRegularValue();
+ if (isNaN(v)) {
+ //flag field as invalid
+ input.addClass("invalid");
+ } else {
+ input.removeClass("invalid");
+ }
+ field.onChange();
+ });
+ if (unitInput) {
+ unitInput.on("change", function() {
+ field.onChange();
+ });
+ }
+
+ field.input = input;
+ field.unitInput = unitInput;
+ },
+
+ _createBooleanField: function(field) {
+ var id = field.id;
+ var that = this;
+ var input = this._createElement(" ").attr("id", id)
+ .addClass("plate-setup-tab-select-field");
+ that.defaultWell[id] = null;
+
+ field.root.find(".plate-setup-tab-field-container").append(input);
+ var tval = {
+ id: "true",
+ text: "true"
+ };
+ var fval = {
+ id: "false",
+ text: "false"
+ };
+ var opts = {
+ data: [tval, fval],
+ placeholder: "select",
+ allowClear: true,
+ minimumResultsForSearch: -1
+ };
+
+ input.select2(opts);
+
+ field.disabled = function(bool) {
+ field.input.prop("disabled", bool);
+ };
+
+ field.parseValue = function(value) {
+ if (value == null) {
+ return null;
+ }
+ var v = String(value).trim().toLowerCase();
+ if (v == "true") {
+ v = true;
+ } else if (v == "false") {
+ v = false;
+ } else if (v == "") {
+ v = null;
+ } else {
+ throw "Invalid value " + value + " for boolean field " + id;
+ }
+ return v;
+ };
+
+ field.getValue = function() {
+ var v = input.val();
+ switch (v) {
+ case "true":
+ return true;
+ case "false":
+ return false;
+ default:
+ return null;
+ }
+ };
+
+ field.setValue = function(v) {
+ if (v == true || v == "true") {
+ v = "true";
+ } else if (v == false || v == "false") {
+ v = "false";
+ } else {
+ v = null;
+ }
+ input.val(v);
+ input.trigger("change.select2");
+ };
+
+ field.getText = function(v) {
+ if (v == null) {
+ return "";
+ }
+ return v.toString();
+ };
+
+ field.parseText = field.parseValue;
+
+ input.on("change", function(e) {
+ field.onChange();
+ });
+
+
+ input.on('select2:unselect', function (evt) {
+ // Prevent select2 v4.0.6rc1 opening dropdown on unselect
+ input.one('select2:opening', function(e) { e.preventDefault(); });
+ });
+
+ field.input = input;
+ },
+
+ _createMultiplexField: function(field) {
+ var that = this;
+ // make correct multiplex data
+ this._createMultiSelectField(field);
+ // overwrite default well for multiplex field
+ that.defaultWell[field.id] = [];
+
+ // single select
+ var nameContainer1 = that._createElement("
").addClass("plate-setup-tab-name-singleSelect").text("Select to edit");
+ var fieldContainer1 = that._createElement("
").addClass("plate-setup-tab-field-container-singleSelect");
+ field.root.find(".plate-setup-tab-field-right-side").append(nameContainer1, fieldContainer1);
+
+ field.singleSelect = this._createElement(" ").attr("id", field.id + "SingleSelect")
+ .addClass("plate-setup-tab-multiplex-single-select-field");
+
+ field.singleSelect.appendTo(fieldContainer1);
+
+ field.singleSelectValue = function() {
+ return field.singleSelect.val();
+ };
+
+ var setSingleSelectOptions = function(v, selected_v) {
+ var opts = {
+ allowClear: false,
+ placeholder: "select",
+ minimumResultsForSearch: 10,
+ data: v || []
+ };
+ if (!selected_v) {
+ if (opts.data.length) {
+ selected_v = opts.data[0].id;
+ } else {
+ selected_v = null;
+ }
+ }
+ if (field.singleSelect.hasClass("select2-hidden-accessible")) {
+ field.singleSelect.select2("destroy");
+ }
+ field.singleSelect.val(null);
+ field.singleSelect.empty();
+ field.singleSelect.select2(opts);
+ field.singleSelect.val(selected_v);
+ field.singleSelect.prop("disabled", opts.data.length == 0);
+ field.singleSelect.trigger("change.select2");
+ field.singleSelect.on("change.select2", singleSelectChange);
+ };
+
+ var singleSelectChange = function() {
+ var v = field.singleSelectValue();
+
+ field.updateSubFieldUnitOpts(v);
+
+ var curData = field.detailData || [];
+ var curSubField = null;
+ curData.forEach(function(val) {
+ if (val[field.id] === v) {
+ curSubField = val;
+ }
+ });
+
+ if (curSubField) {
+ // setvalue for subfield
+ field.subFieldList.forEach(function(subField) {
+ subField.disabled(false);
+ subField.setValue(curSubField[subField.id]);
+ });
+ } else {
+ field.subFieldList.forEach(function(subField) {
+ subField.disabled(true);
+ subField.setValue(null);
+ });
+ }
+ that.readOnlyHandler();
+ };
+
+ setSingleSelectOptions([]);
+
+ field._changeMultiFieldValue = function(added, removed) {
+ var newSubFieldValue = {};
+ for (var subFieldName in field.data.multiplexFields) {
+ var subFieldId = field.data.multiplexFields[subFieldName].id;
+ newSubFieldValue[subFieldId] = null;
+ }
+
+ var val;
+ if (added) {
+ if (added.value) {
+ val = added.value;
+ } else {
+ newSubFieldValue[field.id] = added.id;
+ val = newSubFieldValue;
+ }
+ added = {
+ id: added.id,
+ value: val
+ };
+ }
+
+ if (removed) {
+ if (removed.value) {
+ val = removed.value;
+ } else {
+ newSubFieldValue[field.id] = removed.id;
+ val = newSubFieldValue;
+ }
+ removed = {
+ id: removed.id,
+ value: val
+ };
+ }
+
+ var data = {};
+ data[field.id] = {
+ multi: true,
+ added: added,
+ removed: removed
+ };
+ that._addAllData(data);
+ };
+
+ var multiselectSetValue = field.setValue;
+
+ // overwrite multiplex set value
+ field.setValue = function(v) {
+ // used to keep track of initially loaded multiplex data
+ field.detailData = v;
+ var multiselectValues = null;
+ if (v && v.length) {
+ multiselectValues = v.map(function(val) {
+ return val[field.id]
+ });
+ }
+
+ multiselectSetValue(multiselectValues);
+ var newOptions = field.input.select2('data') || [];
+ setSingleSelectOptions(newOptions);
+ singleSelectChange();
+ };
+
+ field.disabled = function(bool) {
+ field.input.prop("disabled", bool);
+ field.subFieldList.forEach(function(subField) {
+ subField.disabled(bool);
+ });
+ if (bool) {
+ nameContainer1.text("Select to inspect");
+ } else {
+ nameContainer1.text("Select to edit");
+ }
+ };
+
+ field.parseValue = function(value) {
+ var v = value;
+ if (v && v.length) {
+ v = v.map(function(opt) {
+ var valMap = {};
+ valMap[field.id] = opt[field.id];
+ for (var subFieldId in opt) {
+ field.subFieldList.forEach(function(subField) {
+ if (subField.id === subFieldId) {
+ valMap[subField.id] = subField.parseValue(opt[subFieldId]);
+ }
+ });
+ }
+ return valMap;
+ });
+ } else {
+ v = null;
+ }
+ return v;
+ };
+
+ field.updateSubFieldUnitOpts = function(val) {
+ var curOpts;
+ field.data.options.forEach(function(opt) {
+ if (opt.id === val) {
+ curOpts = opt;
+ }
+ });
+ field.subFieldList.forEach(function(subField) {
+ if (subField.data.hasMultiplexUnit) {
+ if (curOpts && curOpts.hasOwnProperty("unitOptions")) {
+ subField.setUnitOpts(curOpts.unitOptions[subField.id]);
+ } else {
+ subField.setUnitOpts(null);
+ }
+ }
+ })
+ };
+
+ field.multiOnChange = function(added, removed) {
+ field._changeMultiFieldValue(added, removed);
+ var v = field.getValue();
+ var curData = field.detailData;
+ var curIds = [];
+ var curOpt = null;
+ //reshape data for saveback
+ if (curData) {
+ curIds = curData.map(function(val) {
+ return val[field.id]
+ });
+ }
+
+ var newMultiplexVal = [];
+ var selectList = [];
+ if (v) {
+ v.forEach(function(selectedVal) {
+ if (curData) {
+ curData.forEach(function(val) {
+ if (val[field.id] === selectedVal) {
+ newMultiplexVal.push(val)
+ }
+ });
+ }
+ // cases when adding new data
+ if (curIds.indexOf(selectedVal) < 0) {
+ var newVal = {};
+ newVal[field.id] = selectedVal;
+
+ field.updateSubFieldUnitOpts(selectedVal);
+ field.subFieldList.forEach(function(subfield) {
+ // special handling for subfield which has multiplexUnit
+ if (subfield.hasUnits) {
+ if (subfield.data.hasMultiplexUnit) {
+ subfield.disabled(false);
+ field.data.options.forEach(function(opt) {
+ if (opt.id === selectedVal) {
+ var val = {
+ value: null,
+ unit: subfield.units[0]
+ };
+ newVal[subfield.id] = subfield.parseValue(val);
+ }
+ });
+ } else {
+ if (subfield.data.units) {
+ if (subfield.data.units.length > 1) {
+ subfield.disabled(false);
+ }
+ }
+ var val = {
+ value: null,
+ unit: subfield.defaultUnit
+ };
+ newVal[subfield.id] = subfield.parseValue(val);
+ }
+ } else {
+ newVal[subfield.id] = subfield.parseValue(null);
+ }
+ });
+ newMultiplexVal.push(newVal);
+ }
+ });
+
+ // make data for single select options
+ v.forEach(function(selectId) {
+ field.data.options.forEach(function(opt) {
+ if (opt.id === selectId) {
+ selectList.push(opt);
+ }
+ });
+ });
+ // set the newest selected to be the current obj
+ curOpt = selectList[v.length - 1].id;
+ }
+
+ field.detailData = newMultiplexVal;
+ setSingleSelectOptions(selectList, curOpt);
+ singleSelectChange();
+ };
+
+ field.getText = function(v) {
+ if (v === null) {
+ return "";
+ }
+ // get subfields that is selected from the checkbox
+ if (field.id in that.globalSelectedMultiplexSubfield) {
+ var checkedSubfields = that.globalSelectedMultiplexSubfield[field.id];
+ var returnVal = [];
+ for (var valIdx in v) {
+ var subV = v[valIdx];
+ var subText = [];
+ for (var optId in field.data.options) {
+ var opt = field.data.options[optId];
+ if (opt.id === subV[field.id]) {
+ subText.push(opt.text);
+ }
+ }
+ field.subFieldList.forEach(function(subField) {
+ if (checkedSubfields.indexOf(subField.id) >= 0) {
+ var x = subField.getText(subV[subField.id]);
+ subText.push(subField.name + ": " + x);
+ }
+ });
+ returnVal.push("{" + subText.join(", ") + "}");
+ }
+ return returnVal.join(";");
+ }
+ };
+
+ field.parseText = function(v) {
+ if (v === null) {
+ return "";
+ } else {
+ var returnVal = [];
+ for (var valIdx in v) {
+ var subV = v[valIdx];
+ var subText = [];
+ for (var optId in field.data.options) {
+ var opt = field.data.options[optId];
+ if (opt.id === subV[field.id]) {
+ subText.push(opt.text);
+ }
+ }
+ field.subFieldList.forEach(function(subField) {
+ var x = subField.getText(subV[subField.id]);
+ if (x) {
+ subText.push(x);
+ }
+ });
+ returnVal.push(subText);
+ }
+ return returnVal;
+ }
+ };
+
+ field.checkMultiplexCompletion = function(valList) {
+ var valCount = 0;
+ var completionPct = 0;
+ var include = false;
+
+ function getSubfieldStatus(vals) {
+ var req = 0;
+ var fill = 0;
+ for (var subFieldId in field.subFieldList) {
+ var subField = field.subFieldList[subFieldId];
+ var curVal = vals[subField.id];
+ if (subField.required) {
+ include = true;
+ req++;
+ if (typeof curVal === 'object' && curVal) {
+ if (curVal.value) {
+ fill++;
+ }
+ } else if (curVal) {
+ fill++;
+ }
+ }
+ }
+ return fill / req;
+ }
+
+ // for cases has value in multiplex field
+ if (valList) {
+ if (valList.length > 0) {
+ for (var idx in valList) {
+ valCount++;
+ var vals = valList[idx];
+ completionPct += getSubfieldStatus(vals);
+ }
+ } else if (field.required) {
+ include = true;
+ valCount = 1;
+ }
+ } else if (field.required) {
+ include = true;
+ valCount = 1;
+ }
+
+ return {
+ include: include,
+ completionPct: completionPct / valCount
+ };
+ };
+
+ // valList contains all of the vals for selected val
+ field.applyMultiplexSubFieldColor = function(valList) {
+ function updateSubFieldWarningMap(vals) {
+ for (var subFieldId in field.subFieldList) {
+ var subField = field.subFieldList[subFieldId];
+ // loop through each well's multiplexval list
+ if (vals === null) {
+ if (field.required && subField.required) {
+ subFieldWarningMap[subField.id].warningStatus.push(true);
+ }
+ } else if (typeof (vals) === "object") {
+ if (vals.length === 0) {
+ if (field.required && subField.required) {
+ subFieldWarningMap[subField.id].warningStatus.push(true);
+ }
+ } else {
+ for (var multiplexIdx in vals) {
+ var curVal = vals[multiplexIdx][subField.id];
+ if (subField.required) {
+ if (typeof (curVal) === 'object' && curVal) {
+ if (!curVal.value) {
+ subFieldWarningMap[subField.id].warningStatus.push(true);
+ } else {
+ subFieldWarningMap[subField.id].warningStatus.push(false);
+ }
+ } else if (!curVal) {
+ subFieldWarningMap[subField.id].warningStatus.push(true);
+ } else {
+ subFieldWarningMap[subField.id].warningStatus.push(false);
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ var subFieldWarningMap = {};
+ field.subFieldList.forEach(function(subField) {
+ if (subField.required) {
+ subFieldWarningMap[subField.id] = {
+ field: subField,
+ warningStatus: []
+ };
+ }
+ });
+
+ valList.forEach(function(multiplexVals) {
+ updateSubFieldWarningMap(multiplexVals);
+ });
+ // turn off main field when all subfield are filled
+
+ var requiredSubField = [];
+ var mainFieldStatus = [];
+ for (var subFieldId in subFieldWarningMap) {
+ var subField = subFieldWarningMap[subFieldId].field;
+ if (subFieldWarningMap[subFieldId].warningStatus.indexOf(true) >= 0) {
+ var text = subField.name + " is a required subfield for " + field.name + ", please make sure all " + field.name + " have " + subField.name;
+ if (field.required) {
+ that.fieldWarningMsg(subField, text, true);
+ mainFieldStatus.push(true);
+ } else {
+ that.fieldWarningMsg(subField, text, true);
+ mainFieldStatus.push(true);
+ }
+ } else {
+ that.fieldWarningMsg(subField, "none", false);
+ mainFieldStatus.push(false);
+ }
+ }
+ var mainFieldWarning = false;
+ if (mainFieldStatus.indexOf(true) < 0) {
+ mainFieldWarning = false;
+ } else {
+ mainFieldWarning = true;
+ }
+ var warningText;
+ if (field.required) {
+ warningText = field.name + " is a required field, please also fix missing required subfield(s) below";
+ } else {
+ warningText = field.name + " is not a required field, please fix missing required subfield(s) below or remove selected " + field.name;
+ }
+ that.fieldWarningMsg(field, warningText, mainFieldWarning);
+ };
+
+ field.parseMainFieldVal = function(val) {
+ var optMap = field.data.options;
+ for (var idx = 0; idx < optMap.length; idx++) {
+ var curOpt = optMap[idx];
+ if (curOpt.id === val) {
+ return curOpt.text
+ }
+ }
+ };
+ },
+
+ _deleteDialog: function(field) {
+ var that = this;
+
+ var valMap = field.allSelectedMultipleVal;
+ var valToRemove;
+ if (valMap) {
+ valToRemove = Object.keys(valMap);
+ } else {
+ valToRemove = [];
+ }
+
+
+ var dialogDiv = $("
").addClass("delete-dialog modal");
+ $('body').append(dialogDiv);
+
+ function killDialog() {
+ dialogDiv.hide();
+ dialogDiv.remove();
+ }
+
+ var dialogContent = $("
").addClass("modal-content").appendTo(dialogDiv);
+ var tableArea = $("
").appendTo(dialogContent);
+ var buttonRow = $("
").addClass("dialog-buttons").css("justify-content", "flex-end").appendTo(dialogContent);
+
+ if (valToRemove.length > 0) {
+ // apply CSS property for table
+ $("
").text(field.name + " in selected wells: choose items to delete and click the delete button below").appendTo(tableArea);
+
+ var table = that._deleteDialogTable(field, valMap);
+ table.appendTo(tableArea);
+ table.addClass("plate-popout-table");
+ table.find('td').addClass("plate-popout-td");
+ table.find('th').addClass("plate-popout-th");
+ table.find('tr').addClass("plate-popout-tr");
+ if (!that.readOnly) {
+ var deleteCheckedButton = $("Delete Checked Items ");
+ buttonRow.append(deleteCheckedButton);
+ deleteCheckedButton.click(function() {
+ table.find("input:checked").each(function() {
+ var val = this.value;
+ field.multiOnChange(null, {id: val});
+ });
+ // refresh selected fields after updating the multiplex field value
+ that.decideSelectedFields();
+ killDialog();
+ });
+ }
+
+ } else {
+ $("
").text("No " + field.name + " in the selected wells").appendTo(tableArea);
+ }
+
+ var cancelButton = $("Cancel ");
+ buttonRow.append(cancelButton);
+ cancelButton.click(killDialog);
+
+ dialogDiv.show();
+
+ window.onclick = function(event) {
+ if (event.target == dialogDiv[0]) {
+ killDialog();
+ }
+ }
+ },
+
+ _deleteDialogTable: function(field, valMap) {
+ var that = this;
+ var colName = [field.name, "Counts"]; //Added because it was missing... no idea what the original should have been
+ if (!that.readOnly) {
+ colName.push("Delete");
+ }
+ var table = $('');
+ var thead = $(' ').appendTo(table);
+ var tr = $(' ').appendTo(thead);
+
+ tr.append(colName.map(function(text) {
+ return $(' ').text(text);
+ }));
+
+ var tbody = $(" ").appendTo(table);
+
+ field.data.options.forEach(function(opt) {
+ if (opt.id in valMap) {
+ var tr = $(' ').appendTo(tbody);
+ var checkbox = $(" ").prop("value", opt.id);
+ $(" ").text(opt.text).appendTo(tr);
+ $(" ").text(valMap[opt.id]).appendTo(tr);
+ if (!that.readOnly) {
+ $(" ").append(checkbox).appendTo(tr);
+ }
+ }
+ });
+
+ return table;
+ },
+
+ _createDeleteButton: function(field) {
+ var that = this;
+ var deleteButton = $(" ").addClass("plate-setup-remove-all-button");
+ deleteButton.id = field.id + "Delete";
+ deleteButton.text("Manage " + field.name + "...");
+ var buttonContainer = that._createElement("
").addClass("plate-setup-remove-all-button-container");
+ buttonContainer.append(deleteButton);
+
+ field.deleteButton = deleteButton;
+ field.root.find(".plate-setup-tab-field-right-side").append(buttonContainer);
+
+ deleteButton.click(function() {
+ that._deleteDialog(field);
+ });
+ }
+
+ };
+ }
+})(jQuery, fabric);
+var plateLayOutWidget = plateLayOutWidget || {};
+
+(function($, fabric) {
+
+ plateLayOutWidget.engine = function(THIS) {
+ // Methods which look after data changes and stack up accordingly
+ // Remember THIS points to plateLayOutWidget and 'this' points to engine
+ // Use THIS to refer parent this.
+ return {
+ engine: {
+
+ derivative: {},
+ colorMap: new Map(),
+ stackUpWithColor: {},
+ stackPointer: 2,
+
+ wellEmpty: function(well) {
+ for (var prop in well) {
+ var curVal = well[prop];
+ if (curVal !== null && curVal !== undefined) {
+ if (Array.isArray(curVal)) {
+ if (curVal.length > 0) {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+ }
+ return true;
+ },
+
+ searchAndStack: function() {
+ // This method search and stack the change we made.
+ this.stackUpWithColor = {};
+ this.stackPointer = 1;
+ var derivativeJson = {};
+ for (var idx in this.derivative) {
+ var data = this.derivative[idx];
+ var wellData = {};
+ for (var i = 0; i < THIS.globalSelectedAttributes.length; i++) {
+ var attr = THIS.globalSelectedAttributes[i];
+
+ if (attr in THIS.globalSelectedMultiplexSubfield) {
+ var selectedSubFields = THIS.globalSelectedMultiplexSubfield[attr];
+ var newMultiplexVal = [];
+ for (var multiplexIdx in data[attr]) {
+ var curMultiplexVals = data[attr][multiplexIdx];
+ var newVal = {};
+ newVal[attr] = curMultiplexVals[attr];
+ selectedSubFields.forEach(function(subFieldId) {
+ newVal[subFieldId] = curMultiplexVals[subFieldId];
+ });
+ newMultiplexVal.push(newVal);
+ }
+ wellData[attr] = newMultiplexVal;
+ } else {
+ if (data[attr] != null) {
+ wellData[attr] = data[attr];
+ }
+ }
+ }
+ if ($.isEmptyObject(wellData)) {
+ derivativeJson[idx] = null;
+ } else {
+ derivativeJson[idx] = JSON.stringify(wellData);
+ }
+ }
+
+ while (!$.isEmptyObject(derivativeJson)) {
+ var keys = Object.keys(derivativeJson).map(function(k) {
+ return parseFloat(k, 10);
+ });
+ keys.sort(function(a, b) {
+ return a - b;
+ });
+
+ var refDerivativeIndex = keys[0];
+ var referenceDerivative = derivativeJson[refDerivativeIndex];
+ var arr = [];
+
+ if (!referenceDerivative) {
+ // if no checked box has value, push it to first spot
+ if (this.stackUpWithColor[0]) {
+ this.stackUpWithColor[0].push(refDerivativeIndex);
+ } else {
+ this.stackUpWithColor[0] = [refDerivativeIndex];
+ }
+
+ delete derivativeJson[refDerivativeIndex];
+ } else {
+ // if checked boxes have values
+ for (var i = 0; i < keys.length; i++) {
+ var idx = keys[i];
+ if (referenceDerivative == derivativeJson[idx]) {
+ arr.push(idx);
+ this.stackUpWithColor[this.stackPointer] = arr;
+ delete derivativeJson[idx];
+ }
+ }
+ if (arr.length > 0)
+ this.stackPointer++;
+ }
+ }
+ },
+
+ applyColors: function() {
+
+ var wholeNoTiles = 0;
+ var wholePercentage = 0;
+
+ THIS.addBottomTableHeadings();
+
+ for (var i = 0; i < THIS.allTiles.length; i++) {
+ var tile = THIS.allTiles[i];
+ THIS.setTileVisible(tile, false);
+ }
+
+ for (var color = 0; color < this.stackPointer; color++) {
+ var arr = this.stackUpWithColor[color];
+ if (arr) {
+ THIS.addBottomTableRow(color, arr);
+
+ for (var tileIndex in arr) {
+ wholeNoTiles++;
+ var index = this.stackUpWithColor[color][tileIndex];
+ var tile = THIS.allTiles[index];
+ var well = this.derivative[index];
+ this.colorMap.set(index, color);
+ THIS.setTileColor(tile, color);
+ // Checks if all the required fields are filled
+ var completion = this.checkCompletion(well, tile);
+ THIS.setTileComplete(tile, completion == 1);
+ wholePercentage = wholePercentage + completion;
+ }
+ }
+ }
+
+ wholePercentage = Math.floor(100 * wholePercentage / wholeNoTiles);
+
+ if (isNaN(wholePercentage)) {
+ THIS.overLayTextContainer.text("Completion Percentage: 0%");
+ } else {
+ THIS.overLayTextContainer.text("Completion Percentage: " + wholePercentage + "%");
+ }
+ },
+
+ checkCompletion: function(wellData, tile) {
+ var req = 0;
+ var fill = 0;
+ for (var i = 0; i < THIS.fieldList.length; i++) {
+ var field = THIS.fieldList[i];
+ if (field.checkMultiplexCompletion) {
+ // also apply color
+ var multiplexStatus = field.checkMultiplexCompletion(wellData[field.id]);
+ if (multiplexStatus.include) {
+ fill += multiplexStatus.completionPct;
+ req++;
+ }
+ } else {
+ if (field.required) {
+ req++;
+ if (wellData[field.id] !== null) {
+ fill++;
+ }
+ }
+ }
+ }
+ if (req === fill) {
+ return 1;
+ }
+ return fill / req;
+ },
+ }
+ }
+ }
+})(jQuery, fabric);
+var plateLayOutWidget = plateLayOutWidget || {};
+
+(function($, fabric) {
+
+ plateLayOutWidget.fabricEvents = function() {
+ // This object contains Menu items and how it works;
+ return {
+ colorToIndex: {},
+ startCoords: {
+ x: 0,
+ y: 0
+ },
+ focalWell: {
+ row: 0,
+ col: 0
+ },
+ selectedAreas: [],
+
+ _clickCoords: function(evt) {
+ //Get XY Coords for a given event.
+ var rect = evt.e.target.getBoundingClientRect();
+ return {
+ x: evt.e.clientX - rect.left,
+ y: evt.e.clientY - rect.top
+ };
+ },
+
+ _fabricEvents: function() {
+ // Set up event handling.
+ var that = this;
+
+ $(that.target).on("getPlates", function(evt, data) {
+ // This method should be compatable to redo/undo.
+ that.getPlates(JSON.parse(data));
+ });
+
+ that.mainFabricCanvas.on("mouse:down", function(evt) {
+ // Start selecting new area
+ that.selecting = true;
+ var coords = that._clickCoords(evt);
+
+ var areas = that.selectedAreas.slice();
+ var focalWell = that.focalWell;
+ var startCoords = that._wellToCoords(focalWell, true);
+ var rect = that._coordsToRect(startCoords, coords);
+
+ if (evt.e.ctrlKey) {
+ //adding new area
+ startCoords = coords;
+ rect = that._coordsToRect(startCoords, coords);
+ focalWell = that._coordsToWell(startCoords);
+ if (evt.e.shiftKey) {
+ //replacing existing areas
+ areas = [that._rectToArea(rect)];
+ } else {
+ areas.push(that._rectToArea(rect));
+ }
+ } else {
+ if (evt.e.shiftKey) {
+ //Altering last area
+ areas[areas.length - 1] = that._rectToArea(rect);
+ } else {
+ //Creating new area
+ startCoords = coords;
+ rect = that._coordsToRect(startCoords, coords);
+ focalWell = that._coordsToWell(startCoords);
+ areas = [that._rectToArea(rect)];
+ }
+ }
+
+ that.startCoords = startCoords;
+ that.setSelection(areas, focalWell);
+ that.mainFabricCanvas.renderAll();
+ });
+
+ that.mainFabricCanvas.on("mouse:move", function(evt) {
+ if (that.selecting) {
+ // continue selecting new area
+ var areas = that.selectedAreas.slice();
+ var endCoords = that._clickCoords(evt);
+ var rect = that._coordsToRect(that.startCoords, endCoords);
+ var area = that._rectToArea(rect);
+ if (area) {
+ areas[areas.length - 1] = area;
+ }
+
+ that.setSelection(areas, that.focalWell);
+ that.mainFabricCanvas.renderAll();
+ }
+
+ });
+
+ that.mainFabricCanvas.on("mouse:up", function(evt) {
+ // finish selecting new area
+ that.selecting = false;
+ var areas = that.selectedAreas.slice();
+ var endCoords = that._clickCoords(evt);
+ var rect = that._coordsToRect(that.startCoords, endCoords);
+ var area = that._rectToArea(rect);
+ if (area) {
+ areas[areas.length - 1] = area;
+ }
+
+ that.setSelection(areas, that.focalWell);
+ that.decideSelectedFields();
+ that.mainFabricCanvas.renderAll();
+ that._trigger("selectedWells", null, {selectedAddress: that.getSelectedAddress()});
+ if (that.options.scrollToGroup === undefined || that.options.scrollToGroup) {
+ that.selectObjectInBottomTab();
+ }
+ });
+ },
+
+ setSelection: function(areas, focalWell) {
+ this.selectedAreas = areas;
+ this.focalWell = focalWell;
+ this.allSelectedObjects = this._areasToTiles(areas);
+ this._setSelectedTiles();
+ this._setFocalWellRect(this.focalWell);
+ document.activeElement.blur();
+ },
+
+ _setFocalWellRect: function(well) {
+ var flag;
+ // check if not allow to add or delete existing wells
+ if (this.disableAddDeleteWell) {
+ var address = this.locToAddress({
+ r: well.row,
+ c: well.col
+ });
+ if (this.addressAllowToEdit.indexOf(address) < 0) {
+ flag = false;
+ this.setFieldsDisabled(true);
+ } else {
+ flag = true;
+ this.setFieldsDisabled(false);
+ }
+ } else if (well) {
+ flag = true;
+ }
+
+ if (flag) {
+ var rect = this._areaToRect(this._wellToArea(well));
+ var strokeWidth = 2;
+ if (this.focalWellRect) {
+ //update focalWellRect
+ this.focalWellRect.top = rect.top;
+ this.focalWellRect.left = rect.left;
+ this.focalWellRect.width = rect.width - strokeWidth;
+ this.focalWellRect.height = rect.height - strokeWidth;
+ } else {
+ //create focalWellRect
+ this.focalWellRect = new fabric.Rect({
+ width: rect.width - strokeWidth,
+ height: rect.height - strokeWidth,
+ left: rect.left,
+ top: rect.top,
+ fill: null,
+ strokeWidth: strokeWidth,
+ stroke: "black",
+ selectable: false
+ });
+ this.mainFabricCanvas.add(this.focalWellRect);
+ }
+ } else {
+ //clear focalWellRect
+ this.mainFabricCanvas.remove(this.focalWellRect);
+ this.focalWellRect = null;
+ }
+ },
+
+ _setSelectedTiles: function() {
+ // Update selected tile display only
+ var selectedTiles = this.allSelectedObjects;
+ this.allTiles.forEach(function(tile) {
+ var selected = selectedTiles.indexOf(tile) >= 0;
+ tile.highlight.visible = selected;
+ })
+ },
+
+ _getSelectedWells: function() {
+ var that = this;
+ return this.allSelectedObjects.map(function(tile) {
+ var well = that.engine.derivative[tile.index];
+ if (!well) {
+ well = that.defaultWell;
+ }
+ return well;
+ });
+ },
+
+ _getCommonFields: function(wells) {
+ if (wells.length) {
+ var referenceWell = wells[0];
+ var referenceFields = $.extend(true, {}, referenceWell);
+ for (var i = 1; i < wells.length; i++) {
+ var fields = wells[i];
+ for (var field in referenceFields) {
+ if (Array.isArray(referenceFields[field])) {
+ var refArr = referenceFields[field];
+ var agrArr = [];
+ for (var j = 0; j < refArr.length; j++) {
+ var v = refArr[j];
+ if (v && typeof (v) === "object") {
+ if (this.containsObject(v, fields[field])) {
+ agrArr.push(v);
+ }
+ } else {
+ if ($.inArray(v, fields[field]) >= 0) {
+ agrArr.push(v);
+ }
+ }
+ }
+ referenceFields[field] = agrArr;
+ } else {
+ if (fields[field] && typeof (fields[field]) === "object" && referenceFields[field] && typeof (referenceFields[field]) === "object") {
+ if ((fields[field].value !== referenceFields[field].value) || (fields[field].unit !== referenceFields[field].unit)) {
+ delete referenceFields[field];
+ }
+ } else if (referenceFields[field] != fields[field]) {
+ delete referenceFields[field];
+ }
+ }
+ }
+ }
+ return referenceFields
+ } else {
+ return {};
+ }
+ },
+
+ containsObject: function(obj, list) {
+ var equality = [];
+ if (list) {
+ list.forEach(function(val) {
+ //evaluate val and obj
+ var evaluate = [];
+ Object.keys(val).forEach(function(listKey) {
+ if (Object.keys(obj).indexOf(listKey) >= 0) {
+ var curVal = val[listKey];
+ if (typeof (curVal) === 'object' && curVal) {
+ if (obj[listKey]) {
+ evaluate.push((curVal.unit === obj[listKey].unit) && (curVal.value === obj[listKey].value));
+ } else {
+ // when obj[listKey] is null but curVal is not
+ evaluate.push(false);
+ }
+ } else {
+ evaluate.push(curVal === obj[listKey]);
+ }
+ }
+ });
+ equality.push(evaluate.indexOf(false) < 0);
+ });
+ return equality.indexOf(true) >= 0;
+ } else {
+ return false;
+ }
+ },
+
+ _getCommonWell: function(wells) {
+ if (wells.length) {
+ var referenceWell = wells[0];
+ var referenceFields = $.extend(true, {}, referenceWell);
+ for (var i = 1; i < wells.length; i++) {
+ var well = wells[i];
+ var fields = well;
+ for (var field in referenceFields) {
+ if (Array.isArray(referenceFields[field])) {
+ var refArr = referenceFields[field];
+ var agrArr = [];
+ for (var j = 0; j < refArr.length; j++) {
+ var v = refArr[j];
+ // for multiplex field
+ if (typeof (refArr[j]) === "object") {
+ if (this.containsObject(v, fields[field])) {
+ agrArr.push(v);
+ }
+ } else {
+ if ($.inArray(v, fields[field]) >= 0) {
+ agrArr.push(v);
+ }
+ }
+ }
+ referenceFields[field] = agrArr;
+ } else {
+ if (fields[field] && typeof (fields[field]) === "object" && referenceFields[field] && typeof (referenceFields[field]) === "object") {
+ if ((fields[field].value !== referenceFields[field].value) || (fields[field].unit !== referenceFields[field].unit)) {
+ referenceFields[field] = null;
+ }
+ } else if (referenceFields[field] != fields[field]) {
+ referenceFields[field] = null;
+ }
+
+ }
+ }
+ }
+ return referenceFields;
+ } else {
+ return this.defaultWell;
+ }
+ },
+
+ _getAllMultipleVal: function(wells) {
+ var multipleFieldList = this.multipleFieldList;
+
+ multipleFieldList.forEach(function(multiplexField) {
+ if (wells.length) {
+ var curMultipleVal = {};
+ wells.forEach(function(wellData) {
+ var id = multiplexField.id;
+ if (wellData[id]) {
+ if (wellData[id].length > 0) {
+ wellData[id].forEach(function(multipleVal) {
+ if (typeof (multipleVal) === 'object') {
+ if (multipleVal[id] in curMultipleVal) {
+ curMultipleVal[multipleVal[id]]++;
+ } else {
+ curMultipleVal[multipleVal[id]] = 1;
+ }
+ } else {
+ if (multipleVal in curMultipleVal) {
+ curMultipleVal[multipleVal]++;
+
+ } else {
+ curMultipleVal[multipleVal] = 1;
+ }
+ }
+ })
+ }
+ }
+ });
+ multiplexField.allSelectedMultipleVal = curMultipleVal;
+ } else {
+ multiplexField.allSelectedMultipleVal = null
+ }
+ });
+ },
+
+ decideSelectedFields: function() {
+ var wells = this._getSelectedWells();
+ this._getAllMultipleVal(wells);
+ this.applyFieldWarning(wells);
+ var well = this._getCommonWell(wells);
+ this._addDataToTabFields(well);
+ },
+
+ // get well value differences for each well in wellsHash
+ getDifferentWellsVals: function(wellsHash) {
+ var wells = [];
+ for (var wellId in wellsHash) {
+ wells.push(wellsHash[wellId]);
+ }
+ var differentWellsVals = {};
+ if (wells.length > 1) {
+ var commonWell = this._getCommonWell(wells);
+ var allFieldVal = {};
+ for (var fieldIdx in wellsHash[0]) {
+ allFieldVal[fieldIdx] = [];
+ }
+ for (var wellIdx in wells) {
+ var diffWellVal = {};
+ var curWellData = wells[wellIdx];
+ for (var fieldId in curWellData) {
+ var commonVal = commonWell[fieldId];
+ var curVal = curWellData[fieldId];
+ var newVal = null;
+ if (Array.isArray(curVal)) {
+ // get uncommonVal
+ newVal = [];
+ for (var idx = 0; idx < curVal.length; idx++) {
+ var curMultiVal = curVal[idx];
+ // multiplex field
+ if (curMultiVal && typeof (curMultiVal === "object")) {
+ if (!this.containsObject(curMultiVal, commonVal)) {
+ newVal.push(curMultiVal);
+ if (!this.containsObject(curMultiVal, allFieldVal[fieldId])) {
+ allFieldVal[fieldId].push(curMultiVal);
+ }
+ }
+ } else {
+ if (commonVal.indexOf(curMultiVal) >= 0) {
+ newVal.push(curMultiVal);
+ if (!allFieldVal[fieldId].indexOf(curMultiVal) >= 0) {
+ allFieldVal[fieldId].push(curMultiVal);
+ }
+ }
+ }
+ }
+ } else if (curVal && typeof (curVal) === "object") {
+ if (commonVal && typeof (commonVal) === "object") {
+ if (!((curVal.value === commonVal.value) || (curVal.unit === commonVal.unit))) {
+ newVal = curVal;
+ if (!this.containsObject(curVal, allFieldVal[fieldId])) {
+ allFieldVal[fieldId].push(curVal);
+ }
+ }
+ } else {
+ newVal = curVal;
+ if (!this.containsObject(curVal, allFieldVal[fieldId])) {
+ allFieldVal[fieldId].push(curVal);
+ }
+ }
+ } else if (curVal !== commonVal) {
+ newVal = curVal;
+ if (!allFieldVal[fieldId].indexOf(curVal) >= 0) {
+ allFieldVal[fieldId].push(curVal);
+ }
+ }
+ diffWellVal[fieldId] = newVal;
+ }
+
+
+ differentWellsVals[wellIdx] = diffWellVal;
+ }
+
+ // clean up step for fields that are empty
+ for (var fieldId in allFieldVal) {
+ if (allFieldVal[fieldId].length === 0) {
+ for (var wellIdx in differentWellsVals) {
+ delete differentWellsVals[wellIdx][fieldId];
+ }
+ }
+ }
+
+ return differentWellsVals;
+ } else if (wellsHash[0]) {
+ var well = {};
+ for (var fieldId in wellsHash[0]) {
+ var curVal = wellsHash[0][fieldId];
+ if (Array.isArray(curVal)) {
+ if (curVal.length > 0) {
+ well[fieldId] = curVal
+ }
+ } else if (curVal) {
+ well[fieldId] = curVal;
+ }
+ }
+ return {
+ 0: well
+ };
+ }
+ },
+
+ // get all wells that has data
+ getWellSetAddressWithData: function() {
+ var address = [];
+ var derivative = this.engine.derivative;
+ for (var id in derivative) {
+ address.push(this.indexToAddress(id));
+ }
+ return address;
+ }
+
+ };
+ }
+})(jQuery, fabric);
+var plateLayOutWidget = plateLayOutWidget || {};
+
+plateLayOutWidget.assets = function() {
+ return {
+ _assets: {
+ doImg: '✓',
+ dontImg: '',
+ warningImg: '⚠'
+ }
+ };
+};
+
+var plateLayOutWidget = plateLayOutWidget || {};
+
+(function($, fabric) {
+
+ plateLayOutWidget.interface = function() {
+ // interface holds all the methods to put the interface in place
+ return {
+
+ _createInterface: function() {
+
+ var divIdentifier = '
';
+ this.container = this._createElement(divIdentifier).addClass("plate-setup-wrapper");
+ this.topSection = this._createElement(divIdentifier).addClass("plate-setup-top-section");
+
+ this.topLeft = this._createElement(divIdentifier).addClass("plate-setup-top-left");
+ this.topRight = this._createElement(divIdentifier).addClass("plate-setup-top-right");
+
+ this.overLayContainer = this._createElement(divIdentifier).addClass("plate-setup-overlay-container");
+ this.canvasContainer = this._createElement(divIdentifier).addClass("plate-setup-canvas-container");
+
+ this._createOverLay();
+ $(this.topLeft).append(this.overLayContainer);
+
+ this._createCanvas();
+ $(this.topLeft).append(this.canvasContainer);
+
+
+ $(this.topSection).append(this.topLeft);
+ $(this.topSection).append(this.topRight);
+
+ $(this.container).append(this.topSection);
+ $(this.element).append(this.container);
+
+ this._initiateFabricCanvas();
+
+ this._createTabAtRight();
+ this._createTabs();
+
+ this._placePresetTabs();
+ // Bottom of the screen
+ this._bottomScreen();
+ // Canvas
+ this._canvas();
+
+ this.bottomForFirstTime();
+
+ var that = this;
+ this._setShortcuts();
+ $(document.body).keyup(function(e) {
+ that._handleShortcuts(e);
+ });
+
+ this._configureUndoRedoArray();
+ },
+
+ _createElement: function(element) {
+ return $(element);
+ },
+
+ _setShortcuts: function() {
+ var that = this;
+ window.addEventListener("cut", function(e) {
+ if (document.activeElement == document.body) {
+ that.copyCriteria();
+ that.clearCriteria();
+ e.preventDefault();
+ }
+ });
+ window.addEventListener("copy", function(e) {
+ if (document.activeElement == document.body) {
+ that.copyCriteria();
+ e.preventDefault();
+ }
+ });
+ window.addEventListener("paste", function(e) {
+ if (document.activeElement == document.body) {
+ that.pasteCriteria();
+ e.preventDefault();
+ }
+ });
+ },
+
+ _handleShortcuts: function(e) {
+ if (document.activeElement === document.body) {
+ if (e.keyCode == 46) {
+ this.clearCriteria();
+ e.preventDefault();
+ } else if (e.ctrlKey || e.metaKey) {
+ if (e.keyCode == 90) {
+ if (e.shiftKey) {
+ this.redo();
+ } else {
+ this.undo();
+ }
+ e.preventDefault();
+ } else if (e.keyCode == 89) {
+ this.redo();
+ e.preventDefault();
+ }
+ }
+ }
+ },
+ };
+ }
+})(jQuery, fabric);
+var plateLayOutWidget = plateLayOutWidget || {};
+
+(function($, fabric) {
+
+ plateLayOutWidget.loadPlate = function(THIS) {
+ // Methods which look after data changes and stack up accordingly
+ // Remember THIS points to plateLayOutWidget and 'this' points to engine
+ return {
+
+ getPlates: function(data) {
+ //sanitize input
+ var derivative = {};
+ for (var index in data.derivative) {
+ var well = data.derivative[index];
+ derivative[index] = this.sanitizeWell(well);
+ }
+
+ var checkboxes = data.checkboxes || [];
+ var selection = this.sanitizeAreas(data.selectedAreas, data.focalWell);
+
+ var sanitized = {
+ "derivative": derivative,
+ "checkboxes": checkboxes,
+ "selectedAreas": selection.selectedAreas,
+ "focalWell": selection.focalWell
+ };
+
+ this.setData(sanitized);
+ },
+
+ sanitizeAreas: function(selectedAreas, focalWell) {
+ var that = this;
+ var rows = this.dimensions.rows;
+ var cols = this.dimensions.cols;
+
+ if (!selectedAreas) {
+ selectedAreas = [];
+ }
+ if (selectedAreas.length) {
+ selectedAreas = selectedAreas.map(function(area) {
+ return {
+ minCol: that._coordIndex(Math.min(area.minCol, area.maxCol), cols),
+ minRow: that._coordIndex(Math.min(area.minRow, area.maxRow), rows),
+ maxCol: that._coordIndex(Math.max(area.minCol, area.maxCol), cols),
+ maxRow: that._coordIndex(Math.max(area.minRow, area.maxRow), rows)
+ };
+ });
+ var area = selectedAreas[selectedAreas.length - 1];
+ if (focalWell && !this._wellInArea(focalWell, area)) {
+ focalWell = null;
+ }
+ if (!focalWell) {
+ focalWell = {
+ row: area.minRow,
+ col: area.minCol
+ };
+ }
+ } else {
+ if (!focalWell) {
+ focalWell = {
+ row: 0,
+ col: 0
+ };
+ }
+ selectedAreas = [this._wellToArea(focalWell)];
+ }
+ return {
+ selectedAreas: selectedAreas,
+ focalWell: focalWell
+ };
+ },
+
+ sanitizeWell: function(well) {
+ var newWell = {};
+ for (var i = 0; i < this.fieldList.length; i++) {
+ var field = this.fieldList[i];
+ newWell[field.id] = field.parseValue(well[field.id]);
+ }
+ return newWell;
+ },
+
+ setData: function(data) {
+ this.engine.derivative = $.extend(true, {}, data.derivative);
+ this.setCheckboxes(data.checkboxes);
+ this.setSelection(data.selectedAreas, data.focalWell);
+ this._colorMixer();
+ this.decideSelectedFields();
+ this.mainFabricCanvas.renderAll();
+ },
+
+ }
+ }
+})(jQuery, fabric);
+var GET_PLATES = 'getPlates';
+var IS_READ_ONLY = 'isReadOnly';
+var IS_DISABLE_ADD_DELETE_WELL = 'isDisableAddDeleteWell';
+var GET_SELECTED_OBJECT = 'getSelectedObject';
+var SETSELECTEDWELL = 'setSelectedWell';
+var plateLayOutWidget = plateLayOutWidget || {};
+
+(function($, fabric) {
+
+ plateLayOutWidget.overlay = function() {
+ // overlay holds all the methods to put the part just above the canvas which contains all those
+ // 'completion percentage' annd 'copy Criteria' button etc ...
+ return {
+
+ _createOverLay: function() {
+
+ var that = this;
+ this.overLayTextContainer = this._createElement("
").addClass("plate-setup-overlay-text-container");
+ this.overLayTextContainer.text("Completion Percentage:");
+ this.overLayContainer.append(this.overLayTextContainer);
+ this.overLayButtonContainer = this._createElement("
").addClass("plate-setup-overlay-button-container");
+ this.overLayContainer.append(this.overLayButtonContainer);
+
+ this.clearCriteriaButton = this._createElement(" ").addClass("plate-setup-button");
+ this.clearCriteriaButton.text("Clear");
+ this.overLayButtonContainer.append(this.clearCriteriaButton);
+
+ this.clearCriteriaButton.click(function(evt) {
+ that.clearCriteria();
+ });
+
+ this.copyCriteriaButton = this._createElement(" ").addClass("plate-setup-button");
+ this.copyCriteriaButton.text("Copy");
+ this.overLayButtonContainer.append(this.copyCriteriaButton);
+
+ this.copyCriteriaButton.click(function(evt) {
+ that.copyCriteria();
+ });
+
+ this.pasteCriteriaButton = this._createElement(" ").addClass("plate-setup-button");
+ this.pasteCriteriaButton.text("Paste");
+ this.overLayButtonContainer.append(this.pasteCriteriaButton);
+
+ this.pasteCriteriaButton.click(function(evt) {
+ that.pasteCriteria();
+ });
+
+ this.undoButton = this._createElement(" ").addClass("plate-setup-button");
+ this.undoButton.text("Undo");
+ this.overLayButtonContainer.append(this.undoButton);
+
+ this.undoButton.click(function(evt) {
+ that.undo();
+ });
+
+ this.redoButton = this._createElement(" ").addClass("plate-setup-button");
+ this.redoButton.text("Redo");
+ this.overLayButtonContainer.append(this.redoButton);
+
+ this.redoButton.click(function(evt) {
+ that.redo();
+ });
+
+ },
+
+ clearCriteria: function() {
+ if (this.allSelectedObjects) {
+ var noOfSelectedObjects = this.allSelectedObjects.length;
+ var hasWellUpdate = false;
+ for (var objectIndex = 0; objectIndex < noOfSelectedObjects; objectIndex++) {
+ var tile = this.allSelectedObjects[objectIndex];
+ if (tile.index in this.engine.derivative) {
+ // handling for clearing well when not allowed to add or delete wells
+ if (this.emptyWellWithDefaultVal && this.disableAddDeleteWell) {
+ var well = JSON.parse(JSON.stringify(this.defaultWell));
+ var defaultValue = this.emptyWellWithDefaultVal;
+ for (var key in defaultValue) {
+ if (key in well) {
+ well[key] = defaultValue[key];
+ this._applyFieldData(key, defaultValue[key]);
+ } else {
+ console.log("Well does not contain key: " + key + ", please contact support");
+ }
+ }
+ this.engine.derivative[tile.index] = well;
+ } else {
+ delete this.engine.derivative[tile.index];
+ }
+ hasWellUpdate = true;
+ }
+ }
+ if (hasWellUpdate) {
+ this.derivativeChange();
+ }
+
+ this._colorMixer();
+ this.decideSelectedFields();
+ } else {
+ alert("Please select any well");
+ }
+ },
+
+ copyCriteria: function() {
+ if (this.allSelectedObjects) {
+ var wells = this._getSelectedWells();
+ this.commonWell = this._getCommonFields(wells);
+ } else {
+ alert("Please select any well.");
+ }
+ },
+
+ pasteCriteria: function() {
+ if (this.commonWell) {
+ this._addAllData(this.commonWell);
+ this.decideSelectedFields();
+ this.mainFabricCanvas.renderAll();
+ }
+ }
+ };
+ }
+})(jQuery, fabric);
+$.widget("DNA.plateLayOut", {
+
+ plateLayOutWidget: {},
+
+ options: {
+ value: 0
+ },
+
+ allTiles: [], // All tiles containes all thise circles in the canvas
+
+ addressToLoc: function(layoutAddress) {
+ var m = /^([A-Z]+)(\d+)$/.exec(layoutAddress.trim().toUpperCase())
+ if (m) {
+ var row_v = m[1];
+ var col = parseInt(m[2]) - 1;
+ var row;
+ for (var i = 0; i < row_v.length; i++) {
+ var c = row_v.charCodeAt(i) - 65;
+ if (i) {
+ row += 1;
+ row *= 26;
+ row += c;
+ } else {
+ row = c;
+ }
+ }
+ return {
+ r: row,
+ c: col
+ };
+ } else {
+ throw layoutAddress + " not a proper layout address";
+ }
+ },
+
+ locToIndex: function(loc, dimensions) {
+ if (!dimensions) {
+ dimensions = this.dimensions;
+ }
+ if (loc.r < 0) {
+ t
+ }
+ if (!(loc.r >= 0 && loc.r < dimensions.rows)) {
+ throw "Row index " + (loc.r + 1) + " invalid";
+ }
+ if (!(loc.c >= 0 && loc.c < dimensions.cols)) {
+ throw "Column index " + (loc.c + 1) + " invalid";
+ }
+ return loc.r * dimensions.cols + loc.c;
+ },
+
+ addressToIndex: function(layoutAddress, dimensions) {
+ var loc = this.addressToLoc(layoutAddress);
+ return this.locToIndex(loc, dimensions);
+ },
+
+ _rowKey: function(i) {
+ var c1 = i % 26;
+ var c2 = (i - c1) / 26;
+ var code = String.fromCharCode(65 + c1);
+ if (c2 > 0) {
+ code = String.fromCharCode(64 + c2) + code;
+ }
+ return code;
+ },
+
+ indexToLoc: function(index, dimensions) {
+ if (!dimensions) {
+ dimensions = this.dimensions;
+ }
+
+ if (index >= dimensions.rows * dimensions.cols) {
+ throw "Index too high: " + index.toString(10);
+ }
+ var loc = {};
+ loc.c = index % dimensions.cols;
+ loc.r = (index - loc.c) / dimensions.cols;
+
+ return loc;
+ },
+
+ locToAddress: function(loc) {
+ return this._rowKey(loc.r) + (loc.c + 1).toString(10);
+ },
+
+ indexToAddress: function(index, dimensions) {
+ var loc = this.indexToLoc(index, dimensions);
+ return this.locToAddress(loc);
+ },
+
+ getDimensions: function() {
+ return $.extend(true, {}, this.dimensions);
+ },
+
+ _create: function() {
+ var rows = parseInt(this.options.numRows || 8);
+ var cols = parseInt(this.options.numCols || 12);
+ this.dimensions = {
+ rows: rows,
+ cols: cols
+ };
+ this.rowIndex = [];
+ for (var i = 0; i < rows; i++) {
+ this.rowIndex.push(this._rowKey(i));
+ }
+
+ this.target = (this.element[0].id) ? "#" + this.element[0].id : "." + this.element[0].className;
+
+ // Import classes from other files.. Here we import it using extend and add it to this
+ // object. internally we add to widget.DNA.getPlates.prototype.
+ // Helpers are methods which return other methods and objects.
+ // add Objects to plateLayOutWidget and it will be added to this object.
+ // set read only well
+ if (this.options.readOnly) {
+ this.isReadOnly(true);
+ }
+
+ for (var component in plateLayOutWidget) {
+ // Incase some properties has to initialize with data from options hash,
+ // we provide it sending this object.
+ $.extend(this, new plateLayOutWidget[component](this));
+ }
+
+ this._createInterface();
+
+ this._trigger("created", null, this);
+
+ return this;
+ },
+
+ _init: function() {
+ // This is invoked when the user use the plugin after _create is called.
+ // The point is _create is invoked for the very first time and for all other
+ // times _init is used.
+ },
+
+ addData: function() {
+ alert("wow this is good");
+ },
+
+ // wellsData follows syntax: {0:{field1: val1, field2: val2}, 1:{field1: val1, field2: val2}}
+ getTextDerivative: function(wellsData) {
+ var textDerivative = {};
+ var fieldMap = this.fieldMap;
+ for (var idx in wellsData) {
+ var textValWell = {};
+ var textFieldIdWell = {};
+ var curWellData = wellsData[idx];
+ for (var fieldId in curWellData) {
+ if (fieldId in this.fieldMap) {
+ var field = this.fieldMap[fieldId];
+ var textVal = field.parseText(curWellData[fieldId]);
+ textFieldIdWell[field.name] = textVal;
+ textValWell[fieldId] = textVal;
+ } else {
+ // do not convert if not a field (ex: layout_address)
+ textFieldIdWell[fieldId] = curWellData[fieldId];
+ textValWell[fieldId] = curWellData[fieldId];
+ }
+ }
+ textDerivative[idx] = {
+ textVal: textValWell,
+ textFieldVal: textFieldIdWell
+ };
+ }
+
+ return textDerivative;
+ },
+
+ // wellsData follows syntax: {0:{field1: val1, field2: val2}, 1:{field1: val1, field2: val2}}
+ getWellsDifferences: function(wellsData) {
+ return this.getDifferentWellsVals(wellsData);
+ },
+
+ setFieldsDisabled: function(flag) {
+ this.fieldList.forEach(function(field) {
+ field.disabled(flag);
+ });
+ },
+
+ isReadOnly: function(flag) {
+ if (flag) {
+ this.readOnly = true;
+ } else {
+ this.readOnly = false;
+ }
+ this.readOnlyHandler();
+ },
+
+ readOnlyHandler: function() {
+ if (this.readOnly) {
+ this.overLayButtonContainer.css("display", "none");
+ $('.multiple-field-manage-delete-button').css("display", "none");
+ this.setFieldsDisabled(true);
+ } else {
+ this.overLayButtonContainer.css("display", "flex");
+ $('.multiple-field-manage-delete-button').css("display", "none");
+ if (!this.disableAddDeleteWell) {
+ this.setFieldsDisabled(false);
+ }
+ }
+ },
+
+ disableAddDeleteWell: null,
+ // column_with_default_val will be used to determine empty wells, format: {field_name: default_val}
+ isDisableAddDeleteWell: function(flag, column_with_default_val) {
+ if (flag) {
+ this.disableAddDeleteWell = true;
+ this.addressAllowToEdit = this.getWellSetAddressWithData();
+ // configure undo redo action
+ this.actionPointer = 0;
+ this.undoRedoArray = [];
+ this.undoRedoArray.push(this.createObject());
+ if (column_with_default_val) {
+ this.emptyWellWithDefaultVal = column_with_default_val;
+ }
+ } else {
+ this.disableAddDeleteWell = false;
+ this.setFieldsDisabled(false);
+ this.emptyWellWithDefaultVal = null;
+ }
+ this._fabricEvents();
+ },
+
+ getSelectedObject: function() {
+ var selectedAddress = [];
+ for (var i = 0; i < this.allSelectedObjects.length; i++) {
+ selectedAddress.push(this.allSelectedObjects[i].address);
+ }
+ var selectedObjects = {};
+ var derivative = this.engine.derivative;
+ for (var index in derivative) {
+ var address = this.indexToAddress(index);
+ if (selectedAddress.indexOf(address) >= 0) {
+ var well = JSON.parse(JSON.stringify(derivative[index]));
+ well.colorIndex = this.engine.colorMap.get(Number(index));
+ selectedObjects[address] = well;
+ }
+ }
+ return selectedObjects;
+ },
+
+ selectObjectInBottomTab: function() {
+ var selectedObjects = this.getSelectedObject();
+ var selectedObjectAddress;
+ for (var prop in selectedObjects) {
+ if (!selectedObjectAddress) {
+ selectedObjectAddress = prop;
+ } else {
+ return; // scroll to matching group only if a single well has been selected
+ }
+ }
+ if (selectedObjects[selectedObjectAddress]) {
+ var colorIndex = selectedObjects[selectedObjectAddress].colorIndex;
+ var trs = document.querySelectorAll('table.plate-setup-bottom-table tr');
+ for (var i = 1; i < trs.length; i++) { // start at 1 to skip the table headers
+ var tds = trs[i].children;
+ var isSelected = tds[0].querySelector('button').innerHTML === colorIndex.toString();
+ for (var j = 1; j < tds.length; j++) {
+ if (isSelected) {
+ tds[j].style.background = '#22cb94';
+ } else {
+ tds[j].style.background = '#ffffff';
+ }
+ }
+ if (isSelected) {
+ scrollTo(document.querySelector('.plate-setup-bottom-table-container'), tds[0].offsetTop, 300);
+ }
+ }
+ }
+ },
+
+ getSelectedIndex: function() {
+ return this.allSelectedObjects.map(function(selectedObj) {
+ return that.addressToIndex(selectedObj.address)
+ });
+ },
+
+ getSelectedAddress: function() {
+ return this.allSelectedObjects.map(function(selectedObj) {
+ return selectedObj.address;
+ });
+ },
+
+ setSelectedWell: function(addressList) {
+ var areas = [];
+ var minRow = 999;
+ var locMap = {};
+ for (var id = 0; id < addressList.length; id++) {
+ var wellIdx = this.addressToIndex(addressList[id]);
+ var loc = this.indexToLoc(wellIdx);
+ areas.push({
+ minCol: loc.c,
+ minRow: loc.r,
+ maxCol: loc.c,
+ maxRow: loc.r
+ });
+ if (loc.r <= minRow) {
+ minRow = loc.r;
+ if (loc.r in locMap) {
+ locMap[loc.r].push(loc.c);
+ } else {
+ locMap[loc.r] = [loc.c];
+ }
+ }
+ }
+ var focalWell = {
+ row: minRow,
+ col: Math.min.apply(null, locMap[minRow])
+ };
+
+ this.setSelection(areas, focalWell);
+ this.decideSelectedFields();
+ this.mainFabricCanvas.renderAll();
+ }
+
+});
+
+// https://stackoverflow.com/questions/17733076/smooth-scroll-anchor-links-without-jquery
+function scrollTo(element, to, duration) {
+ if (duration <= 0) return;
+ var difference = to - element.scrollTop;
+ var perTick = difference / duration * 10;
+ setTimeout(function() {
+ element.scrollTop = element.scrollTop + perTick;
+ if (element.scrollTop === to) return;
+ scrollTo(element, to, duration - 10);
+ }, 10);
+}
+var plateLayOutWidget = plateLayOutWidget || {};
+
+(function($, fabric) {
+
+ plateLayOutWidget.preset = function(me) {
+ // All the preset action goes here
+ return {
+
+ presets: [],
+
+ _placePresetTabs: function() {
+ var presets = this.options.attributes.presets;
+
+ if (presets && presets.length) {
+ this.wellAttrContainer = this._createElement("
").addClass("plate-setup-well-attr-container")
+ .text("Checkbox presets");
+ this.tabContainer.append(this.wellAttrContainer);
+
+ this.presetTabContainer = this._createElement("
").addClass("plate-setup-preset-container");
+ this.tabContainer.append(this.presetTabContainer);
+
+ for (var i = 0; i < presets.length; i++) {
+ var preset = presets[i];
+ var divText = this._createElement("
").addClass("plate-setup-prest-tab-div")
+ .text(preset.title);
+
+ var presetButton = this._createElement("
").addClass("plate-setup-prest-tab")
+ .data("preset", preset.fields).append(divText);
+ this.presetTabContainer.append(presetButton);
+
+ var that = this;
+ presetButton.click(function() {
+ var preset = $(this);
+ that._selectPreset(preset);
+ });
+ this.presets.push(presetButton);
+ }
+ }
+ },
+
+ _clearPresetSelection: function() {
+ for (var j = 0; j < this.presets.length; j++) {
+ var p = this.presets[j];
+ p.removeClass("plate-setup-prest-tab-selected")
+ .addClass("plate-setup-prest-tab");
+ }
+ },
+
+ _selectPreset: function(preset) {
+ this.setCheckboxes(preset.data("preset"));
+ preset.removeClass("plate-setup-prest-tab")
+ .addClass("plate-setup-prest-tab-selected");
+ },
+ };
+ }
+})(jQuery, fabric);
+var plateLayOutWidget = plateLayOutWidget || {};
+
+(function($, fabric) {
+
+ plateLayOutWidget.tabs = function() {
+ // Tabs crete and manage tabs at the right side of the canvas.
+ return {
+
+ allTabs: [],
+
+ defaultWell: {},
+
+ allDataTabs: [], // To hold all the tab contents. this contains all the tabs and its elements and elements
+ // Settings as a whole. its very usefull, when we have units for a specific field.
+ // it goes like tabs-> individual field-> units and checkbox
+
+ _createTabAtRight: function() {
+ this.tabContainer = this._createElement("
").addClass("plate-setup-tab-container");
+ $(this.topRight).append(this.tabContainer);
+ },
+
+ _createTabs: function() {
+ // this could be done using z-index. just imagine few cards stacked up.
+ // Check if options has tab data.
+ // Originally we will be pulling tab data from developer.
+ // Now we are building upon dummy data.
+ this.tabHead = this._createElement("
").addClass("plate-setup-tab-head");
+ $(this.tabContainer).append(this.tabHead);
+
+ var tabData = this.options.attributes.tabs;
+ var that = this;
+
+ tabData.forEach(function(tab, tabIndex) {
+ that.allTabs[tabIndex] = that._createElement("
").addClass("plate-setup-tab");
+ $(that.allTabs[tabIndex]).data("index", tabIndex)
+ .text(tab.name);
+
+ $(that.allTabs[tabIndex]).click(function() {
+ that._tabClickHandler(this);
+ });
+
+ $(that.tabHead).append(that.allTabs[tabIndex]);
+ });
+
+ this.tabDataContainer = this._createElement("
").addClass("plate-setup-tab-data-container");
+ $(this.tabContainer).append(this.tabDataContainer);
+
+ this._addDataTabs(tabData);
+
+ $(this.allTabs[0]).click();
+
+ this._addTabData();
+ },
+
+ _tabClickHandler: function(clickedTab) {
+
+ if (this.selectedTab) {
+ $(this.selectedTab).removeClass("plate-setup-tab-selected")
+ .addClass("plate-setup-tab");
+
+ var previouslyClickedTabIndex = $(this.selectedTab).data("index");
+ $(this.allDataTabs[previouslyClickedTabIndex]).css("z-index", 0);
+ this.readOnlyHandler();
+ }
+
+ $(clickedTab).addClass("plate-setup-tab-selected");
+
+ this.selectedTab = clickedTab;
+
+ var clickedTabIndex = $(clickedTab).data("index");
+ $(this.allDataTabs[clickedTabIndex]).css("z-index", 1000);
+ },
+
+ _addDataTabs: function(tabs) {
+
+ var tabIndex = 0;
+
+ for (var tabData in tabs) {
+ this.allDataTabs[tabIndex++] = this._createElement("
").addClass("plate-setup-data-div")
+ .css("z-index", 0);
+ $(this.tabDataContainer).append(this.allDataTabs[tabIndex - 1]);
+ }
+ }
+ };
+ }
+})(jQuery, fabric);
+var plateLayOutWidget = plateLayOutWidget || {};
+
+(function($, fabric) {
+
+ plateLayOutWidget.undoRedoManager = function(THIS) {
+
+ return {
+
+ undoRedoArray: [],
+
+ actionPointer: null,
+
+ addToUndoRedo: function(data) {
+
+ if (this.actionPointer != null) {
+ var i = this.actionPointer + 1;
+ if (i < this.undoRedoArray.length) {
+ this.undoRedoArray.splice(i, this.undoRedoArray.length - i);
+ }
+ }
+ this.actionPointer = null;
+ this.undoRedoArray.push($.extend(true, {}, data));
+ },
+
+ _configureUndoRedoArray: function() {
+
+ var data = {
+ checkboxes: [],
+ derivative: {},
+ selectedAreas: [{
+ minRow: 0,
+ minCol: 0,
+ maxRow: 0,
+ maxCol: 0
+ }],
+ focalWell: {
+ row: 0,
+ col: 0
+ }
+ };
+
+ this.undoRedoArray = [];
+ this.actionPointer = null;
+ this.undoRedoArray.push($.extend({}, data));
+ },
+
+ undo: function() {
+ console.log("undo");
+ return this.shiftUndoRedo(-1);
+ },
+
+ redo: function() {
+ console.log("redo");
+ return this.shiftUndoRedo(1);
+ },
+
+ shiftUndoRedo: function(pointerDiff) {
+ var pointer = this.actionPointer;
+ if (pointer == null) {
+ pointer = this.undoRedoArray.length - 1;
+ }
+ pointer += pointerDiff;
+ return this.setUndoRedo(pointer);
+ },
+
+ setUndoRedo: function(pointer) {
+ if (pointer < 0) {
+ return false;
+ }
+ if (pointer >= this.undoRedoArray.length) {
+ return false;
+ }
+ this.undoRedoActive = true;
+ this.setData(this.undoRedoArray[pointer]);
+ this.actionPointer = pointer;
+ this.undoRedoActive = false;
+ this.derivativeChange();
+ return true;
+ }
+ }
+ };
+
+})(jQuery, fabric);
+var plateLayOutWidget = plateLayOutWidget || {};
+
+(function($, fabric) {
+
+ plateLayOutWidget.wellArea = function(fabric) {
+
+ return {
+
+ _areasToTiles: function(areas) {
+ //Convert areas to tiles
+ var cols = this.dimensions.cols;
+ var that = this;
+ return areas.reduce(function(tiles, area) {
+ if (area) {
+ for (var r = area.minRow; r <= area.maxRow; r++) {
+ for (var c = area.minCol; c <= area.maxCol; c++) {
+ var tile = that.allTiles[c + cols * r];
+ if (tiles.indexOf(tile) < 0) {
+ if (that.disableAddDeleteWell) {
+ if (that.addressAllowToEdit.indexOf(tile.address) >= 0) {
+ tiles.push(tile);
+ }
+ } else {
+ tiles.push(tile);
+ }
+ }
+ }
+ }
+ }
+ return tiles;
+ }, []);
+ },
+
+ _encodeArea: function(area) {
+ //Encode area as string
+ if ((area.minRow == area.maxRow) && (area.minCol == area.maxCol)) {
+ return this.rowIndex[area.minRow] + area.minCol.toString(10);
+ } else {
+ return this.rowIndex[area.minRow] + area.minCol.toString(10) + ":" + this.rowIndex[area.maxRow] + area.maxCol.toString(10);
+ }
+ },
+
+ _encodeAreas: function(areas) {
+ //Encode an array of areas as a string
+ var that = this;
+ return areas.map(function(area) {
+ return that._encodeArea(area);
+ }).join(",");
+ },
+
+ _decodeWell: function(wellAddress) {
+ var that = this;
+ var adRx = new RegExp("^\\s*(" + that.rowIndex.join("|") + ")(\\d+)\\s*$")
+ var rcRx = /^\s*R(\d+)C(\d+)\s*$/i;
+
+ var match;
+ match = wellAddress.match(adRx);
+ if (match) {
+ var row = that.rowIndex.indexOf(match[1]);
+ if (row >= 0) {
+ return {
+ row: row,
+ col: parseInt(match[2]) - 1
+ };
+ }
+ }
+ match = wellAddress.match(rcRx);
+ if (match) {
+ return {
+ row: parseInt(match[1]) - 1,
+ col: parseInt(match[2]) - 1
+ };
+ }
+
+ throw "Invalid well address: " + wellAddress;
+ },
+
+ _decodeArea: function(areaAddress) {
+ //Decode single area as string
+ var that = this;
+ var wells = areaAddress.split(":").map(function(wellAddress) {
+ return that._decodeWell(wellAddress);
+ })
+ if (wells.length == 1) {
+ return {
+ minRow: wells[0].row,
+ minCol: wells[0].col,
+ maxRow: wells[0].row,
+ maxCol: wells[0].col
+ }
+ } else if (wells.length == 2) {
+ var minRow = Math.min(wells[0].row, wells[1].row)
+ return {
+ minRow: Math.min(wells[0].row, wells[1].row),
+ minCol: Math.min(wells[0].col, wells[1].col),
+ maxRow: Math.max(wells[0].row, wells[1].row),
+ maxCol: Math.max(wells[0].col, wells[1].col)
+ }
+ } else {
+ throw "Invalid address: " + areaAddress;
+ }
+ },
+
+ _decodeAreas: function(areasAddress) {
+ //Decode single area as string
+ var that = this;
+ return areasAddress.split(",").map(function(areaAddress) {
+ return that._decodeArea(areaAddress);
+ });
+ },
+
+ _wellToArea: function(well) {
+ //Convert a well to an area
+ return {
+ minCol: well.col,
+ minRow: well.row,
+ maxCol: well.col,
+ maxRow: well.row
+ }
+ },
+
+ _wellInArea: function(well, area) {
+ //Determine if a well lies within an area
+ return well.row >= area.minRow && well.row <= area.maxRow && well.col >= area.minCol && well.col <= area.maxCol;
+ },
+
+ _coordsToRect: function(startCoords, endCoords) {
+ //Convert two XY coords to a bounding box
+ var left = Math.min(startCoords.x, endCoords.x);
+ var top = Math.min(startCoords.y, endCoords.y);
+ var height = Math.abs(endCoords.y - startCoords.y);
+ var width = Math.abs(endCoords.x - startCoords.x);
+ return {
+ top: top,
+ left: left,
+ height: height,
+ width: width
+ };
+ },
+
+ _coordIndex: function(v, count) {
+ var i;
+ if (v < 0) {
+ i = 0;
+ } else if (v >= count) {
+ i = count - 1;
+ } else {
+ i = Math.floor(v);
+ }
+ return i;
+ },
+
+ _coordsToWell: function(coord) {
+ //Convert a coordinate to a well
+ var cols = this.dimensions.cols;
+ var rows = this.dimensions.rows;
+
+ var w = this.sizes.spacing;
+ var m = this.sizes.label_spacing;
+
+ var x = (coord.x - m) / w;
+ var y = (coord.y - m) / w;
+
+ var row = this._coordIndex(y, rows);
+ var col = this._coordIndex(x, cols);
+
+ return {
+ row: row,
+ col: col,
+ };
+ },
+
+ _wellToCoords: function(well, center) {
+ //Convert a well to a coordinate
+ var w = this.sizes.spacing;
+ var m = this.sizes.label_spacing;
+ var x = well.col * w + m;
+ var y = well.row * w + m;
+ if (center) {
+ var hw = w / 2;
+ x = x + hw;
+ y = y + hw;
+ }
+
+ return {
+ x: x,
+ y: y
+ };
+ },
+
+ _areaToRect: function(area) {
+ //Convert area to rectangle
+ var rows = area.maxRow - area.minRow + 1;
+ var cols = area.maxCol - area.minCol + 1;
+
+ var w = this.sizes.spacing;
+ var m = this.sizes.label_spacing;
+
+ return {
+ top: area.minRow * w + m,
+ left: area.minCol * w + m,
+ height: rows * w,
+ width: cols * w
+ }
+ },
+
+ _rectToArea: function(rect) {
+ //Convert a rectangular region to an area
+ var rows = this.dimensions.rows;
+ var cols = this.dimensions.cols;
+
+ var w = this.sizes.spacing;
+ var m = this.sizes.label_spacing;
+
+ var left = (rect.left - m) / w;
+ var top = (rect.top - m) / w;
+ var height = rect.height / w;
+ var width = rect.width / w;
+ var right = left + width;
+ var bottom = top + height;
+
+ //select whole row
+ if (right < 0) {
+ right = cols;
+ }
+ if (left >= cols) {
+ left = 0;
+ }
+ //select whole col
+ if (bottom < 0) {
+ bottom = rows;
+ }
+ if (top <= 0) {
+ top = 0;
+ }
+
+ return {
+ minCol: this._coordIndex(left, cols),
+ minRow: this._coordIndex(top, rows),
+ maxCol: this._coordIndex(right, cols),
+ maxRow: this._coordIndex(bottom, rows)
+ };
+ }
+
+ }
+ }
+})(jQuery, fabric);
\ No newline at end of file
diff --git a/dist/js/plate-map.min.js b/dist/js/plate-map.min.js
new file mode 100755
index 0000000..af52137
--- /dev/null
+++ b/dist/js/plate-map.min.js
@@ -0,0 +1,2 @@
+var plateLayOutWidget=plateLayOutWidget||{};!function(c,e){plateLayOutWidget.addDataOnChange=function(){return{_addAllData:function(e){if(this.allSelectedObjects)for(var t=this.allSelectedObjects.length,i=[],a=0;a ").addClass("plate-setup-tab-default-field"),l=a._createElement("
").addClass("plate-setup-tab-field-left-side"),s=a._createElement("
").addClass("plate-setup-tab-field-right-side"),r=a._createElement("
").addClass("plate-setup-tab-name").text(e.name),o=a._createElement("
").addClass("plate-setup-tab-field-container");c(s).append(r),c(s).append(o),c(n).append(l),c(n).append(s),c(a.allDataTabs[t]).append(n);var d={id:e.id,name:e.name,root:n,data:e,required:e.required||!1};return i.push(d),a.fieldMap[e.id]=d},_makeRegularField:function(e,t,i,a){var n=this,l=n._createElement("
").addClass("plate-setup-tab-default-field"),s=n._createElement("
").addClass("plate-setup-tab-field-left-side"),r=n._createElement("
").addClass("plate-setup-tab-field-right-side "),o=n._createElement("
").addClass("plate-setup-tab-name").text(e.name),d=n._createElement("
").addClass("plate-setup-tab-field-container");r.append(o),r.append(d),l.append(s),l.append(r),n.allDataTabs[t].append(l);var c={id:e.id,name:e.name,root:l,data:e,required:e.required};return c.required&&n.requiredField.push(c.id),i.push(c),n.fieldList.push(c),n.fieldMap[c.id]=c,a&&n._addCheckBox(c),n._createField(c),c.onChange=function(){var e=c.getValue(),t={};t[c.id]=e,n._addAllData(t)},c},_makeMultiplexField:function(e,t,i){var a=this,n=a._createElement("
").addClass("plate-setup-tab-default-field"),l=a._createElement("
").addClass("plate-setup-tab-field-left-side"),s=a._createElement("
").addClass("plate-setup-tab-field-right-side "),r=a._createElement("
").addClass("plate-setup-tab-name").text(e.name),o=a._createElement("
").addClass("plate-setup-tab-field-container");s.append(r),s.append(o),n.append(l),n.append(s),a.allDataTabs[t].append(n);var d={id:e.id,name:e.name,root:n,data:e,required:e.required};i.push(d),a.fieldList.push(d),a.fieldMap[e.id]=d;var c=[],u=[];for(var f in e.multiplexFields){var h=e.multiplexFields[f],p=a._makeSubField(h,t,i);c.push(p),h.required&&u.push(p.id)}return(d.required||u.length)&&this.requiredField.push({multiplexId:d.id,subFields:u}),d.subFieldList=c,a._createField(d),a._addCheckBox(d),c.forEach(function(s){s.mainMultiplexField=d,i.push(s),a._createField(s),a._addCheckBox(s),delete a.defaultWell[s.id],s.onChange=function(){var t=s.getValue(),i=s.mainMultiplexField,a=i.singleSelectValue(),e={};e[i.id]=a,e[s.id]=t;var n={id:a,value:e};d._changeMultiFieldValue(n,null);var l=i.detailData;null!==l&&(a=i.singleSelectValue(),l=l.map(function(e){return e[i.id]===a&&(e[s.id]=t),e})),i.detailData=l}}),d.getValue=function(){var e=d.input.val();return e.length?e:null},d}}}}(jQuery,fabric);plateLayOutWidget=plateLayOutWidget||{};!function(s,e){plateLayOutWidget.addWarningMsg=function(){return{fieldWarningMsg:function(e,t,i){var a="fieldWarning"+e.id,n=s("
").html(this._assets.warningImg).attr("id",a).addClass("plate-field-warning-image");if(i){if(e.root.find("#"+a).length<=0){e.root.find(".plate-setup-tab-name").text(" "+e.name),e.root.find(".plate-setup-tab-name").prepend(n);var l=s("
").addClass("pop-out-text");l.text(t),e.root.find(".plate-setup-tab-name").append(l),s("#"+a).hover(function(e){l[0].style.display="flex"},function(){l.hide()})}}else 0").html(this._assets.warningImg).attr("id",a).addClass("plate-field-warning-image");if(i){e.root.find(".plate-setup-tab-name").append(n);var l=s("
").addClass("pop-out-text");l.text(t),e.root.find(".plate-setup-tab-name").append(l),s("#"+a).hover(function(e){l[0].style.display="inline-block"},function(){l.hide()})}else s("#"+a).remove(),0 ").addClass("plate-setup-bottom-container"),this.bottomTableContainer=this._createElement("
").addClass("plate-setup-bottom-table-container"),this.bottomTable=this._createElement("
").addClass("plate-setup-bottom-table"),this.bottomTableContainer.append(this.bottomTable),this.bottomContainer.append(this.bottomTableContainer),this.container.append(this.bottomContainer)},addBottomTableHeadings:function(){this.bottomRow=this._createElement("
");var e=this._createElement("
").text("Group");this.bottomRow.prepend(e),this.bottomTable.empty(),this.bottomTable.append(this.bottomRow),this.rowCounter=1;for(var t=0;t
").text(a.name);this.bottomRow.append(e),this.rowCounter=this.rowCounter+1}this.adjustFieldWidth(this.bottomRow)},tileAttrText:function(e,t){var i=this.engine.derivative[e.index];return this.fieldMap[t].getText(i[t])},addBottomTableRow:function(e,i){var a=this,t=this.allTiles[i[0]],n=this._createElement(" "),l=this._createElement(" ").addClass("plate-setup-bottom-id"),s=this._createElement(" ");s.addClass("plate-setup-color-text"),s.text(e),l.append(s),s.click(function(e){var t=i.map(function(e){return a.indexToAddress(e)});e.ctrlKey&&a.getSelectedAddress().forEach(function(e){t.indexOf(e)<0&&t.push(e)}),a.setSelectedWell(t),a._trigger("selectedWells",null,{selectedAddress:a.getSelectedAddress()})}),0").text(c);n.append(u)}this.bottomTable.append(n),this.adjustFieldWidth(n)},bottomForFirstTime:function(){this.addBottomTableHeadings();var e=this._createElement(" "),t=this.colorPairs[0],i=this._createElement(" ");i.css("background","-webkit-linear-gradient(left, "+t[0]+" , "+t[1]+")"),e.append(i),this.bottomTable.append(e),this.createExportButton()},adjustFieldWidth:function(e){var t=this.rowCounter;1024<150*t&&e.css("width",152*t+"px")},downloadCSV:function(e,t){var i,a;i=new Blob([e],{type:"text/csv"}),(a=document.createElement("a")).download=t,a.href=window.URL.createObjectURL(i),a.style.display="none",document.body.appendChild(a),a.click()},exportData:function(e){var t=[],i=document.querySelectorAll("table tr"),a={},n=this.engine.stackUpWithColor,l=this.getDimensions(),s=this;for(var r in n)a[r]=n[r].map(function(e){return s.indexToAddress(e,l)});for(var o=0;o").addClass("plate-setup-bottom-control-container"),i=d("").addClass("plate-setup-overlay-text-container");i.text("Color groups"),t.append(i);var a=d("
").addClass("plate-setup-overlay-bottom-button-container"),n=d("
").addClass("plate-setup-button");function l(){n.text("Export CSV"),n[0].classList.remove("plate-setup-clicked-button"),n.addClass("plate-setup-button")}n.text("Export CSV"),a.append(n),n.click(function(){e.exportData("csv"),n.text("Exported"),n[0].classList.remove("plate-setup-button"),n.addClass("plate-setup-clicked-button"),setTimeout(l,3e3)});var s=d("
").addClass("plate-setup-button");s.text("Copy To Clipboard"),a.append(s);var r=new ClipboardJS(s.get(0),{text:function(){return e.exportData("clipboard")}});function o(){s.text("Copy To Clipboard"),s[0].classList.remove("plate-setup-clicked-button"),s.addClass("plate-setup-button")}r.on("success",function(e){s.text("Copied as tab-delimited format"),s[0].classList.remove("plate-setup-button"),s.addClass("plate-setup-clicked-button"),setTimeout(o,3e3)}),r.on("error",function(e){s.text("Failed to copy table to clipboard: browser may be incompatible"),setTimeout(o,3e3)}),t.append(a),this.bottomContainer.prepend(t)}}}}(jQuery,fabric);plateLayOutWidget=plateLayOutWidget||{};!function(e,i){plateLayOutWidget.canvas=function(){return{allSelectedObjects:null,allPreviouslySelectedObjects:null,colorPointer:0,goldenRatio:.618033988749895,_createCanvas:function(){this.normalCanvas=this._createElement("
").attr("id","DNAcanvas"),e(this.canvasContainer).append(this.normalCanvas)},_initiateFabricCanvas:function(){var e=this.canvasContainer.width(),t=this.canvasContainer.height();this._setCanvasArea(e,t),this.mainFabricCanvas=new i.Canvas("DNAcanvas",{backgroundColor:"#f5f5f5",selection:!1,stateful:!1,hoverCursor:"pointer",renderOnAddRemove:!1}).setWidth(e).setHeight(t)}}}}(jQuery,fabric);plateLayOutWidget=plateLayOutWidget||{};!function(l,e){plateLayOutWidget.checkBox=function(){return{globalSelectedAttributes:[],_addCheckBox:function(e){var t=l("").html(this._assets.dontImg).addClass("plate-setup-tab-check-box bg-light").data("clicked",!1);t.data("linkedFieldId",e.id),e.root.find(".plate-setup-tab-field-left-side").empty().append(t),this._applyCheckboxHandler(t),e.checkbox=t},_applyCheckboxHandler:function(e){var n=this;e.click(function(e,t){var i=l(this),a={};a[i.data("linkedFieldId")]=!i.data("clicked"),n.changeCheckboxes(a)})},changeSubFieldsCheckboxes:function(e,n){var l=this,s=[];return e.subFieldList.forEach(function(e){var t=e.checkbox,i=t.data("linkedFieldId"),a=t.data("clicked");i in n&&(a=Boolean(n[i])),t.data("clicked",a),a?(t.html(l._assets.doImg),s.push(e.id)):t.html(l._assets.dontImg)}),s},changeCheckboxes:function(e){for(var t=[],i={},a=0;a").attr("id",e).addClass("plate-setup-tab-input");i.root.find(".plate-setup-tab-field-container").append(t),this.defaultWell[e]=null,i.parseValue=function(e){return e=e?String(e):null},i.getValue=function(){var e=t.val().trim();return""==e&&(e=null),e},i.setValue=function(e){t.val(e)},i.getText=function(e){return null==e?"":e},i.disabled=function(e){i.input.prop("disabled",e)},i.parseText=i.parseValue,t.on("input",function(e,t){i.onChange()}),i.input=t},_createOpts:function(e){var t={allowClear:!0,placeholder:"select",minimumResultsForSearch:10},i=!1;if(e.options&&(t.data=e.options,i=!0),e.ajax&&(t.ajax=ajax,i=!0),!i)throw"Must specify data or ajax";return t},_createSelectField:function(i){var a=i.id,t=this._createElement(" ").attr("id",a).addClass("plate-setup-tab-select-field");i.root.find(".plate-setup-tab-field-container").append(t),this.defaultWell[a]=null;var e=this._createOpts(i.data),n={};e.data.forEach(function(e){n[e.id]=e}),t.select2(e),i.parseValue=function(e){var t=e;if(""==t&&(t=null),null==t)return null;if(t in n)return n[t].id;throw"Invalid value "+e+" for select field "+a},i.disabled=function(e){i.input.prop("disabled",e)},i.getValue=function(){return t.val()},i.setValue=function(e){t.val(e),t.trigger("change.select2")},i.getText=function(e){return null==e?"":n[e].text},i.parseText=function(e){var t=e;if(""==t&&(t=null),null==t)return null;if(t in n)return n[t].text;throw"Invalid text value "+e+" for select field "+a},t.on("change",function(e,t){i.onChange()}),t.on("select2:unselect",function(e){t.one("select2:opening",function(e){e.preventDefault()})}),i.input=t},_createMultiSelectField:function(a){var i=a.id,n=this,t=this._createElement(" ").attr("id",i).addClass("plate-setup-tab-multiselect-field");t.attr("multiple","multiple"),a.root.find(".plate-setup-tab-field-container").append(t),n.defaultWell[i]=null;var e=n._createOpts(a.data);e.multiple=!0;var l={};e.data.forEach(function(e){l[e.id]=e}),t.select2(e),a.disabled=function(e){a.input.prop("disabled",e)},a.parseValue=function(e){var t=e;return t=t&&t.length?t.map(function(e){if(e in l)return l[e].id;throw"Invalid value "+e+" for multiselect field "+i}):null},a.getValue=function(){var e=t.val();return e.length?e:null},a.setValue=function(e){e=e||[],t.val(e),t.trigger("change.select2")},a.getText=function(e){return null==e?"":0").addClass("plate-setup-tab-input").attr("placeholder",e.placeholder||"").attr("id",i);n.root.find(".plate-setup-tab-field-container").append(t),this.defaultWell[i]=null;var a=e.units||[],l=e.defaultUnit||null,s=null;if(l?a.length?a.indexOf(l)<0&&(l=a[0]):a=[l]:a.length&&(l=a[0]),a.length)if(n.units=a,n.hasUnits=!0,n.defaultUnit=l,1==a.length){var r=f("
").addClass("plate-setup-tab-unit");r.text(l),n.root.find(".plate-setup-tab-field-container").append(r)}else{s=this._createElement(" ").attr("id",i).addClass("plate-setup-tab-label-select-field"),n.root.find(".plate-setup-tab-field-container").append(s);var o=null,d={data:a.map(function(e){return e==l&&(o=e),{id:e,text:e}}),allowClear:!1,minimumResultsForSearch:10};s.select2(d),s.val(o)}n.disabled=function(e){n.input.prop("disabled",e),s&&s.prop("disabled",e)},n.setUnitOpts=function(e){n.units=e||null;var t=[],i=n.defaultUnit=null;n.units&&n.units.length&&(n.defaultUnit=n.units[0],t=n.units.map(function(e){var t={id:e,text:e};return e==n.defaultUnit&&(i=e),t}));var a={data:t,allowClear:!1,minimumResultsForSearch:10};s.select2("destroy"),s.val(null),s.empty(),s.select2(a),s.val(i)},n.parseValue=function(e){var t;if(f.isPlainObject(e)){if(n.hasUnits)return null===(t=n.parseRegularValue(e.value))?null:{value:t,unit:n.parseUnit(e.unit)};throw"Value must be plain numeric for numeric field "+i}return n.hasUnits?null===(t=n.parseRegularValue(e))?null:{value:t,unit:n.defaultUnit}:n.parseRegularValue(e)},n.getValue=function(){var e=n.getRegularValue();if(null===e||isNaN(e))return null;if(n.hasUnits){var t={value:e,unit:n.getUnit()};if(n.data.hasMultiplexUnit)for(var i in n.data.unitMap){n.data.unitMap[i].forEach(function(e){e.text===t.unit&&(t.unitTypeId=i,t.unitId=e.id)})}return t}return e},n.setValue=function(e){n.hasUnits?f.isPlainObject(e)?(n.setUnit(e.unit||n.defaultUnit),n.setRegularValue(e.value)):(n.setRegularValue(e),n.setUnit(n.defaultUnit)):n.setRegularValue(e)},n.parseRegularValue=function(e){if(null==e)return null;var t=String(e).trim();if(""===t)return null;if(t=Number(e),isNaN(t))throw"Invalid value "+e+" for numeric field "+i;return t},n.getRegularValue=function(){var e=t.val().trim();return e=""==e?null:Number(e)},n.setRegularValue=function(e){t.val(e)},n.parseUnit=function(e){if(null==e||""===e)return n.defaultUnit;for(var t=0;t").attr("id",i).addClass("plate-setup-tab-select-field");this.defaultWell[i]=null,t.root.find(".plate-setup-tab-field-container").append(a);var e={data:[{id:"true",text:"true"},{id:"false",text:"false"}],placeholder:"select",allowClear:!0,minimumResultsForSearch:-1};a.select2(e),t.disabled=function(e){t.input.prop("disabled",e)},t.parseValue=function(e){if(null==e)return null;var t=String(e).trim().toLowerCase();if("true"==t)t=!0;else if("false"==t)t=!1;else{if(""!=t)throw"Invalid value "+e+" for boolean field "+i;t=null}return t},t.getValue=function(){switch(a.val()){case"true":return!0;case"false":return!1;default:return null}},t.setValue=function(e){e=1==e||"true"==e?"true":0==e||"false"==e?"false":null,a.val(e),a.trigger("change.select2")},t.getText=function(e){return null==e?"":e.toString()},t.parseText=t.parseValue,a.on("change",function(e){t.onChange()}),a.on("select2:unselect",function(e){a.one("select2:opening",function(e){e.preventDefault()})}),t.input=a},_createMultiplexField:function(o){var d=this;this._createMultiSelectField(o),d.defaultWell[o.id]=[];var e=d._createElement("
").addClass("plate-setup-tab-name-singleSelect").text("Select to edit"),t=d._createElement("
").addClass("plate-setup-tab-field-container-singleSelect");o.root.find(".plate-setup-tab-field-right-side").append(e,t),o.singleSelect=this._createElement(" ").attr("id",o.id+"SingleSelect").addClass("plate-setup-tab-multiplex-single-select-field"),o.singleSelect.appendTo(t),o.singleSelectValue=function(){return o.singleSelect.val()};var c=function(e,t){var i={allowClear:!1,placeholder:"select",minimumResultsForSearch:10,data:e||[]};t||(t=i.data.length?i.data[0].id:null),o.singleSelect.hasClass("select2-hidden-accessible")&&o.singleSelect.select2("destroy"),o.singleSelect.val(null),o.singleSelect.empty(),o.singleSelect.select2(i),o.singleSelect.val(t),o.singleSelect.prop("disabled",0==i.data.length),o.singleSelect.trigger("change.select2"),o.singleSelect.on("change.select2",u)},u=function(){var t=o.singleSelectValue();o.updateSubFieldUnitOpts(t);var e=o.detailData||[],i=null;e.forEach(function(e){e[o.id]===t&&(i=e)}),i?o.subFieldList.forEach(function(e){e.disabled(!1),e.setValue(i[e.id])}):o.subFieldList.forEach(function(e){e.disabled(!0),e.setValue(null)}),d.readOnlyHandler()};c([]),o._changeMultiFieldValue=function(e,t){var i,a={};for(var n in o.data.multiplexFields){a[o.data.multiplexFields[n].id]=null}e&&(i=e.value?e.value:(a[o.id]=e.id,a),e={id:e.id,value:i}),t&&(i=t.value?t.value:(a[o.id]=t.id,a),t={id:t.id,value:i});var l={};l[o.id]={multi:!0,added:e,removed:t},d._addAllData(l)};var a=o.setValue;o.setValue=function(e){var t=null;(o.detailData=e)&&e.length&&(t=e.map(function(e){return e[o.id]})),a(t);var i=o.input.select2("data")||[];c(i),u()},o.disabled=function(t){o.input.prop("disabled",t),o.subFieldList.forEach(function(e){e.disabled(t)}),t?e.text("Select to inspect"):e.text("Select to edit")},o.parseValue=function(e){var t=e;return t=t&&t.length?t.map(function(t){var i={};for(var a in i[o.id]=t[o.id],t)o.subFieldList.forEach(function(e){e.id===a&&(i[e.id]=e.parseValue(t[a]))});return i}):null},o.updateSubFieldUnitOpts=function(t){var i;o.data.options.forEach(function(e){e.id===t&&(i=e)}),o.subFieldList.forEach(function(e){e.data.hasMultiplexUnit&&(i&&i.hasOwnProperty("unitOptions")?e.setUnitOpts(i.unitOptions[e.id]):e.setUnitOpts(null))})},o.multiOnChange=function(e,t){o._changeMultiFieldValue(e,t);var i=o.getValue(),l=o.detailData,s=[],a=null;l&&(s=l.map(function(e){return e[o.id]}));var r=[],n=[];i&&(i.forEach(function(a){if(l&&l.forEach(function(e){e[o.id]===a&&r.push(e)}),s.indexOf(a)<0){var n={};n[o.id]=a,o.updateSubFieldUnitOpts(a),o.subFieldList.forEach(function(i){if(i.hasUnits)if(i.data.hasMultiplexUnit)i.disabled(!1),o.data.options.forEach(function(e){if(e.id===a){var t={value:null,unit:i.units[0]};n[i.id]=i.parseValue(t)}});else{i.data.units&&1").addClass("delete-dialog modal");function l(){n.hide(),n.remove()}f("body").append(n);var s=f("
").addClass("modal-content").appendTo(n),r=f("
").appendTo(s),o=f("
").addClass("dialog-buttons").css("justify-content","flex-end").appendTo(s);if(0 ").text(t.name+" in selected wells: choose items to delete and click the delete button below").appendTo(r);var d=i._deleteDialogTable(t,a);if(d.appendTo(r),d.addClass("plate-popout-table"),d.find("td").addClass("plate-popout-td"),d.find("th").addClass("plate-popout-th"),d.find("tr").addClass("plate-popout-tr"),!i.readOnly){var c=f("Delete Checked Items ");o.append(c),c.click(function(){d.find("input:checked").each(function(){var e=this.value;t.multiOnChange(null,{id:e})}),i.decideSelectedFields(),l()})}}else f("
").text("No "+t.name+" in the selected wells").appendTo(r);var u=f("Cancel ");o.append(u),u.click(l),n.show(),window.onclick=function(e){e.target==n[0]&&l()}},_deleteDialogTable:function(e,a){var n=this,t=[e.name,"Counts"];n.readOnly||t.push("Delete");var i=f(""),l=f(" ").appendTo(i);f(" ").appendTo(l).append(t.map(function(e){return f(" ").text(e)}));var s=f(" ").appendTo(i);return e.data.options.forEach(function(e){if(e.id in a){var t=f(" ").appendTo(s),i=f(" ").prop("value",e.id);f(" ").text(e.text).appendTo(t),f(" ").text(a[e.id]).appendTo(t),n.readOnly||f(" ").append(i).appendTo(t)}}),i},_createDeleteButton:function(e){var t=this,i=f(" ").addClass("plate-setup-remove-all-button");i.id=e.id+"Delete",i.text("Manage "+e.name+"...");var a=t._createElement("
").addClass("plate-setup-remove-all-button-container");a.append(i),e.deleteButton=i,e.root.find(".plate-setup-tab-field-right-side").append(a),i.click(function(){t._deleteDialog(e)})}}}}(jQuery,fabric);plateLayOutWidget=plateLayOutWidget||{};!function(b,e){plateLayOutWidget.engine=function(v){return{engine:{derivative:{},colorMap:new Map,stackUpWithColor:{},stackPointer:2,wellEmpty:function(e){for(var t in e){var i=e[t];if(null!=i){if(!Array.isArray(i))return!1;if(0 ").addClass("plate-setup-overlay-text-container"),this.overLayTextContainer.text("Completion Percentage:"),this.overLayContainer.append(this.overLayTextContainer),this.overLayButtonContainer=this._createElement("
").addClass("plate-setup-overlay-button-container"),this.overLayContainer.append(this.overLayButtonContainer),this.clearCriteriaButton=this._createElement("
").addClass("plate-setup-button"),this.clearCriteriaButton.text("Clear"),this.overLayButtonContainer.append(this.clearCriteriaButton),this.clearCriteriaButton.click(function(e){t.clearCriteria()}),this.copyCriteriaButton=this._createElement("
").addClass("plate-setup-button"),this.copyCriteriaButton.text("Copy"),this.overLayButtonContainer.append(this.copyCriteriaButton),this.copyCriteriaButton.click(function(e){t.copyCriteria()}),this.pasteCriteriaButton=this._createElement("
").addClass("plate-setup-button"),this.pasteCriteriaButton.text("Paste"),this.overLayButtonContainer.append(this.pasteCriteriaButton),this.pasteCriteriaButton.click(function(e){t.pasteCriteria()}),this.undoButton=this._createElement("
").addClass("plate-setup-button"),this.undoButton.text("Undo"),this.overLayButtonContainer.append(this.undoButton),this.undoButton.click(function(e){t.undo()}),this.redoButton=this._createElement("
").addClass("plate-setup-button"),this.redoButton.text("Redo"),this.overLayButtonContainer.append(this.redoButton),this.redoButton.click(function(e){t.redo()})},clearCriteria:function(){if(this.allSelectedObjects){for(var e=this.allSelectedObjects.length,t=!1,i=0;i
=t.rows*t.cols)throw"Index too high: "+e.toString(10);var i={};return i.c=e%t.cols,i.r=(e-i.c)/t.cols,i},locToAddress:function(e){return this._rowKey(e.r)+(e.c+1).toString(10)},indexToAddress:function(e,t){var i=this.indexToLoc(e,t);return this.locToAddress(i)},getDimensions:function(){return $.extend(!0,{},this.dimensions)},_create:function(){var e=parseInt(this.options.numRows||8),t=parseInt(this.options.numCols||12);this.dimensions={rows:e,cols:t},this.rowIndex=[];for(var i=0;i ").addClass("plate-setup-well-attr-container").text("Checkbox presets"),this.tabContainer.append(this.wellAttrContainer),this.presetTabContainer=this._createElement("
").addClass("plate-setup-preset-container"),this.tabContainer.append(this.presetTabContainer);for(var t=0;t ").addClass("plate-setup-prest-tab-div").text(i.title),n=this._createElement("
").addClass("plate-setup-prest-tab").data("preset",i.fields).append(a);this.presetTabContainer.append(n);var l=this;n.click(function(){var e=s(this);l._selectPreset(e)}),this.presets.push(n)}}},_clearPresetSelection:function(){for(var e=0;e").addClass("plate-setup-tab-container"),a(this.topRight).append(this.tabContainer)},_createTabs:function(){this.tabHead=this._createElement("
").addClass("plate-setup-tab-head"),a(this.tabContainer).append(this.tabHead);var e=this.options.attributes.tabs,i=this;e.forEach(function(e,t){i.allTabs[t]=i._createElement("
").addClass("plate-setup-tab"),a(i.allTabs[t]).data("index",t).text(e.name),a(i.allTabs[t]).click(function(){i._tabClickHandler(this)}),a(i.tabHead).append(i.allTabs[t])}),this.tabDataContainer=this._createElement("
").addClass("plate-setup-tab-data-container"),a(this.tabContainer).append(this.tabDataContainer),this._addDataTabs(e),a(this.allTabs[0]).click(),this._addTabData()},_tabClickHandler:function(e){if(this.selectedTab){a(this.selectedTab).removeClass("plate-setup-tab-selected").addClass("plate-setup-tab");var t=a(this.selectedTab).data("index");a(this.allDataTabs[t]).css("z-index",0),this.readOnlyHandler()}a(e).addClass("plate-setup-tab-selected"),this.selectedTab=e;var i=a(e).data("index");a(this.allDataTabs[i]).css("z-index",1e3)},_addDataTabs:function(e){var t=0;for(var i in e)this.allDataTabs[t++]=this._createElement("
").addClass("plate-setup-data-div").css("z-index",0),a(this.tabDataContainer).append(this.allDataTabs[t-1])}}}}(jQuery,fabric);plateLayOutWidget=plateLayOutWidget||{};!function(i,e){plateLayOutWidget.undoRedoManager=function(e){return{undoRedoArray:[],actionPointer:null,addToUndoRedo:function(e){if(null!=this.actionPointer){var t=this.actionPointer+1;t=this.undoRedoArray.length)&&(this.undoRedoActive=!0,this.setData(this.undoRedoArray[e]),this.actionPointer=e,this.undoRedoActive=!1,this.derivativeChange(),!0))}}}}(jQuery,fabric);plateLayOutWidget=plateLayOutWidget||{};jQuery,fabric,plateLayOutWidget.wellArea=function(e){return{_areasToTiles:function(e){var l=this.dimensions.cols,s=this;return e.reduce(function(e,t){if(t)for(var i=t.minRow;i<=t.maxRow;i++)for(var a=t.minCol;a<=t.maxCol;a++){var n=s.allTiles[a+l*i];e.indexOf(n)<0&&(s.disableAddDeleteWell?0<=s.addressAllowToEdit.indexOf(n.address)&&e.push(n):e.push(n))}return e},[])},_encodeArea:function(e){return e.minRow==e.maxRow&&e.minCol==e.maxCol?this.rowIndex[e.minRow]+e.minCol.toString(10):this.rowIndex[e.minRow]+e.minCol.toString(10)+":"+this.rowIndex[e.maxRow]+e.maxCol.toString(10)},_encodeAreas:function(e){var t=this;return e.map(function(e){return t._encodeArea(e)}).join(",")},_decodeWell:function(e){var t,i=new RegExp("^\\s*("+this.rowIndex.join("|")+")(\\d+)\\s*$");if(t=e.match(i)){var a=this.rowIndex.indexOf(t[1]);if(0<=a)return{row:a,col:parseInt(t[2])-1}}if(t=e.match(/^\s*R(\d+)C(\d+)\s*$/i))return{row:parseInt(t[1])-1,col:parseInt(t[2])-1};throw"Invalid well address: "+e},_decodeArea:function(e){var t=this,i=e.split(":").map(function(e){return t._decodeWell(e)});if(1==i.length)return{minRow:i[0].row,minCol:i[0].col,maxRow:i[0].row,maxCol:i[0].col};if(2!=i.length)throw"Invalid address: "+e;return Math.min(i[0].row,i[1].row),{minRow:Math.min(i[0].row,i[1].row),minCol:Math.min(i[0].col,i[1].col),maxRow:Math.max(i[0].row,i[1].row),maxCol:Math.max(i[0].col,i[1].col)}},_decodeAreas:function(e){var t=this;return e.split(",").map(function(e){return t._decodeArea(e)})},_wellToArea:function(e){return{minCol:e.col,minRow:e.row,maxCol:e.col,maxRow:e.row}},_wellInArea:function(e,t){return e.row>=t.minRow&&e.row<=t.maxRow&&e.col>=t.minCol&&e.col<=t.maxCol},_coordsToRect:function(e,t){var i=Math.min(e.x,t.x);return{top:Math.min(e.y,t.y),left:i,height:Math.abs(t.y-e.y),width:Math.abs(t.x-e.x)}},_coordIndex:function(e,t){return e<0?0:t<=e?t-1:Math.floor(e)},_coordsToWell:function(e){var t=this.dimensions.cols,i=this.dimensions.rows,a=this.sizes.spacing,n=this.sizes.label_spacing,l=(e.x-n)/a,s=(e.y-n)/a;return{row:this._coordIndex(s,i),col:this._coordIndex(l,t)}},_wellToCoords:function(e,t){var i=this.sizes.spacing,a=this.sizes.label_spacing,n=e.col*i+a,l=e.row*i+a;if(t){var s=i/2;n+=s,l+=s}return{x:n,y:l}},_areaToRect:function(e){var t=e.maxRow-e.minRow+1,i=e.maxCol-e.minCol+1,a=this.sizes.spacing,n=this.sizes.label_spacing;return{top:e.minRow*a+n,left:e.minCol*a+n,height:t*a,width:i*a}},_rectToArea:function(e){var t=this.dimensions.rows,i=this.dimensions.cols,a=this.sizes.spacing,n=this.sizes.label_spacing,l=(e.left-n)/a,s=(e.top-n)/a,r=e.height/a,o=l+e.width/a,d=s+r;return o<0&&(o=i),i<=l&&(l=0),d<0&&(d=t),s<=0&&(s=0),{minCol:this._coordIndex(l,i),minRow:this._coordIndex(s,t),maxCol:this._coordIndex(o,i),maxRow:this._coordIndex(d,t)}}}};
+//# sourceMappingURL=plate-map.min.js.map
\ No newline at end of file
diff --git a/dist/js/plate-map.min.js.map b/dist/js/plate-map.min.js.map
new file mode 100644
index 0000000..9eb5f94
--- /dev/null
+++ b/dist/js/plate-map.min.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["add-data-on-change.js","add-data-to-tabs.js","add-tab-data.js","add-warning-msg.js","bottom-table.js","canvas.js","check-box.js","color-manager.js","create-canvas-elements.js","create-field.js","engine.js","fabric-events.js","image_assets.js","interface.js","load-plate.js","main.js","overlay.js","plate-layout.js","preset.js","tabs.js","undo-redo-manager.js","well-area.js"],"names":["plateLayOutWidget","$","fabric","addDataOnChange","_addAllData","data","this","allSelectedObjects","noOfSelectedObjects","length","wells","objectIndex","well","tile","index","engine","derivative","extend","defaultWell","processedData","processWellData","wellEmpty","emptyWellWithDefaultVal","disableAddDeleteWell","wellCopy","JSON","parse","stringify","defaultValue","key","_applyFieldData","_getAllMultipleVal","applyFieldWarning","_colorMixer","derivativeChange","newData","curWell","wellList","id","v","undefined","multi","curData","preData","newDt","_getMultiData","push","fieldId","addNew","added","removed","value","add","listIdx","toString","map","val","subFieldId","indexOf","removeIndex","removeListIndex","newPreData","idx","parseInt","undoRedoActive","createObject","addToUndoRedo","searchAndStack","applyColors","mainFabricCanvas","renderAll","_trigger","checkboxes","globalSelectedAttributes","slice","selectedAreas","focalWell","requiredField","jQuery","addDataToFields","_addDataToTabFields","values","fieldMap","setValue","addTabData","fieldList","autoId","_addTabData","tabData","options","attributes","tabs","that","multiplexFieldArray","forEach","tab","tabPointer","tabFields","fieldArray","field","field_val","console","log","type","_makeMultiplexField","_makeRegularField","allDataTabs","multipleFieldList","_makeSubField","wrapperDiv","_createElement","addClass","wrapperDivLeftSide","wrapperDivRightSide","nameContainer","text","name","fieldContainer","append","root","required","checkbox","_addCheckBox","_createField","onChange","getValue","subFieldList","requiredSubField","subFieldKey","multiplexFields","subFieldData","subField","multiplexId","subFields","subfield","mainMultiplexField","mainRefField","curId","singleSelectValue","curVal","returnVal","_changeMultiFieldValue","curDataLs","detailData","input","addWarningMsg","fieldWarningMsg","include","imgId","img","html","_assets","warningImg","attr","find","prepend","popText","hover","e","style","display","hide","remove","removeWarningMsg","fieldData","i","applyMultiplexSubFieldColor","Array","bottomTable","_bottomScreen","bottomContainer","bottomTableContainer","container","addBottomTableHeadings","bottomRow","singleField","empty","rowCounter","adjustFieldWidth","tileAttrText","getText","addBottomTableRow","color","singleStack","modelTile","allTiles","row","plateIdDiv","numberText","click","evt","addressToSelect","addressIdx","indexToAddress","ctrlKey","getSelectedAddress","setSelectedWell","selectedAddress","colorPairs","colorStops","css","dataDiv","bottomForFirstTime","createExportButton","downloadCSV","csv","filename","csvFile","downloadLink","Blob","document","createElement","download","href","window","URL","createObjectURL","body","appendChild","exportData","format","rows","querySelectorAll","colorLocMap","colorLocIdxMap","stackUpWithColor","dim","getDimensions","colorIdx","locIdx","cols","j","innerText","replace","loc","join","overlayContainer","descriptionDiv","buttonContainer","exportButton","resetExportText","classList","setTimeout","clipboardButton","clipboard","ClipboardJS","get","resetClipboardText","on","canvas","allPreviouslySelectedObjects","colorPointer","goldenRatio","_createCanvas","normalCanvas","canvasContainer","_initiateFabricCanvas","w","width","h","height","_setCanvasArea","Canvas","backgroundColor","selection","stateful","hoverCursor","renderOnAddRemove","setWidth","setHeight","checkBox","checkImage","dontImg","_applyCheckboxHandler","checkBoxImage","machineClick","changes","changeCheckboxes","changeSubFieldsCheckboxes","subFieldToInclude","clicked","Boolean","doImg","gsa","multiplexCheckedSubField","globalSelectedMultiplexSubfield","_clearPresetSelection","setSubFieldCheckboxes","fieldIds","setCheckboxes","colorManager","createCanvasElements","scaleFactor","baseSizes","spacing","tile_radius","center_radius_complete","center_radius_incomplete","label_size","label_spacing","text_size","stroke","gap","Math","min","dimensions","sizes","prop","_canvas","_fixRowAndColumn","_putCircles","d1","d2","fontSize","top","left","tempFabricText","IText","fill","originX","originY","fontFamily","selectable","fontWeight","rowIndex","tileCounter","col","_createTile","background","highlight","circle","circleCenter","circleText","_addLargeRectangleOverlay","_fabricEvents","visible","colorIndex","address","Circle","radius","hasControls","hasBorders","lockMovementX","lockMovementY","evented","setGradient","x1","x2","y1","y2","r1","r2","0","1","Rect","strokeWidth","lockScalingX","lockScalingY","setTileComplete","complete","setTileVisible","setTileColor","String","overLay","opacity","createField","_createTextField","_createNumericField","_createSelectField","_createMultiSelectField","_createBooleanField","_createMultiplexField","parseValue","trim","disabled","bool","parseText","generated","_createOpts","config","opts","allowClear","placeholder","minimumResultsForSearch","data_specified","ajax","optMap","opt","select2","trigger","one","preventDefault","multiple","multiOnChange","params","_createDeleteButton","units","defaultUnit","unitInput","hasUnits","unitText","selected","unit","setUnitOpts","newUnits","curUnit","cleanUnit","newOpts","isPlainObject","parseRegularValue","parseUnit","getRegularValue","isNaN","getUnit","hasMultiplexUnit","unitTypeKey","unitMap","setUnit","setRegularValue","Number","toLowerCase","u","getRegularText","textVal","removeClass","nameContainer1","fieldContainer1","singleSelect","appendTo","setSingleSelectOptions","selected_v","hasClass","singleSelectChange","updateSubFieldUnitOpts","curSubField","readOnlyHandler","newSubFieldValue","subFieldName","multiselectSetValue","multiselectValues","newOptions","valMap","curOpts","hasOwnProperty","unitOptions","curIds","curOpt","newMultiplexVal","selectList","selectedVal","newVal","selectId","checkedSubfields","valIdx","subV","subText","optId","x","checkMultiplexCompletion","valList","valCount","completionPct","getSubfieldStatus","vals","req","subFieldWarningMap","warningStatus","multiplexVals","multiplexIdx","updateSubFieldWarningMap","mainFieldStatus","warningText","mainFieldWarning","parseMainFieldVal","_deleteDialog","valToRemove","allSelectedMultipleVal","Object","keys","dialogDiv","killDialog","dialogContent","tableArea","buttonRow","table","_deleteDialogTable","readOnly","deleteCheckedButton","each","decideSelectedFields","cancelButton","show","onclick","event","target","colName","thead","tbody","tr","deleteButton","THIS","colorMap","Map","stackPointer","isArray","derivativeJson","wellData","selectedSubFields","curMultiplexVals","isEmptyObject","k","parseFloat","sort","a","b","refDerivativeIndex","referenceDerivative","arr","wholeNoTiles","wholePercentage","tileIndex","set","completion","checkCompletion","floor","overLayTextContainer","multiplexStatus","fabricEvents","colorToIndex","startCoords","y","_clickCoords","rect","getBoundingClientRect","clientX","clientY","getPlates","selecting","coords","areas","_wellToCoords","_coordsToRect","_coordsToWell","shiftKey","_rectToArea","setSelection","endCoords","area","scrollToGroup","selectObjectInBottomTab","_areasToTiles","_setSelectedTiles","_setFocalWellRect","activeElement","blur","flag","locToAddress","r","c","addressAllowToEdit","setFieldsDisabled","_areaToRect","_wellToArea","focalWellRect","selectedTiles","_getSelectedWells","_getCommonFields","referenceWell","referenceFields","fields","refArr","agrArr","containsObject","inArray","obj","list","equality","evaluate","listKey","_getCommonWell","multiplexField","curMultipleVal","multipleVal","getDifferentWellsVals","wellsHash","wellId","differentWellsVals","commonWell","allFieldVal","fieldIdx","wellIdx","diffWellVal","curWellData","commonVal","curMultiVal","getWellSetAddressWithData","assets","interface","_createInterface","divIdentifier","topSection","topLeft","topRight","overLayContainer","_createOverLay","element","_createTabAtRight","_createTabs","_placePresetTabs","_setShortcuts","keyup","_handleShortcuts","_configureUndoRedoArray","addEventListener","copyCriteria","clearCriteria","pasteCriteria","keyCode","metaKey","redo","undo","loadPlate","sanitizeWell","sanitizeAreas","sanitized","setData","minCol","_coordIndex","maxCol","minRow","maxRow","max","_wellInArea","newWell","GET_PLATES","IS_READ_ONLY","IS_DISABLE_ADD_DELETE_WELL","GET_SELECTED_OBJECT","SETSELECTEDWELL","scrollTo","to","duration","perTick","scrollTop","overlay","overLayButtonContainer","clearCriteriaButton","copyCriteriaButton","pasteCriteriaButton","undoButton","redoButton","hasWellUpdate","alert","widget","addressToLoc","layoutAddress","m","exec","toUpperCase","row_v","charCodeAt","locToIndex","t","addressToIndex","_rowKey","c1","c2","code","fromCharCode","indexToLoc","_create","numRows","numCols","component","className","isReadOnly","_init","addData","getTextDerivative","wellsData","textDerivative","textValWell","textFieldIdWell","textFieldVal","getWellsDifferences","isDisableAddDeleteWell","column_with_default_val","actionPointer","undoRedoArray","getSelectedObject","selectedObjects","selectedObjectAddress","trs","tds","children","isSelected","querySelector","innerHTML","offsetTop","getSelectedIndex","selectedObj","addressList","locMap","apply","preset","me","presets","wellAttrContainer","tabContainer","presetTabContainer","divText","title","presetButton","_selectPreset","allTabs","tabHead","tabIndex","_tabClickHandler","tabDataContainer","_addDataTabs","clickedTab","selectedTab","previouslyClickedTabIndex","clickedTabIndex","undoRedoManager","splice","shiftUndoRedo","pointerDiff","pointer","setUndoRedo","wellArea","reduce","tiles","_encodeArea","_encodeAreas","_decodeWell","wellAddress","match","adRx","RegExp","_decodeArea","areaAddress","split","_decodeAreas","areasAddress","abs","count","coord","center","hw","right","bottom"],"mappings":"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","file":"plate-map.min.js","sourcesContent":["var plateLayOutWidget = plateLayOutWidget || {};\n\n(function($, fabric) {\n\n plateLayOutWidget.addDataOnChange = function() {\n // This object is invoked when something in the tab fields change\n return {\n\n _addAllData: function(data) {\n // Method to add data when something changes in the tabs. Its going to be tricky , just starting.\n if (this.allSelectedObjects) {\n var noOfSelectedObjects = this.allSelectedObjects.length;\n var wells = [];\n for (var objectIndex = 0; objectIndex < noOfSelectedObjects; objectIndex++) {\n var tile = this.allSelectedObjects[objectIndex];\n var well;\n if (tile.index in this.engine.derivative) {\n well = this.engine.derivative[tile.index];\n } else {\n well = $.extend(true, {}, this.defaultWell);\n this.engine.derivative[tile.index] = well;\n }\n var processedData = this.processWellData(data, well, noOfSelectedObjects, wells);\n wells = processedData.wells;\n well = processedData.well;\n var empty = this.engine.wellEmpty(well);\n if (empty) {\n if (this.emptyWellWithDefaultVal && this.disableAddDeleteWell) {\n var wellCopy = JSON.parse(JSON.stringify(well));\n var defaultValue = this.emptyWellWithDefaultVal;\n for (var key in defaultValue) {\n if (key in wellCopy) {\n wellCopy[key] = defaultValue[key];\n this._applyFieldData(key, defaultValue[key]);\n }\n }\n this.engine.derivative[tile.index] = wellCopy;\n } else {\n delete this.engine.derivative[tile.index];\n }\n }\n }\n }\n // update multiplex remove all field\n this._getAllMultipleVal(wells);\n this.applyFieldWarning(wells);\n // create well when default field is sent for the cases when user delete all fields during disabledNewDeleteWell mode\n this._colorMixer();\n this.derivativeChange();\n },\n\n processWellData: function(newData, curWell, noOfSelectedObjects, wellList) {\n\n if (!wellList) {\n wellList = [];\n }\n for (var id in newData) {\n var v;\n if (newData[id] !== undefined && newData[id] !== null) {\n if (newData[id].multi) {\n var curData = newData[id];\n var preData = curWell[id];\n var newDt = this._getMultiData(preData, curData, id, noOfSelectedObjects);\n // need to replace newData\n v = JSON.parse(JSON.stringify(newDt));\n } else {\n v = JSON.parse(JSON.stringify(newData[id]));\n }\n } else {\n v = JSON.parse(JSON.stringify(newData[id]));\n }\n curWell[id] = v;\n wellList.push(curWell);\n }\n\n return {\n well: curWell,\n wells: wellList\n }\n },\n\n _getMultiData: function(preData, curData, fieldId, noOfSelectedObjects) {\n var addNew = curData.added;\n var removed = curData.removed;\n if (addNew) {\n if (preData) {\n if (addNew.value) {\n var add = true;\n for (var listIdx in preData) {\n var multiplexData = preData[listIdx];\n // for cases when the add new data exist in well\n if (multiplexData[fieldId].toString() === addNew.id.toString()) {\n add = false;\n // update subfield value\n preData = preData.map(function(val) {\n if (val[fieldId].toString() === addNew.id.toString()) {\n for (var subFieldId in val) {\n // over write previous data if only one well is selected\n if (subFieldId in addNew.value && subFieldId !== fieldId) {\n if (noOfSelectedObjects === 1) {\n val[subFieldId] = addNew.value[subFieldId];\n } else if (addNew.value[subFieldId]) {\n val[subFieldId] = addNew.value[subFieldId];\n }\n }\n }\n }\n return val;\n })\n }\n }\n if (add) {\n preData.push(addNew.value);\n }\n } else if (preData.indexOf(addNew) < 0) {\n preData.push(addNew);\n }\n } else {\n preData = [];\n if (addNew.value) {\n preData.push(addNew.value);\n } else if (addNew) {\n preData.push(addNew);\n }\n }\n }\n\n var removeListIndex = function(preData, removeIndex) {\n var newPreData = [];\n for (var idx in preData) {\n if (parseInt(idx) !== parseInt(removeIndex)) {\n newPreData.push(preData[idx]);\n }\n }\n return newPreData;\n };\n\n if (removed) {\n var removeIndex;\n // for multiplex field\n if (removed.value) {\n for (var listIdx in preData) {\n var multiplexData = preData[listIdx];\n if (multiplexData[fieldId].toString() === removed.id.toString()) {\n removeIndex = listIdx;\n }\n }\n // remove nested element\n preData = removeListIndex(preData, removeIndex);\n } else {\n if (preData) {\n removeIndex = preData.indexOf(removed);\n if (removeIndex >= 0) {\n preData = removeListIndex(preData, removeIndex);\n }\n }\n }\n }\n if (preData && (preData.length == 0)) {\n preData = null;\n }\n return preData\n },\n\n _colorMixer: function() {\n if (!this.undoRedoActive) {\n var data = this.createObject();\n this.addToUndoRedo(data);\n }\n this.engine.searchAndStack();\n this.engine.applyColors();\n this.mainFabricCanvas.renderAll();\n },\n\n derivativeChange: function() {\n this._trigger(\"updateWells\", null, this.createObject());\n },\n\n createObject: function() {\n var derivative = $.extend(true, {}, this.engine.derivative);\n var checkboxes = this.globalSelectedAttributes.slice();\n var selectedAreas = this.selectedAreas.slice();\n var focalWell = this.focalWell;\n\n return {\n \"derivative\": derivative,\n \"checkboxes\": checkboxes,\n \"selectedAreas\": selectedAreas,\n \"focalWell\": focalWell,\n \"requiredField\": this.requiredField\n };\n }\n };\n }\n})(jQuery, fabric);","var plateLayOutWidget = plateLayOutWidget || {};\n\n(function($, fabric) {\n\n plateLayOutWidget.addDataToFields = function() {\n\n return {\n\n _addDataToTabFields: function(values) {\n // Configure how data is added to tab fields\n for (var id in values) {\n this._applyFieldData(id, values[id]);\n }\n },\n\n _applyFieldData: function(id, v) {\n this.fieldMap[id].setValue(v);\n }\n }\n }\n})(jQuery, fabric)","var plateLayOutWidget = plateLayOutWidget || {};\n\n(function($, fabric) {\n\n plateLayOutWidget.addTabData = function() {\n\n return {\n\n fieldList: [],\n fieldMap: {},\n autoId: 1,\n\n _addTabData: function() {\n // Here we may need more changes because attributes format likely to change\n var tabData = this.options.attributes.tabs;\n var that = this;\n this.requiredField = [];\n var multiplexFieldArray = [];\n tabData.forEach(function(tab, tabPointer) {\n if (tab[\"fields\"]) {\n var tabFields = tab[\"fields\"];\n var fieldArray = [];\n var fieldArrayIndex = 0;\n // Now we look for fields in the json\n for (var field in tabFields) {\n var data = tabFields[field];\n\n if (!data.id) {\n data.id = \"Auto\" + that.autoId++;\n console.log(\"Field autoassigned id \" + data.id);\n }\n if (!data.type) {\n data.type = \"text\";\n console.log(\"Field \" + data.id + \" autoassigned type \" + data.type);\n }\n\n var field_val;\n if (data.type === \"multiplex\") {\n field_val = that._makeMultiplexField(data, tabPointer, fieldArray);\n multiplexFieldArray.push(field_val);\n } else {\n field_val = that._makeRegularField(data, tabPointer, fieldArray, true);\n if (data.type === \"multiselect\") {\n multiplexFieldArray.push(field_val);\n }\n }\n ;\n }\n\n that.allDataTabs[tabPointer][\"fields\"] = fieldArray;\n } else {\n console.log(\"unknown format in field initialization\");\n }\n });\n that.multipleFieldList = multiplexFieldArray;\n },\n\n _makeSubField: function(data, tabPointer, fieldArray) {\n var that = this;\n if (!data.id) {\n data.id = \"Auto\" + that.autoId++;\n console.log(\"Field autoassigned id \" + data.id);\n }\n if (!data.type) {\n data.type = \"text\";\n console.log(\"Field \" + data.id + \" autoassigned type \" + data.type);\n }\n var wrapperDiv = that._createElement(\"
\").addClass(\"plate-setup-tab-default-field\");\n var wrapperDivLeftSide = that._createElement(\"
\").addClass(\"plate-setup-tab-field-left-side\");\n var wrapperDivRightSide = that._createElement(\"
\").addClass(\"plate-setup-tab-field-right-side\");\n var nameContainer = that._createElement(\"
\").addClass(\"plate-setup-tab-name\").text(data.name);\n var fieldContainer = that._createElement(\"
\").addClass(\"plate-setup-tab-field-container\");\n\n $(wrapperDivRightSide).append(nameContainer);\n $(wrapperDivRightSide).append(fieldContainer);\n $(wrapperDiv).append(wrapperDivLeftSide);\n $(wrapperDiv).append(wrapperDivRightSide);\n $(that.allDataTabs[tabPointer]).append(wrapperDiv);\n\n var field = {\n id: data.id,\n name: data.name,\n root: wrapperDiv,\n data: data,\n required: data.required || false\n };\n\n fieldArray.push(field);\n that.fieldMap[data.id] = field;\n\n return field;\n },\n\n _makeRegularField: function(data, tabPointer, fieldArray, checkbox) {\n var that = this;\n var wrapperDiv = that._createElement(\"
\").addClass(\"plate-setup-tab-default-field\");\n var wrapperDivLeftSide = that._createElement(\"
\").addClass(\"plate-setup-tab-field-left-side\");\n var wrapperDivRightSide = that._createElement(\"
\").addClass(\"plate-setup-tab-field-right-side \");\n var nameContainer = that._createElement(\"
\").addClass(\"plate-setup-tab-name\").text(data.name);\n var fieldContainer = that._createElement(\"
\").addClass(\"plate-setup-tab-field-container\");\n\n wrapperDivRightSide.append(nameContainer);\n wrapperDivRightSide.append(fieldContainer);\n wrapperDiv.append(wrapperDivLeftSide);\n wrapperDiv.append(wrapperDivRightSide);\n that.allDataTabs[tabPointer].append(wrapperDiv);\n\n var field = {\n id: data.id,\n name: data.name,\n root: wrapperDiv,\n data: data,\n required: data.required\n };\n\n if (field.required) {\n that.requiredField.push(field.id);\n }\n\n fieldArray.push(field);\n that.fieldList.push(field);\n that.fieldMap[field.id] = field;\n\n // Adding checkbox\n if (checkbox) {\n that._addCheckBox(field);\n }\n that._createField(field);\n\n field.onChange = function() {\n var v = field.getValue();\n var data = {};\n data[field.id] = v;\n that._addAllData(data);\n };\n return field;\n },\n\n _makeMultiplexField: function(data, tabPointer, fieldArray) {\n var that = this;\n var wrapperDiv = that._createElement(\"
\").addClass(\"plate-setup-tab-default-field\");\n var wrapperDivLeftSide = that._createElement(\"
\").addClass(\"plate-setup-tab-field-left-side\");\n var wrapperDivRightSide = that._createElement(\"
\").addClass(\"plate-setup-tab-field-right-side \");\n var nameContainer = that._createElement(\"
\").addClass(\"plate-setup-tab-name\").text(data.name);\n var fieldContainer = that._createElement(\"
\").addClass(\"plate-setup-tab-field-container\");\n\n wrapperDivRightSide.append(nameContainer);\n wrapperDivRightSide.append(fieldContainer);\n wrapperDiv.append(wrapperDivLeftSide);\n wrapperDiv.append(wrapperDivRightSide);\n that.allDataTabs[tabPointer].append(wrapperDiv);\n\n var field = {\n id: data.id,\n name: data.name,\n root: wrapperDiv,\n data: data,\n required: data.required\n };\n\n fieldArray.push(field);\n that.fieldList.push(field);\n that.fieldMap[data.id] = field;\n\n var subFieldList = [];\n //create subfields\n var requiredSubField = [];\n for (var subFieldKey in data.multiplexFields) {\n var subFieldData = data.multiplexFields[subFieldKey];\n var subField = that._makeSubField(subFieldData, tabPointer, fieldArray);\n subFieldList.push(subField);\n\n // stores required subField\n if (subFieldData.required) {\n requiredSubField.push(subField.id);\n }\n }\n\n //store required field\n if (field.required || requiredSubField.length) {\n this.requiredField.push({\n multiplexId: field.id,\n subFields: requiredSubField\n });\n }\n\n field.subFieldList = subFieldList;\n that._createField(field);\n that._addCheckBox(field);\n\n subFieldList.forEach(function(subfield) {\n subfield.mainMultiplexField = field;\n fieldArray.push(subfield);\n that._createField(subfield);\n that._addCheckBox(subfield);\n delete that.defaultWell[subfield.id];\n // overwrite subField setvalue\n subfield.onChange = function() {\n var v = subfield.getValue();\n var mainRefField = subfield.mainMultiplexField;\n var curId = mainRefField.singleSelectValue();\n //var curDataLs = mainRefField.detailData;\n var curVal = {};\n curVal[mainRefField.id] = curId;\n //append subfields\n curVal[subfield.id] = v;\n var returnVal = {\n id: curId,\n value: curVal\n };\n\n field._changeMultiFieldValue(returnVal, null);\n var curDataLs = mainRefField.detailData;\n if (curDataLs !== null) {\n curId = mainRefField.singleSelectValue();\n curDataLs = curDataLs.map(function(curData) {\n if (curData[mainRefField.id] === curId) {\n curData[subfield.id] = v;\n }\n return curData;\n });\n }\n mainRefField.detailData = curDataLs;\n };\n\n });\n\n field.getValue = function() {\n var v = field.input.val();\n if (v.length) {\n return v;\n }\n return null;\n };\n\n return field;\n }\n }\n }\n\n})(jQuery, fabric);\n","var plateLayOutWidget = plateLayOutWidget || {};\n\n(function($, fabric) {\n\n plateLayOutWidget.addWarningMsg = function() {\n // For those check boxes associated with every field in the tab\n return {\n fieldWarningMsg: function(field, text, include) {\n var that = this;\n var imgId = \"fieldWarning\" + field.id;\n var img = $(\"\").html(that._assets.warningImg).attr(\"id\", imgId).addClass(\"plate-field-warning-image\");\n //field.root.find(\".plate-setup-tab-name\").append(' ')\n if (include) {\n if (field.root.find(\"#\" + imgId).length <= 0) {\n field.root.find(\".plate-setup-tab-name\").text(\" \" + field.name);\n field.root.find(\".plate-setup-tab-name\").prepend(img);\n\n var popText = $(\"
\").addClass(\"pop-out-text\");\n popText.text(text);\n field.root.find(\".plate-setup-tab-name\").append(popText);\n\n $(\"#\" + imgId).hover(function(e) {\n popText[0].style.display = 'flex';\n }, function() {\n popText.hide();\n });\n }\n\n\n } else {\n if (field.root.find(\"#\" + imgId).length > 0) {\n field.root.find(\".plate-setup-tab-name\").text(field.name);\n $(\"#\" + imgId).remove();\n }\n }\n },\n\n removeWarningMsg: function(field, text, include) {\n var that = this;\n var imgId = \"fieldWarning\" + field.id;\n var img = $(\"\").html(that._assets.warningImg).attr(\"id\", imgId).addClass(\"plate-field-warning-image\");\n //field.root.find(\".plate-setup-tab-name\").append(' ')\n if (include) {\n field.root.find(\".plate-setup-tab-name\").append(img);\n\n var popText = $(\"
\").addClass(\"pop-out-text\");\n popText.text(text);\n field.root.find(\".plate-setup-tab-name\").append(popText);\n\n $(\"#\" + imgId).hover(function(e) {\n popText[0].style.display = 'inline-block';\n }, function() {\n popText.hide();\n });\n\n } else {\n $(\"#\" + imgId).remove();\n if (field.root.find(\"#\" + imgId).length > 0) {\n //field.root.find(\".plate-setup-tab-name\").remove(img);\n $(\"#\" + imgId).remove();\n }\n }\n },\n\n applyFieldWarning: function(wells) {\n var that = this;\n var req = 0;\n var fill = 0;\n var fieldData = {};\n that.fieldList.forEach(function(field) {\n fieldData[field.id] = [];\n });\n wells.forEach(function(well) {\n if (!that.engine.wellEmpty(well)) {\n for (var fieldId in fieldData) {\n if (fieldId in well) {\n fieldData[fieldId].push(well[fieldId]);\n } else {\n fieldData[fieldId].push(null);\n }\n }\n }\n });\n for (var i = 0; i < that.fieldList.length; i++) {\n var field = that.fieldList[i];\n if (field.applyMultiplexSubFieldColor) {\n field.applyMultiplexSubFieldColor(fieldData[field.id]);\n } else {\n if (field.required) {\n var include = false;\n fieldData[field.id].forEach(function(val) {\n // for multiselect\n if (val instanceof Array) {\n if (val.length === 0) {\n include = true;\n }\n } else {\n if (val === null) {\n include = true;\n }\n }\n });\n //field.root.find(\".plate-setup-tab-name\").css(\"background\", color);\n that.fieldWarningMsg(field, \"required field\", include);\n }\n }\n }\n }\n }\n }\n})(jQuery, fabric);","var plateLayOutWidget = plateLayOutWidget || {};\n\n(function($, fabric) {\n\n plateLayOutWidget.bottomTable = function() {\n // for bottom table\n return {\n _bottomScreen: function() {\n this.bottomContainer = this._createElement(\"
\").addClass(\"plate-setup-bottom-container\");\n this.bottomTableContainer = this._createElement(\"
\").addClass(\"plate-setup-bottom-table-container\");\n this.bottomTable = this._createElement(\"\").addClass(\"plate-setup-bottom-table\");\n this.bottomTableContainer.append(this.bottomTable);\n this.bottomContainer.append(this.bottomTableContainer);\n this.container.append(this.bottomContainer);\n },\n\n addBottomTableHeadings: function() {\n\n this.bottomRow = this._createElement(\" \");\n\n var singleField = this._createElement(\" \")\n .text(\"Group\");\n this.bottomRow.prepend(singleField);\n // Now we append all the captions at the place.\n this.bottomTable.empty();\n this.bottomTable.append(this.bottomRow);\n\n this.rowCounter = 1;\n\n for (var i = 0; i < this.globalSelectedAttributes.length; i++) {\n var attr = this.globalSelectedAttributes[i];\n var field = this.fieldMap[attr];\n var singleField = this._createElement(\" \").text(field.name);\n this.bottomRow.append(singleField);\n this.rowCounter = this.rowCounter + 1;\n }\n\n this.adjustFieldWidth(this.bottomRow);\n },\n\n tileAttrText: function(tile, attr) {\n var well = this.engine.derivative[tile.index];\n var field = this.fieldMap[attr];\n return field.getText(well[attr]);\n },\n\n addBottomTableRow: function(color, singleStack) {\n var that = this;\n var modelTile = this.allTiles[singleStack[0]];\n var row = this._createElement(\" \");\n var plateIdDiv = this._createElement(\" \").addClass(\"plate-setup-bottom-id\");\n var numberText = this._createElement(\" \");\n numberText.addClass(\"plate-setup-color-text\");\n numberText.text(color);\n plateIdDiv.append(numberText);\n\n numberText.click(function(evt) {\n var addressToSelect = singleStack.map(function(addressIdx) {\n return that.indexToAddress(addressIdx)\n });\n if (evt.ctrlKey) {\n that.getSelectedAddress().forEach(function(val) {\n if (addressToSelect.indexOf(val) < 0) {\n addressToSelect.push(val);\n }\n })\n }\n that.setSelectedWell(addressToSelect);\n that._trigger(\"selectedWells\", null, {selectedAddress: that.getSelectedAddress()});\n });\n\n if (color > 0) {\n color = ((color - 1) % (this.colorPairs.length - 1)) + 1;\n }\n var colorStops = this.colorPairs[color];\n\n plateIdDiv.css(\"background\", \"linear-gradient(to right, \" + colorStops[0] + \" , \" + colorStops[1] + \")\");\n\n row.append(plateIdDiv);\n\n for (var i = 0; i < this.globalSelectedAttributes.length; i++) {\n var attr = this.globalSelectedAttributes[i];\n var text = this.tileAttrText(modelTile, attr);\n var dataDiv = this._createElement(\" \").text(text);\n row.append(dataDiv);\n }\n this.bottomTable.append(row);\n this.adjustFieldWidth(row);\n },\n\n bottomForFirstTime: function() {\n this.addBottomTableHeadings();\n // This is executed for the very first time.. !\n var row = this._createElement(\" \");\n\n var colorStops = this.colorPairs[0];\n var plateIdDiv = this._createElement(\" \");\n plateIdDiv.css(\"background\", \"-webkit-linear-gradient(left, \" + colorStops[0] + \" , \" + colorStops[1] + \")\");\n row.append(plateIdDiv);\n this.bottomTable.append(row);\n this.createExportButton();\n },\n\n adjustFieldWidth: function(row) {\n\n var length = this.rowCounter;\n if ((length) * 150 > 1024) {\n row.css(\"width\", (length) * 152 + \"px\");\n }\n },\n\n downloadCSV: function(csv, filename) {\n var csvFile;\n var downloadLink;\n\n // CSV file\n csvFile = new Blob([csv], {\n type: \"text/csv\"\n });\n\n // Download link\n downloadLink = document.createElement(\"a\");\n\n // File name\n downloadLink.download = filename;\n\n // Create a link to the file\n downloadLink.href = window.URL.createObjectURL(csvFile);\n\n // Hide download link\n downloadLink.style.display = \"none\";\n\n // Add the link to DOM\n document.body.appendChild(downloadLink);\n\n // Click download link\n downloadLink.click();\n },\n\n exportData: function(format) {\n var data = [];\n var rows = document.querySelectorAll(\"table tr\");\n\n var colorLocMap = {};\n var colorLocIdxMap = this.engine.stackUpWithColor;\n var dim = this.getDimensions();\n var that = this;\n for (var colorIdx in colorLocIdxMap) {\n colorLocMap[colorIdx] = colorLocIdxMap[colorIdx].map(function(locIdx) {\n return that.indexToAddress(locIdx, dim);\n })\n }\n\n for (var i = 0; i < rows.length; i++) {\n var row = [],\n cols = rows[i].querySelectorAll(\"td, th\");\n\n for (var j = 0; j < cols.length; j++) {\n var v = \"\";\n if (cols[j].innerText) {\n if (format === \"csv\") {\n v = '\"' + cols[j].innerText.replace(/\"/g, '\"\"') + '\"';\n } else {\n v = cols[j].innerText;\n }\n }\n row.push(v);\n\n // add location column\n if (i === 0 && j === 0) {\n if (format === \"csv\") {\n row.push('\"Location\"');\n } else if (format === 'clipboard') {\n row.push(\"Location\");\n }\n\n }\n if (i !== 0 && j === 0) {\n var loc = '';\n if (colorLocMap[parseInt(cols[j].innerText)]) {\n if (format === \"csv\") {\n loc = '\"' + colorLocMap[parseInt(cols[j].innerText)].join(\",\") + '\"';\n } else if (format === 'clipboard') {\n loc = colorLocMap[parseInt(cols[j].innerText)].join(\",\");\n }\n }\n row.push(loc);\n }\n }\n\n if (format === \"csv\") {\n data.push(row.join(\",\"));\n } else if (format === 'clipboard') {\n data.push(row.join(\"\\t\"));\n //data.push(row); // for text type\n }\n\n }\n if (format === \"csv\") {\n // Download CSV file\n this.downloadCSV(data.join(\"\\n\"), 'table.csv');\n } else if (format === 'clipboard') {\n //return formatTableToString(data); // for text type\n return data.join(\"\\n\");\n }\n },\n\n createExportButton: function() {\n var that = this;\n var overlayContainer = $(\"\").addClass(\"plate-setup-bottom-control-container\");\n\n var descriptionDiv = $(\"
\").addClass(\"plate-setup-overlay-text-container\");\n descriptionDiv.text(\"Color groups\");\n overlayContainer.append(descriptionDiv);\n\n var buttonContainer = $(\"
\").addClass(\"plate-setup-overlay-bottom-button-container\");\n\n // create export csv option\n var exportButton = $(\"
\").addClass(\"plate-setup-button\");\n exportButton.text(\"Export CSV\");\n buttonContainer.append(exportButton);\n\n exportButton.click(function() {\n that.exportData('csv');\n exportButton.text(\"Exported\");\n exportButton[0].classList.remove(\"plate-setup-button\");\n exportButton.addClass(\"plate-setup-clicked-button\");\n setTimeout(resetExportText, 3000);\n });\n\n function resetExportText() {\n exportButton.text(\"Export CSV\");\n exportButton[0].classList.remove(\"plate-setup-clicked-button\");\n exportButton.addClass(\"plate-setup-button\");\n }\n\n // creat clipboard option, CLipboard is an external js file located in vendor/asset/javascripts\n var clipboardButton = $(\"
\").addClass(\"plate-setup-button\");\n clipboardButton.text(\"Copy To Clipboard\");\n buttonContainer.append(clipboardButton);\n\n var clipboard = new ClipboardJS(clipboardButton.get(0), {\n text: function() {\n return that.exportData(\"clipboard\");\n }\n });\n\n clipboard.on('success', function(e) {\n clipboardButton.text(\"Copied as tab-delimited format\");\n clipboardButton[0].classList.remove(\"plate-setup-button\");\n clipboardButton.addClass(\"plate-setup-clicked-button\");\n setTimeout(resetClipboardText, 3000);\n });\n\n function resetClipboardText() {\n clipboardButton.text(\"Copy To Clipboard\");\n clipboardButton[0].classList.remove(\"plate-setup-clicked-button\");\n clipboardButton.addClass(\"plate-setup-button\");\n }\n\n clipboard.on('error', function(e) {\n clipboardButton.text(\"Failed to copy table to clipboard: browser may be incompatible\");\n setTimeout(resetClipboardText, 3000);\n });\n\n overlayContainer.append(buttonContainer);\n this.bottomContainer.prepend(overlayContainer);\n }\n };\n }\n})(jQuery, fabric);","var plateLayOutWidget = plateLayOutWidget || {};\n\n(function($, fabric) {\n\n plateLayOutWidget.canvas = function() {\n //\n return {\n\n allSelectedObjects: null, // Contains all the selected objets, when click and drag.\n\n allPreviouslySelectedObjects: null,\n\n colorPointer: 0,\n\n goldenRatio: 0.618033988749895,\n\n _createCanvas: function() {\n this.normalCanvas = this._createElement(\"
\").attr(\"id\", \"DNAcanvas\");\n $(this.canvasContainer).append(this.normalCanvas);\n },\n\n _initiateFabricCanvas: function() {\n var w = this.canvasContainer.width();\n var h = this.canvasContainer.height();\n\n this._setCanvasArea(w, h);\n\n this.mainFabricCanvas = new fabric.Canvas('DNAcanvas', {\n backgroundColor: '#f5f5f5',\n selection: false,\n stateful: false,\n hoverCursor: \"pointer\",\n renderOnAddRemove: false,\n })\n .setWidth(w)\n .setHeight(h);\n },\n\n };\n }\n})(jQuery, fabric);","var plateLayOutWidget = plateLayOutWidget || {};\n\n(function($, fabric) {\n\n plateLayOutWidget.checkBox = function() {\n // For those check boxes associated with every field in the tab\n return {\n\n globalSelectedAttributes: [],\n\n _addCheckBox: function(field) {\n var checkImage = $(\"\").html(this._assets.dontImg).addClass(\"plate-setup-tab-check-box bg-light\")\n .data(\"clicked\", false);\n checkImage.data(\"linkedFieldId\", field.id);\n field.root.find(\".plate-setup-tab-field-left-side\").empty().append(checkImage);\n this._applyCheckboxHandler(checkImage); // Adding handler for change the image when clicked\n field.checkbox = checkImage;\n },\n\n _applyCheckboxHandler: function(checkBoxImage) {\n // We add checkbox handler here, thing is it s not checkbox , its an image and we change\n // source\n var that = this;\n checkBoxImage.click(function(evt, machineClick) {\n var checkBox = $(this);\n\n var changes = {};\n changes[checkBox.data(\"linkedFieldId\")] = !checkBox.data(\"clicked\");\n\n that.changeCheckboxes(changes);\n });\n },\n\n changeSubFieldsCheckboxes: function(field, changes) {\n var that = this;\n var subFieldToInclude = [];\n\n field.subFieldList.forEach(function(subField) {\n var checkImage = subField.checkbox;\n var fieldId = checkImage.data(\"linkedFieldId\");\n var clicked = checkImage.data(\"clicked\");\n if (fieldId in changes) {\n clicked = Boolean(changes[fieldId]);\n }\n checkImage.data(\"clicked\", clicked);\n if (clicked) {\n checkImage.html(that._assets.doImg);\n subFieldToInclude.push(subField.id);\n } else {\n checkImage.html(that._assets.dontImg);\n }\n });\n return subFieldToInclude;\n },\n\n changeCheckboxes: function(changes) {\n var gsa = [];\n var multiplexCheckedSubField = {};\n for (var i = 0; i < this.fieldList.length; i++) {\n var field = this.fieldList[i];\n if (field.checkbox) {\n if (field.subFieldList) {\n multiplexCheckedSubField[field.id] = this.changeSubFieldsCheckboxes(field, changes);\n }\n\n var checkImage = field.checkbox;\n var fieldId = checkImage.data(\"linkedFieldId\");\n var clicked = checkImage.data(\"clicked\");\n if (fieldId in changes) {\n clicked = Boolean(changes[fieldId]);\n }\n checkImage.data(\"clicked\", clicked);\n if (clicked) {\n gsa.push(fieldId);\n checkImage.html(this._assets.doImg);\n } else {\n checkImage.html(this._assets.dontImg);\n }\n }\n }\n this.globalSelectedMultiplexSubfield = multiplexCheckedSubField;\n this.globalSelectedAttributes = gsa;\n this._clearPresetSelection();\n this._colorMixer();\n },\n\n setSubFieldCheckboxes: function(field, fieldIds) {\n var that = this;\n var subFieldToInclude = [];\n field.subFieldList.forEach(function(subField) {\n var checkImage = subField.checkbox;\n var fieldId = checkImage.data(\"linkedFieldId\");\n var clicked = fieldIds.indexOf(fieldId) >= 0;\n checkImage.data(\"clicked\", clicked);\n if (clicked) {\n checkImage.html(that._assets.doImg);\n subFieldToInclude.push(subField.id);\n } else {\n checkImage.html(that._assets.dontImg);\n }\n });\n return subFieldToInclude;\n },\n\n setCheckboxes: function(fieldIds) {\n fieldIds = fieldIds || [];\n var gsa = [];\n var multiplexCheckedSubField = {};\n\n for (var i = 0; i < this.fieldList.length; i++) {\n var field = this.fieldList[i];\n if (field.checkbox) {\n // special handling for multiplex field\n if (field.subFieldList) {\n multiplexCheckedSubField[field.id] = this.setSubFieldCheckboxes(field, fieldIds);\n }\n\n var checkImage = field.checkbox;\n var fieldId = checkImage.data(\"linkedFieldId\");\n var clicked = fieldIds.indexOf(fieldId) >= 0;\n checkImage.data(\"clicked\", clicked);\n if (clicked) {\n gsa.push(fieldId);\n checkImage.html(this._assets.doImg);\n } else {\n\n checkImage.html(this._assets.dontImg);\n }\n }\n }\n this.globalSelectedMultiplexSubfield = multiplexCheckedSubField;\n this.globalSelectedAttributes = gsa;\n this._clearPresetSelection();\n this._colorMixer();\n }\n\n };\n }\n})(jQuery, fabric);","var plateLayOutWidget = plateLayOutWidget || {};\n\n(function($, fabric) {\n\n plateLayOutWidget.colorManager = function() {\n\n return {\n // See these are color pairs for the gradient.\n colorPairs: [\n [\"#e6e6e6\", \"#808080\"],\n [\"#66e8ff\", \"#0082c8\"],\n [\"#ff7fb1\", \"#e6194b\"],\n [\"#a2ffb1\", \"#3cb44b\"],\n [\"#f784ff\", \"#911eb4\"],\n [\"#ffe897\", \"#f58231\"],\n [\"#6666ff\", \"#0000FF\"],\n [\"#ffff7f\", \"#ffe119\"],\n [\"#acffff\", \"#46f0f0\"],\n [\"#ff98ff\", \"#f032e6\"],\n [\"#ffffa2\", \"#d2f53c\"],\n [\"#ffffff\", \"#fabebe\"],\n [\"#66e6e6\", \"#008080\"],\n [\"#ffffff\", \"#e6beff\"],\n [\"#ffd48e\", \"#aa6e28\"],\n [\"#e66666\", \"#800000\"],\n [\"#ffffff\", \"#aaffc3\"],\n [\"#e6e666\", \"#808000\"],\n [\"#ffffff\", \"#ffd8b1\"],\n [\"#66a9ef\", \"#004389\"],\n [\"#ff6672\", \"#a7000c\"],\n [\"#66db72\", \"#00750c\"],\n [\"#b866db\", \"#520075\"],\n [\"#ffa966\", \"#b64300\"],\n [\"#ffff66\", \"#c0a200\"],\n [\"#6dffff\", \"#07b1b1\"],\n [\"#ff66ff\", \"#b100a7\"],\n [\"#f9ff66\", \"#93b600\"],\n [\"#ffe5e5\", \"#bb7f7f\"],\n [\"#66a7a7\", \"#004141\"],\n [\"#ffe5ff\", \"#a77fc0\"],\n [\"#d19566\", \"#6b2f00\"],\n [\"#ffffef\", \"#c0bb89\"],\n [\"#d1ffea\", \"#6bc084\"],\n [\"#a7a766\", \"#414100\"],\n [\"#ffffd8\", \"#c09972\"],\n [\"#a5ffff\", \"#3fc1ff\"],\n [\"#ffbef0\", \"#ff588a\"],\n [\"#e1fff0\", \"#7bf38a\"],\n [\"#ffc3ff\", \"#d05df3\"],\n [\"#ffffd6\", \"#ffc170\"],\n [\"#a5a5ff\", \"#3f3fff\"],\n [\"#ffffbe\", \"#ffff58\"],\n [\"#ebffff\", \"#85ffff\"],\n [\"#ffd7ff\", \"#ff71ff\"],\n [\"#a5ffff\", \"#3fbfbf\"],\n [\"#ffffcd\", \"#e9ad67\"],\n [\"#ffa5a5\", \"#bf3f3f\"],\n [\"#ffffa5\", \"#bfbf3f\"]\n ]\n }\n }\n\n})(jQuery, fabric);","var plateLayOutWidget = plateLayOutWidget || {};\n\n(function($, fabric) {\n\n plateLayOutWidget.createCanvasElements = function() {\n // this class manages creating all the elements within canvas\n return {\n\n scaleFactor: 1,\n\n baseSizes: {\n spacing: 48,\n tile_radius: 22,\n center_radius_complete: 10,\n center_radius_incomplete: 14,\n label_size: 14,\n label_spacing: 24,\n text_size: 13,\n stroke: 0.5,\n gap: 2\n },\n\n _setCanvasArea: function(w, h) {\n this.scaleFactor = Math.min(\n h / (this.dimensions.rows * this.baseSizes.spacing + this.baseSizes.label_spacing),\n w / (this.dimensions.cols * this.baseSizes.spacing + this.baseSizes.label_spacing));\n\n var sizes = {};\n for (var prop in this.baseSizes) {\n sizes[prop] = this.baseSizes[prop] * this.scaleFactor;\n }\n this.sizes = sizes;\n },\n\n _canvas: function() {\n // Those 1,2,3 s and A,B,C s\n this._fixRowAndColumn();\n\n // All those circles in the canvas.\n this._putCircles();\n },\n\n _fixRowAndColumn: function() {\n var cols = this.dimensions.cols;\n var rows = this.dimensions.rows;\n\n var spacing = this.sizes.spacing;\n var d1 = this.sizes.label_spacing / 2;\n var d2 = this.sizes.label_spacing + this.sizes.spacing / 2;\n var fontSize = this.sizes.label_size;\n\n // For column\n var top = d1;\n var left = d2;\n for (var i = 1; i <= cols; i++) {\n var tempFabricText = new fabric.IText(i.toString(), {\n fill: 'black',\n originX: 'center',\n originY: 'center',\n fontSize: fontSize,\n top: top,\n left: left,\n fontFamily: '\"Roboto\", Arial, sans-serif',\n selectable: false,\n fontWeight: \"400\"\n });\n left += spacing;\n\n this.mainFabricCanvas.add(tempFabricText);\n }\n\n // for row\n top = d2;\n left = d1;\n for (var i = 1; i <= rows; i++) {\n var tempFabricText = new fabric.IText(this.rowIndex[i - 1], {\n fill: 'black',\n originX: 'center',\n originY: 'center',\n fontSize: fontSize,\n top: top,\n left: left,\n fontFamily: '\"Roboto\", Arial, sans-serif',\n selectable: false,\n fontWeight: \"400\"\n });\n top += spacing;\n\n this.mainFabricCanvas.add(tempFabricText);\n }\n },\n\n _putCircles: function() {\n var cols = this.dimensions.cols;\n var rows = this.dimensions.rows;\n\n var tileCounter = 0;\n for (var row = 0; row < rows; row++) {\n for (var col = 0; col < cols; col++) {\n var index = this.allTiles.length;\n var tile = this._createTile(row, col);\n tile.index = tileCounter++;\n this.allTiles.push(tile);\n this.mainFabricCanvas.add(tile.background);\n this.mainFabricCanvas.add(tile.highlight);\n this.mainFabricCanvas.add(tile.circle);\n this.mainFabricCanvas.add(tile.circleCenter);\n this.mainFabricCanvas.add(tile.circleText);\n }\n }\n\n this._addLargeRectangleOverlay();\n this._fabricEvents();\n },\n\n _createTile: function(row, col) {\n var tile = {};\n\n tile.visible = false;\n tile.colorIndex = null;\n tile.row = row;\n tile.col = col;\n tile.address = this.rowIndex[row] + (col + 1);\n\n var top = (row + 1) * this.sizes.spacing;\n var left = (col + 1) * this.sizes.spacing;\n\n tile.background = new fabric.Circle({\n top: top,\n left: left,\n radius: this.sizes.tile_radius,\n originX: 'center',\n originY: 'center',\n hasControls: false,\n hasBorders: false,\n lockMovementX: true,\n lockMovementY: true,\n evented: false,\n });\n\n tile.background.setGradient(\"fill\", {\n type: \"radial\",\n x1: this.sizes.tile_radius,\n x2: this.sizes.tile_radius,\n y1: this.sizes.tile_radius + this.sizes.gap,\n y2: this.sizes.tile_radius + this.sizes.gap,\n r1: this.sizes.tile_radius - this.sizes.gap,\n r2: this.sizes.tile_radius,\n colorStops: {\n 0: 'rgba(0,0,0,0.1)',\n 1: 'rgba(0,0,0,0.2)'\n }\n });\n\n tile.highlight = new fabric.Rect({\n originX: 'center',\n originY: 'center',\n top: top,\n left: left,\n width: this.sizes.spacing,\n height: this.sizes.spacing,\n fill: \"rgba(0,0,0,0.4)\",\n evented: false,\n visible: false\n });\n\n tile.circle = new fabric.Circle({\n originX: 'center',\n originY: 'center',\n top: top,\n left: left,\n radius: this.sizes.tile_radius,\n stroke: 'gray',\n strokeWidth: this.sizes.stroke,\n evented: false,\n visible: false\n });\n\n tile.circleCenter = new fabric.Circle({\n originX: 'center',\n originY: 'center',\n top: top,\n left: left,\n radius: this.sizes.center_radius_incomplete,\n fill: \"white\",\n stroke: 'gray',\n strokeWidth: this.sizes.stroke,\n evented: false,\n visible: false\n });\n\n tile.circleText = new fabric.IText(\"\", {\n originX: 'center',\n originY: 'center',\n top: top,\n left: left,\n fill: 'black',\n fontFamily: '\"Roboto\", Arial, sans-serif',\n fontSize: this.sizes.text_size,\n lockScalingX: true,\n lockScalingY: true,\n evented: false,\n visible: false\n });\n\n return tile;\n },\n\n setTileComplete: function(tile, complete) {\n if (complete) {\n tile.circleCenter.radius = this.sizes.center_radius_complete;\n tile.circleText.fill = \"black\";\n tile.circleText.fontWeight = 'normal';\n } else {\n tile.circleCenter.radius = this.sizes.center_radius_incomplete;\n tile.circleText.fill = \"red\";\n tile.circleText.fontWeight = 'bold';\n }\n },\n\n setTileVisible: function(tile, visible) {\n tile.visible = visible;\n tile.circle.visible = tile.visible;\n tile.circleCenter.visible = tile.visible;\n tile.circleText.visible = tile.visible;\n },\n\n setTileColor: function(tile, color) {\n this.setTileVisible(tile, true);\n tile.colorIndex = parseInt(color);\n tile.circleText.text = String(tile.colorIndex);\n\n if (color > 0) {\n color = ((color - 1) % (this.colorPairs.length - 1)) + 1;\n }\n var colorStops = this.colorPairs[color];\n\n tile.circle.setGradient(\"fill\", {\n y2: 2 * this.sizes.tile_radius,\n colorStops: colorStops\n });\n },\n\n _addLargeRectangleOverlay: function() {\n\n this.overLay = new fabric.Rect({\n width: 632,\n height: 482,\n left: 0,\n top: 0,\n opacity: 0.0,\n originX: 'left',\n originY: 'top',\n lockMovementY: true,\n lockMovementX: true,\n selectable: false\n });\n\n this.mainFabricCanvas.add(this.overLay);\n }\n };\n }\n})(jQuery, fabric);\n","var plateLayOutWidget = plateLayOutWidget || {};\n\n(function($, fabric) {\n\n plateLayOutWidget.createField = function() {\n // It creates those fields in the tab , there is 4 types of them.\n return {\n\n _createField: function(field) {\n switch (field.data.type) {\n case \"text\":\n this._createTextField(field);\n break;\n\n case \"numeric\":\n this._createNumericField(field);\n break;\n\n case \"select\":\n this._createSelectField(field);\n break;\n\n case \"multiselect\":\n this._createMultiSelectField(field);\n break;\n\n case \"boolean\":\n this._createBooleanField(field);\n break;\n\n case \"multiplex\":\n this._createMultiplexField(field);\n break;\n }\n },\n\n _createTextField: function(field) {\n var id = field.id;\n var that = this;\n var input = this._createElement(\" \").attr(\"id\", id)\n .addClass(\"plate-setup-tab-input\");\n\n field.root.find(\".plate-setup-tab-field-container\").append(input);\n that.defaultWell[id] = null;\n\n field.parseValue = function(v) {\n if (v) {\n v = String(v);\n } else {\n v = null;\n }\n return v;\n };\n\n field.getValue = function() {\n var v = input.val().trim();\n if (v == \"\") {\n v = null;\n }\n return v;\n };\n\n field.setValue = function(v) {\n input.val(v);\n };\n\n field.getText = function(v) {\n if (v == null) {\n return \"\";\n }\n return v;\n };\n\n field.disabled = function(bool) {\n field.input.prop(\"disabled\", bool);\n };\n\n field.parseText = field.parseValue;\n\n input.on(\"input\", function(e, generated) {\n field.onChange();\n });\n\n field.input = input;\n },\n\n _createOpts: function(config) {\n var opts = {\n allowClear: true,\n placeholder: \"select\",\n minimumResultsForSearch: 10\n };\n var data_specified = false;\n\n if (config.options) {\n opts.data = config.options;\n data_specified = true;\n }\n if (config.ajax) {\n opts.ajax = ajax;\n data_specified = true;\n }\n if (!data_specified) {\n throw \"Must specify data or ajax\";\n }\n return opts;\n },\n\n _createSelectField: function(field) {\n var id = field.id;\n var that = this;\n var input = this._createElement(\" \").attr(\"id\", id)\n .addClass(\"plate-setup-tab-select-field\");\n\n field.root.find(\".plate-setup-tab-field-container\").append(input);\n that.defaultWell[id] = null;\n\n var opts = that._createOpts(field.data);\n var optMap = {};\n opts.data.forEach(function(opt) {\n optMap[opt.id] = opt;\n });\n\n input.select2(opts);\n\n field.parseValue = function(value) {\n var v = value;\n\n if (v == \"\") {\n v = null;\n }\n if (v == null) {\n return null;\n }\n if (v in optMap) {\n return optMap[v].id;\n } else {\n throw \"Invalid value \" + value + \" for select field \" + id;\n }\n };\n\n field.disabled = function(bool) {\n field.input.prop(\"disabled\", bool);\n };\n\n field.getValue = function() {\n return input.val();\n };\n\n field.setValue = function(v) {\n input.val(v);\n input.trigger(\"change.select2\")\n };\n\n field.getText = function(v) {\n if (v == null) {\n return \"\";\n }\n return optMap[v].text;\n };\n\n field.parseText = function(value) {\n var v = value;\n\n if (v == \"\") {\n v = null;\n }\n if (v == null) {\n return null;\n }\n if (v in optMap) {\n return optMap[v].text;\n } else {\n throw \"Invalid text value \" + value + \" for select field \" + id;\n }\n };\n\n input.on(\"change\", function(e, generated) {\n field.onChange();\n });\n\n\n input.on('select2:unselect', function (evt) {\n // Prevent select2 v4.0.6rc1 opening dropdown on unselect\n input.one('select2:opening', function(e) { e.preventDefault(); });\n });\n\n field.input = input;\n },\n\n _createMultiSelectField: function(field) {\n var id = field.id;\n var that = this;\n var input = this._createElement(\" \").attr(\"id\", id)\n .addClass(\"plate-setup-tab-multiselect-field\");\n input.attr(\"multiple\", \"multiple\");\n\n field.root.find(\".plate-setup-tab-field-container\").append(input);\n that.defaultWell[id] = null;\n\n var separator = \",\";\n var opts = that._createOpts(field.data);\n opts.multiple = true;\n var optMap = {};\n opts.data.forEach(function(opt) {\n optMap[opt.id] = opt;\n });\n input.select2(opts);\n\n field.disabled = function(bool) {\n field.input.prop(\"disabled\", bool);\n };\n\n field.parseValue = function(value) {\n var v = value;\n if (v && v.length) {\n v = v.map(function(opt) {\n if (opt in optMap) {\n return optMap[opt].id;\n } else {\n throw \"Invalid value \" + opt + \" for multiselect field \" + id;\n }\n });\n } else {\n v = null;\n }\n return v;\n };\n\n field.getValue = function() {\n var v = input.val();\n if (v.length) {\n return v;\n }\n return null;\n };\n\n field.setValue = function(v) {\n v = v || [];\n input.val(v);\n input.trigger(\"change.select2\");\n };\n\n field.getText = function(v) {\n if (v == null) {\n return \"\";\n }\n if (v.length > 0) {\n return v.map(function(v) {\n return optMap[v].text\n }).join(\"; \");\n }\n return \"\";\n };\n\n field.multiOnChange = function(added, removed) {\n if (added) {\n added = added.id.toString();\n }\n if (removed) {\n removed = removed.id.toString();\n }\n var data = {};\n data[field.id] = {\n multi: true,\n added: added,\n removed: removed\n };\n\n that._addAllData(data);\n };\n\n field.parseText = function(value) {\n var v = value;\n if (v && v.length) {\n v = v.map(function(opt) {\n if (opt in optMap) {\n return optMap[opt].text;\n } else {\n throw \"Invalid text value \" + opt + \" for multiselect field \" + id;\n }\n });\n } else {\n v = null;\n }\n return v;\n };\n\n input.on(\"select2:select\", function (e) {\n field.multiOnChange(e.params.data, null);\n });\n\n input.on(\"select2:unselect\", function (e) {\n field.multiOnChange(null, e.params.data);\n // Prevent select2 v4.0.6rc1 opening dropdown on unselect\n input.one('select2:opening', function(e) { e.preventDefault(); });\n });\n\n field.input = input;\n\n that._createDeleteButton(field);\n },\n\n _createNumericField: function(field) {\n var id = field.id;\n var data = field.data;\n var that = this;\n var input = this._createElement(\" \").addClass(\"plate-setup-tab-input\")\n .attr(\"placeholder\", data.placeholder || \"\").attr(\"id\", id);\n\n field.root.find(\".plate-setup-tab-field-container\").append(input);\n that.defaultWell[id] = null;\n\n // Adding unit\n var units = data.units || [];\n var defaultUnit = data.defaultUnit || null;\n var unitInput = null;\n if (defaultUnit) {\n if (units.length) {\n if (units.indexOf(defaultUnit) < 0) {\n defaultUnit = units[0];\n }\n } else {\n units = [defaultUnit];\n }\n } else {\n if (units.length) {\n defaultUnit = units[0];\n }\n }\n\n if (units.length) {\n field.units = units;\n field.hasUnits = true;\n field.defaultUnit = defaultUnit;\n if (units.length == 1) {\n var unitText = $(\"
\").addClass(\"plate-setup-tab-unit\");\n unitText.text(defaultUnit);\n field.root.find(\".plate-setup-tab-field-container\").append(unitText);\n } else {\n unitInput = this._createElement(\" \").attr(\"id\", id)\n .addClass(\"plate-setup-tab-label-select-field\");\n\n field.root.find(\".plate-setup-tab-field-container\").append(unitInput);\n\n var selected = null;\n var unitData = units.map(function(unit) {\n var o = {\n id: unit,\n text: unit\n };\n if (unit == defaultUnit) {\n selected = unit;\n }\n return o;\n });\n\n var opts = {\n data: unitData,\n allowClear: false,\n minimumResultsForSearch: 10\n };\n\n unitInput.select2(opts);\n unitInput.val(selected);\n }\n }\n\n field.disabled = function(bool) {\n field.input.prop(\"disabled\", bool);\n if (unitInput) {\n unitInput.prop(\"disabled\", bool);\n }\n };\n\n field.setUnitOpts = function(opts) {\n field.units = opts || null;\n field.defaultUnit = null;\n\n var newUnits = [];\n var selected = null;\n if (field.units && field.units.length) {\n field.defaultUnit = field.units[0];\n newUnits = field.units.map(function(curUnit) {\n var cleanUnit = {\n id: curUnit,\n text: curUnit\n };\n if (curUnit == field.defaultUnit) {\n selected = curUnit;\n }\n return cleanUnit;\n });\n }\n\n var newOpts = {\n data: newUnits,\n allowClear: false,\n minimumResultsForSearch: 10\n };\n unitInput.select2(\"destroy\");\n unitInput.val(null);\n unitInput.empty();\n unitInput.select2(newOpts);\n unitInput.val(selected);\n };\n\n field.parseValue = function(value) {\n var v;\n if ($.isPlainObject(value)) {\n if (field.hasUnits) {\n v = field.parseRegularValue(value.value);\n if (v === null) {\n return null;\n }\n return {\n value: v,\n unit: field.parseUnit(value.unit)\n };\n } else {\n throw \"Value must be plain numeric for numeric field \" + id;\n }\n } else {\n if (field.hasUnits) {\n v = field.parseRegularValue(value);\n if (v === null) {\n return null;\n }\n return {\n value: v,\n unit: field.defaultUnit\n };\n } else {\n return field.parseRegularValue(value);\n }\n }\n };\n\n field.getValue = function() {\n var v = field.getRegularValue();\n\n if ((v === null) || isNaN(v)) {\n return null;\n } else if (field.hasUnits) {\n var returnVal = {\n value: v,\n unit: field.getUnit()\n };\n\n if (field.data.hasMultiplexUnit) {\n // include unitTypeId and UnitId to returnVal\n for (var unitTypeKey in field.data.unitMap) {\n var unitTypeUnits = field.data.unitMap[unitTypeKey];\n unitTypeUnits.forEach(function(unit) {\n if (unit.text === returnVal.unit) {\n returnVal['unitTypeId'] = unitTypeKey;\n returnVal['unitId'] = unit.id;\n }\n })\n }\n }\n return returnVal;\n } else {\n return v;\n }\n };\n\n field.setValue = function(value) {\n if (field.hasUnits) {\n if ($.isPlainObject(value)) {\n field.setUnit(value.unit || field.defaultUnit);\n field.setRegularValue(value.value);\n\n } else {\n field.setRegularValue(value);\n field.setUnit(field.defaultUnit)\n }\n } else {\n field.setRegularValue(value);\n }\n };\n\n field.parseRegularValue = function(value) {\n if (value == null) {\n return null;\n }\n var v = String(value).trim();\n if (v === \"\") {\n return null;\n }\n v = Number(value);\n if (isNaN(v)) {\n throw \"Invalid value \" + value + \" for numeric field \" + id;\n }\n return v;\n };\n\n field.getRegularValue = function() {\n var v = input.val().trim();\n if (v == \"\") {\n v = null;\n } else {\n v = Number(v);\n }\n return v;\n };\n\n field.setRegularValue = function(value) {\n input.val(value);\n };\n\n field.parseUnit = function(unit) {\n if (unit == null || unit === \"\") {\n return field.defaultUnit;\n }\n for (var i = 0; i < units.length; i++) {\n if (unit.toLowerCase() == units[i].toLowerCase()) {\n return units[i];\n }\n }\n throw \"Invalid unit \" + unit + \" for field \" + id;\n };\n\n field.getUnit = function() {\n if (unitInput) {\n return unitInput.val();\n } else {\n return field.defaultUnit;\n }\n };\n\n field.setUnit = function(unit) {\n if (unitInput) {\n unit = unit || field.defaultUnit;\n unitInput.val(unit);\n unitInput.trigger(\"change.select2\");\n }\n };\n\n // val now contains unit\n field.getText = function(val) {\n if (typeof (val) === 'object' && val) {\n var v = val.value;\n var u = val.unit;\n if (v == null) {\n return \"\";\n }\n v = v.toString();\n if (!u) {\n u = defaultUnit;\n }\n if (u) {\n v = v + \" \" + u;\n }\n return v;\n } else {\n return field.getRegularText(val);\n }\n };\n\n field.getRegularText = function(v) {\n if (v == null) {\n return \"\";\n }\n v = v.toString();\n return v;\n };\n\n field.parseText = function(v) {\n var textVal = field.parseValue(v);\n if (textVal && typeof (textVal) === \"object\") {\n return textVal.value + textVal.unit;\n } else if (textVal) {\n return textVal\n } else {\n return null;\n }\n };\n\n input.on(\"input\", function() {\n var v = field.getRegularValue();\n if (isNaN(v)) {\n //flag field as invalid\n input.addClass(\"invalid\");\n } else {\n input.removeClass(\"invalid\");\n }\n field.onChange();\n });\n if (unitInput) {\n unitInput.on(\"change\", function() {\n field.onChange();\n });\n }\n\n field.input = input;\n field.unitInput = unitInput;\n },\n\n _createBooleanField: function(field) {\n var id = field.id;\n var that = this;\n var input = this._createElement(\" \").attr(\"id\", id)\n .addClass(\"plate-setup-tab-select-field\");\n that.defaultWell[id] = null;\n\n field.root.find(\".plate-setup-tab-field-container\").append(input);\n var tval = {\n id: \"true\",\n text: \"true\"\n };\n var fval = {\n id: \"false\",\n text: \"false\"\n };\n var opts = {\n data: [tval, fval],\n placeholder: \"select\",\n allowClear: true,\n minimumResultsForSearch: -1\n };\n\n input.select2(opts);\n\n field.disabled = function(bool) {\n field.input.prop(\"disabled\", bool);\n };\n\n field.parseValue = function(value) {\n if (value == null) {\n return null;\n }\n var v = String(value).trim().toLowerCase();\n if (v == \"true\") {\n v = true;\n } else if (v == \"false\") {\n v = false;\n } else if (v == \"\") {\n v = null;\n } else {\n throw \"Invalid value \" + value + \" for boolean field \" + id;\n }\n return v;\n };\n\n field.getValue = function() {\n var v = input.val();\n switch (v) {\n case \"true\":\n return true;\n case \"false\":\n return false;\n default:\n return null;\n }\n };\n\n field.setValue = function(v) {\n if (v == true || v == \"true\") {\n v = \"true\";\n } else if (v == false || v == \"false\") {\n v = \"false\";\n } else {\n v = null;\n }\n input.val(v);\n input.trigger(\"change.select2\");\n };\n\n field.getText = function(v) {\n if (v == null) {\n return \"\";\n }\n return v.toString();\n };\n\n field.parseText = field.parseValue;\n\n input.on(\"change\", function(e) {\n field.onChange();\n });\n\n\n input.on('select2:unselect', function (evt) {\n // Prevent select2 v4.0.6rc1 opening dropdown on unselect\n input.one('select2:opening', function(e) { e.preventDefault(); });\n });\n\n field.input = input;\n },\n\n _createMultiplexField: function(field) {\n var that = this;\n // make correct multiplex data\n this._createMultiSelectField(field);\n // overwrite default well for multiplex field\n that.defaultWell[field.id] = [];\n\n // single select\n var nameContainer1 = that._createElement(\"
\").addClass(\"plate-setup-tab-name-singleSelect\").text(\"Select to edit\");\n var fieldContainer1 = that._createElement(\"
\").addClass(\"plate-setup-tab-field-container-singleSelect\");\n field.root.find(\".plate-setup-tab-field-right-side\").append(nameContainer1, fieldContainer1);\n\n field.singleSelect = this._createElement(\" \").attr(\"id\", field.id + \"SingleSelect\")\n .addClass(\"plate-setup-tab-multiplex-single-select-field\");\n\n field.singleSelect.appendTo(fieldContainer1);\n\n field.singleSelectValue = function() {\n return field.singleSelect.val();\n };\n\n var setSingleSelectOptions = function(v, selected_v) {\n var opts = {\n allowClear: false,\n placeholder: \"select\",\n minimumResultsForSearch: 10,\n data: v || []\n };\n if (!selected_v) {\n if (opts.data.length) {\n selected_v = opts.data[0].id;\n } else {\n selected_v = null;\n }\n }\n if (field.singleSelect.hasClass(\"select2-hidden-accessible\")) {\n field.singleSelect.select2(\"destroy\");\n }\n field.singleSelect.val(null);\n field.singleSelect.empty();\n field.singleSelect.select2(opts);\n field.singleSelect.val(selected_v);\n field.singleSelect.prop(\"disabled\", opts.data.length == 0);\n field.singleSelect.trigger(\"change.select2\");\n field.singleSelect.on(\"change.select2\", singleSelectChange);\n };\n\n var singleSelectChange = function() {\n var v = field.singleSelectValue();\n\n field.updateSubFieldUnitOpts(v);\n\n var curData = field.detailData || [];\n var curSubField = null;\n curData.forEach(function(val) {\n if (val[field.id] === v) {\n curSubField = val;\n }\n });\n\n if (curSubField) {\n // setvalue for subfield\n field.subFieldList.forEach(function(subField) {\n subField.disabled(false);\n subField.setValue(curSubField[subField.id]);\n });\n } else {\n field.subFieldList.forEach(function(subField) {\n subField.disabled(true);\n subField.setValue(null);\n });\n }\n that.readOnlyHandler();\n };\n\n setSingleSelectOptions([]);\n\n field._changeMultiFieldValue = function(added, removed) {\n var newSubFieldValue = {};\n for (var subFieldName in field.data.multiplexFields) {\n var subFieldId = field.data.multiplexFields[subFieldName].id;\n newSubFieldValue[subFieldId] = null;\n }\n\n var val;\n if (added) {\n if (added.value) {\n val = added.value;\n } else {\n newSubFieldValue[field.id] = added.id;\n val = newSubFieldValue;\n }\n added = {\n id: added.id,\n value: val\n };\n }\n\n if (removed) {\n if (removed.value) {\n val = removed.value;\n } else {\n newSubFieldValue[field.id] = removed.id;\n val = newSubFieldValue;\n }\n removed = {\n id: removed.id,\n value: val\n };\n }\n\n var data = {};\n data[field.id] = {\n multi: true,\n added: added,\n removed: removed\n };\n that._addAllData(data);\n };\n\n var multiselectSetValue = field.setValue;\n\n // overwrite multiplex set value\n field.setValue = function(v) {\n // used to keep track of initially loaded multiplex data\n field.detailData = v;\n var multiselectValues = null;\n if (v && v.length) {\n multiselectValues = v.map(function(val) {\n return val[field.id]\n });\n }\n\n multiselectSetValue(multiselectValues);\n var newOptions = field.input.select2('data') || [];\n setSingleSelectOptions(newOptions);\n singleSelectChange();\n };\n\n field.disabled = function(bool) {\n field.input.prop(\"disabled\", bool);\n field.subFieldList.forEach(function(subField) {\n subField.disabled(bool);\n });\n if (bool) {\n nameContainer1.text(\"Select to inspect\");\n } else {\n nameContainer1.text(\"Select to edit\");\n }\n };\n\n field.parseValue = function(value) {\n var v = value;\n if (v && v.length) {\n v = v.map(function(opt) {\n var valMap = {};\n valMap[field.id] = opt[field.id];\n for (var subFieldId in opt) {\n field.subFieldList.forEach(function(subField) {\n if (subField.id === subFieldId) {\n valMap[subField.id] = subField.parseValue(opt[subFieldId]);\n }\n });\n }\n return valMap;\n });\n } else {\n v = null;\n }\n return v;\n };\n\n field.updateSubFieldUnitOpts = function(val) {\n var curOpts;\n field.data.options.forEach(function(opt) {\n if (opt.id === val) {\n curOpts = opt;\n }\n });\n field.subFieldList.forEach(function(subField) {\n if (subField.data.hasMultiplexUnit) {\n if (curOpts && curOpts.hasOwnProperty(\"unitOptions\")) {\n subField.setUnitOpts(curOpts.unitOptions[subField.id]);\n } else {\n subField.setUnitOpts(null);\n }\n }\n })\n };\n\n field.multiOnChange = function(added, removed) {\n field._changeMultiFieldValue(added, removed);\n var v = field.getValue();\n var curData = field.detailData;\n var curIds = [];\n var curOpt = null;\n //reshape data for saveback\n if (curData) {\n curIds = curData.map(function(val) {\n return val[field.id]\n });\n }\n\n var newMultiplexVal = [];\n var selectList = [];\n if (v) {\n v.forEach(function(selectedVal) {\n if (curData) {\n curData.forEach(function(val) {\n if (val[field.id] === selectedVal) {\n newMultiplexVal.push(val)\n }\n });\n }\n // cases when adding new data\n if (curIds.indexOf(selectedVal) < 0) {\n var newVal = {};\n newVal[field.id] = selectedVal;\n\n field.updateSubFieldUnitOpts(selectedVal);\n field.subFieldList.forEach(function(subfield) {\n // special handling for subfield which has multiplexUnit\n if (subfield.hasUnits) {\n if (subfield.data.hasMultiplexUnit) {\n subfield.disabled(false);\n field.data.options.forEach(function(opt) {\n if (opt.id === selectedVal) {\n var val = {\n value: null,\n unit: subfield.units[0]\n };\n newVal[subfield.id] = subfield.parseValue(val);\n }\n });\n } else {\n if (subfield.data.units) {\n if (subfield.data.units.length > 1) {\n subfield.disabled(false);\n }\n }\n var val = {\n value: null,\n unit: subfield.defaultUnit\n };\n newVal[subfield.id] = subfield.parseValue(val);\n }\n } else {\n newVal[subfield.id] = subfield.parseValue(null);\n }\n });\n newMultiplexVal.push(newVal);\n }\n });\n\n // make data for single select options\n v.forEach(function(selectId) {\n field.data.options.forEach(function(opt) {\n if (opt.id === selectId) {\n selectList.push(opt);\n }\n });\n });\n // set the newest selected to be the current obj\n curOpt = selectList[v.length - 1].id;\n }\n\n field.detailData = newMultiplexVal;\n setSingleSelectOptions(selectList, curOpt);\n singleSelectChange();\n };\n\n field.getText = function(v) {\n if (v === null) {\n return \"\";\n }\n // get subfields that is selected from the checkbox\n if (field.id in that.globalSelectedMultiplexSubfield) {\n var checkedSubfields = that.globalSelectedMultiplexSubfield[field.id];\n var returnVal = [];\n for (var valIdx in v) {\n var subV = v[valIdx];\n var subText = [];\n for (var optId in field.data.options) {\n var opt = field.data.options[optId];\n if (opt.id === subV[field.id]) {\n subText.push(opt.text);\n }\n }\n field.subFieldList.forEach(function(subField) {\n if (checkedSubfields.indexOf(subField.id) >= 0) {\n var x = subField.getText(subV[subField.id]);\n subText.push(subField.name + \": \" + x);\n }\n });\n returnVal.push(\"{\" + subText.join(\", \") + \"}\");\n }\n return returnVal.join(\";\");\n }\n };\n\n field.parseText = function(v) {\n if (v === null) {\n return \"\";\n } else {\n var returnVal = [];\n for (var valIdx in v) {\n var subV = v[valIdx];\n var subText = [];\n for (var optId in field.data.options) {\n var opt = field.data.options[optId];\n if (opt.id === subV[field.id]) {\n subText.push(opt.text);\n }\n }\n field.subFieldList.forEach(function(subField) {\n var x = subField.getText(subV[subField.id]);\n if (x) {\n subText.push(x);\n }\n });\n returnVal.push(subText);\n }\n return returnVal;\n }\n };\n\n field.checkMultiplexCompletion = function(valList) {\n var valCount = 0;\n var completionPct = 0;\n var include = false;\n\n function getSubfieldStatus(vals) {\n var req = 0;\n var fill = 0;\n for (var subFieldId in field.subFieldList) {\n var subField = field.subFieldList[subFieldId];\n var curVal = vals[subField.id];\n if (subField.required) {\n include = true;\n req++;\n if (typeof curVal === 'object' && curVal) {\n if (curVal.value) {\n fill++;\n }\n } else if (curVal) {\n fill++;\n }\n }\n }\n return fill / req;\n }\n\n // for cases has value in multiplex field\n if (valList) {\n if (valList.length > 0) {\n for (var idx in valList) {\n valCount++;\n var vals = valList[idx];\n completionPct += getSubfieldStatus(vals);\n }\n } else if (field.required) {\n include = true;\n valCount = 1;\n }\n } else if (field.required) {\n include = true;\n valCount = 1;\n }\n\n return {\n include: include,\n completionPct: completionPct / valCount\n };\n };\n\n // valList contains all of the vals for selected val\n field.applyMultiplexSubFieldColor = function(valList) {\n function updateSubFieldWarningMap(vals) {\n for (var subFieldId in field.subFieldList) {\n var subField = field.subFieldList[subFieldId];\n // loop through each well's multiplexval list\n if (vals === null) {\n if (field.required && subField.required) {\n subFieldWarningMap[subField.id].warningStatus.push(true);\n }\n } else if (typeof (vals) === \"object\") {\n if (vals.length === 0) {\n if (field.required && subField.required) {\n subFieldWarningMap[subField.id].warningStatus.push(true);\n }\n } else {\n for (var multiplexIdx in vals) {\n var curVal = vals[multiplexIdx][subField.id];\n if (subField.required) {\n if (typeof (curVal) === 'object' && curVal) {\n if (!curVal.value) {\n subFieldWarningMap[subField.id].warningStatus.push(true);\n } else {\n subFieldWarningMap[subField.id].warningStatus.push(false);\n }\n } else if (!curVal) {\n subFieldWarningMap[subField.id].warningStatus.push(true);\n } else {\n subFieldWarningMap[subField.id].warningStatus.push(false);\n }\n }\n }\n }\n }\n }\n }\n\n var subFieldWarningMap = {};\n field.subFieldList.forEach(function(subField) {\n if (subField.required) {\n subFieldWarningMap[subField.id] = {\n field: subField,\n warningStatus: []\n };\n }\n });\n\n valList.forEach(function(multiplexVals) {\n updateSubFieldWarningMap(multiplexVals);\n });\n // turn off main field when all subfield are filled\n\n var requiredSubField = [];\n var mainFieldStatus = [];\n for (var subFieldId in subFieldWarningMap) {\n var subField = subFieldWarningMap[subFieldId].field;\n if (subFieldWarningMap[subFieldId].warningStatus.indexOf(true) >= 0) {\n var text = subField.name + \" is a required subfield for \" + field.name + \", please make sure all \" + field.name + \" have \" + subField.name;\n if (field.required) {\n that.fieldWarningMsg(subField, text, true);\n mainFieldStatus.push(true);\n } else {\n that.fieldWarningMsg(subField, text, true);\n mainFieldStatus.push(true);\n }\n } else {\n that.fieldWarningMsg(subField, \"none\", false);\n mainFieldStatus.push(false);\n }\n }\n var mainFieldWarning = false;\n if (mainFieldStatus.indexOf(true) < 0) {\n mainFieldWarning = false;\n } else {\n mainFieldWarning = true;\n }\n var warningText;\n if (field.required) {\n warningText = field.name + \" is a required field, please also fix missing required subfield(s) below\";\n } else {\n warningText = field.name + \" is not a required field, please fix missing required subfield(s) below or remove selected \" + field.name;\n }\n that.fieldWarningMsg(field, warningText, mainFieldWarning);\n };\n\n field.parseMainFieldVal = function(val) {\n var optMap = field.data.options;\n for (var idx = 0; idx < optMap.length; idx++) {\n var curOpt = optMap[idx];\n if (curOpt.id === val) {\n return curOpt.text\n }\n }\n };\n },\n\n _deleteDialog: function(field) {\n var that = this;\n\n var valMap = field.allSelectedMultipleVal;\n var valToRemove;\n if (valMap) {\n valToRemove = Object.keys(valMap);\n } else {\n valToRemove = [];\n }\n\n\n var dialogDiv = $(\"
\").addClass(\"delete-dialog modal\");\n $('body').append(dialogDiv);\n\n function killDialog() {\n dialogDiv.hide();\n dialogDiv.remove();\n }\n\n var dialogContent = $(\"
\").addClass(\"modal-content\").appendTo(dialogDiv);\n var tableArea = $(\"
\").appendTo(dialogContent);\n var buttonRow = $(\"
\").addClass(\"dialog-buttons\").css(\"justify-content\", \"flex-end\").appendTo(dialogContent);\n\n if (valToRemove.length > 0) {\n // apply CSS property for table\n $(\"
\").text(field.name + \" in selected wells: choose items to delete and click the delete button below\").appendTo(tableArea);\n\n var table = that._deleteDialogTable(field, valMap);\n table.appendTo(tableArea);\n table.addClass(\"plate-popout-table\");\n table.find('td').addClass(\"plate-popout-td\");\n table.find('th').addClass(\"plate-popout-th\");\n table.find('tr').addClass(\"plate-popout-tr\");\n if (!that.readOnly) {\n var deleteCheckedButton = $(\"Delete Checked Items \");\n buttonRow.append(deleteCheckedButton);\n deleteCheckedButton.click(function() {\n table.find(\"input:checked\").each(function() {\n var val = this.value;\n field.multiOnChange(null, {id: val});\n });\n // refresh selected fields after updating the multiplex field value\n that.decideSelectedFields();\n killDialog();\n });\n }\n\n } else {\n $(\"
\").text(\"No \" + field.name + \" in the selected wells\").appendTo(tableArea);\n }\n\n var cancelButton = $(\"Cancel \");\n buttonRow.append(cancelButton);\n cancelButton.click(killDialog);\n\n dialogDiv.show();\n\n window.onclick = function(event) {\n if (event.target == dialogDiv[0]) {\n killDialog();\n }\n }\n },\n\n _deleteDialogTable: function(field, valMap) {\n var that = this;\n var colName = [field.name, \"Counts\"]; //Added because it was missing... no idea what the original should have been\n if (!that.readOnly) {\n colName.push(\"Delete\");\n }\n var table = $('');\n var thead = $(' ').appendTo(table);\n var tr = $(' ').appendTo(thead);\n\n tr.append(colName.map(function(text) {\n return $(' ').text(text);\n }));\n\n var tbody = $(\" \").appendTo(table);\n\n field.data.options.forEach(function(opt) {\n if (opt.id in valMap) {\n var tr = $(' ').appendTo(tbody);\n var checkbox = $(\" \").prop(\"value\", opt.id);\n $(\" \").text(opt.text).appendTo(tr);\n $(\" \").text(valMap[opt.id]).appendTo(tr);\n if (!that.readOnly) {\n $(\" \").append(checkbox).appendTo(tr);\n }\n }\n });\n\n return table;\n },\n\n _createDeleteButton: function(field) {\n var that = this;\n var deleteButton = $(\" \").addClass(\"plate-setup-remove-all-button\");\n deleteButton.id = field.id + \"Delete\";\n deleteButton.text(\"Manage \" + field.name + \"...\");\n var buttonContainer = that._createElement(\"
\").addClass(\"plate-setup-remove-all-button-container\");\n buttonContainer.append(deleteButton);\n\n field.deleteButton = deleteButton;\n field.root.find(\".plate-setup-tab-field-right-side\").append(buttonContainer);\n\n deleteButton.click(function() {\n that._deleteDialog(field);\n });\n }\n\n };\n }\n})(jQuery, fabric);","var plateLayOutWidget = plateLayOutWidget || {};\n\n(function($, fabric) {\n\n plateLayOutWidget.engine = function(THIS) {\n // Methods which look after data changes and stack up accordingly\n // Remember THIS points to plateLayOutWidget and 'this' points to engine\n // Use THIS to refer parent this.\n return {\n engine: {\n\n derivative: {},\n colorMap: new Map(),\n stackUpWithColor: {},\n stackPointer: 2,\n\n wellEmpty: function(well) {\n for (var prop in well) {\n var curVal = well[prop];\n if (curVal !== null && curVal !== undefined) {\n if (Array.isArray(curVal)) {\n if (curVal.length > 0) {\n return false;\n }\n } else {\n return false;\n }\n }\n }\n return true;\n },\n\n searchAndStack: function() {\n // This method search and stack the change we made.\n this.stackUpWithColor = {};\n this.stackPointer = 1;\n var derivativeJson = {};\n for (var idx in this.derivative) {\n var data = this.derivative[idx];\n var wellData = {};\n for (var i = 0; i < THIS.globalSelectedAttributes.length; i++) {\n var attr = THIS.globalSelectedAttributes[i];\n\n if (attr in THIS.globalSelectedMultiplexSubfield) {\n var selectedSubFields = THIS.globalSelectedMultiplexSubfield[attr];\n var newMultiplexVal = [];\n for (var multiplexIdx in data[attr]) {\n var curMultiplexVals = data[attr][multiplexIdx];\n var newVal = {};\n newVal[attr] = curMultiplexVals[attr];\n selectedSubFields.forEach(function(subFieldId) {\n newVal[subFieldId] = curMultiplexVals[subFieldId];\n });\n newMultiplexVal.push(newVal);\n }\n wellData[attr] = newMultiplexVal;\n } else {\n if (data[attr] != null) {\n wellData[attr] = data[attr];\n }\n }\n }\n if ($.isEmptyObject(wellData)) {\n derivativeJson[idx] = null;\n } else {\n derivativeJson[idx] = JSON.stringify(wellData);\n }\n }\n\n while (!$.isEmptyObject(derivativeJson)) {\n var keys = Object.keys(derivativeJson).map(function(k) {\n return parseFloat(k, 10);\n });\n keys.sort(function(a, b) {\n return a - b;\n });\n\n var refDerivativeIndex = keys[0];\n var referenceDerivative = derivativeJson[refDerivativeIndex];\n var arr = [];\n\n if (!referenceDerivative) {\n // if no checked box has value, push it to first spot\n if (this.stackUpWithColor[0]) {\n this.stackUpWithColor[0].push(refDerivativeIndex);\n } else {\n this.stackUpWithColor[0] = [refDerivativeIndex];\n }\n\n delete derivativeJson[refDerivativeIndex];\n } else {\n // if checked boxes have values\n for (var i = 0; i < keys.length; i++) {\n var idx = keys[i];\n if (referenceDerivative == derivativeJson[idx]) {\n arr.push(idx);\n this.stackUpWithColor[this.stackPointer] = arr;\n delete derivativeJson[idx];\n }\n }\n if (arr.length > 0)\n this.stackPointer++;\n }\n }\n },\n\n applyColors: function() {\n\n var wholeNoTiles = 0;\n var wholePercentage = 0;\n\n THIS.addBottomTableHeadings();\n\n for (var i = 0; i < THIS.allTiles.length; i++) {\n var tile = THIS.allTiles[i];\n THIS.setTileVisible(tile, false);\n }\n\n for (var color = 0; color < this.stackPointer; color++) {\n var arr = this.stackUpWithColor[color];\n if (arr) {\n THIS.addBottomTableRow(color, arr);\n\n for (var tileIndex in arr) {\n wholeNoTiles++;\n var index = this.stackUpWithColor[color][tileIndex];\n var tile = THIS.allTiles[index];\n var well = this.derivative[index];\n this.colorMap.set(index, color);\n THIS.setTileColor(tile, color);\n // Checks if all the required fields are filled\n var completion = this.checkCompletion(well, tile);\n THIS.setTileComplete(tile, completion == 1);\n wholePercentage = wholePercentage + completion;\n }\n }\n }\n\n wholePercentage = Math.floor(100 * wholePercentage / wholeNoTiles);\n\n if (isNaN(wholePercentage)) {\n THIS.overLayTextContainer.text(\"Completion Percentage: 0%\");\n } else {\n THIS.overLayTextContainer.text(\"Completion Percentage: \" + wholePercentage + \"%\");\n }\n },\n\n checkCompletion: function(wellData, tile) {\n var req = 0;\n var fill = 0;\n for (var i = 0; i < THIS.fieldList.length; i++) {\n var field = THIS.fieldList[i];\n if (field.checkMultiplexCompletion) {\n // also apply color\n var multiplexStatus = field.checkMultiplexCompletion(wellData[field.id]);\n if (multiplexStatus.include) {\n fill += multiplexStatus.completionPct;\n req++;\n }\n } else {\n if (field.required) {\n req++;\n if (wellData[field.id] !== null) {\n fill++;\n }\n }\n }\n }\n if (req === fill) {\n return 1;\n }\n return fill / req;\n },\n }\n }\n }\n})(jQuery, fabric);","var plateLayOutWidget = plateLayOutWidget || {};\n\n(function($, fabric) {\n\n plateLayOutWidget.fabricEvents = function() {\n // This object contains Menu items and how it works;\n return {\n colorToIndex: {},\n startCoords: {\n x: 0,\n y: 0\n },\n focalWell: {\n row: 0,\n col: 0\n },\n selectedAreas: [],\n\n _clickCoords: function(evt) {\n //Get XY Coords for a given event. \n var rect = evt.e.target.getBoundingClientRect();\n return {\n x: evt.e.clientX - rect.left,\n y: evt.e.clientY - rect.top\n };\n },\n\n _fabricEvents: function() {\n // Set up event handling. \n var that = this;\n\n $(that.target).on(\"getPlates\", function(evt, data) {\n // This method should be compatable to redo/undo.\n that.getPlates(JSON.parse(data));\n });\n\n that.mainFabricCanvas.on(\"mouse:down\", function(evt) {\n // Start selecting new area\n that.selecting = true;\n var coords = that._clickCoords(evt);\n\n var areas = that.selectedAreas.slice();\n var focalWell = that.focalWell;\n var startCoords = that._wellToCoords(focalWell, true);\n var rect = that._coordsToRect(startCoords, coords);\n\n if (evt.e.ctrlKey) {\n //adding new area\n startCoords = coords;\n rect = that._coordsToRect(startCoords, coords);\n focalWell = that._coordsToWell(startCoords);\n if (evt.e.shiftKey) {\n //replacing existing areas\n areas = [that._rectToArea(rect)];\n } else {\n areas.push(that._rectToArea(rect));\n }\n } else {\n if (evt.e.shiftKey) {\n //Altering last area\n areas[areas.length - 1] = that._rectToArea(rect);\n } else {\n //Creating new area\n startCoords = coords;\n rect = that._coordsToRect(startCoords, coords);\n focalWell = that._coordsToWell(startCoords);\n areas = [that._rectToArea(rect)];\n }\n }\n\n that.startCoords = startCoords;\n that.setSelection(areas, focalWell);\n that.mainFabricCanvas.renderAll();\n });\n\n that.mainFabricCanvas.on(\"mouse:move\", function(evt) {\n if (that.selecting) {\n // continue selecting new area\n var areas = that.selectedAreas.slice();\n var endCoords = that._clickCoords(evt);\n var rect = that._coordsToRect(that.startCoords, endCoords);\n var area = that._rectToArea(rect);\n if (area) {\n areas[areas.length - 1] = area;\n }\n\n that.setSelection(areas, that.focalWell);\n that.mainFabricCanvas.renderAll();\n }\n\n });\n\n that.mainFabricCanvas.on(\"mouse:up\", function(evt) {\n // finish selecting new area\n that.selecting = false;\n var areas = that.selectedAreas.slice();\n var endCoords = that._clickCoords(evt);\n var rect = that._coordsToRect(that.startCoords, endCoords);\n var area = that._rectToArea(rect);\n if (area) {\n areas[areas.length - 1] = area;\n }\n\n that.setSelection(areas, that.focalWell);\n that.decideSelectedFields();\n that.mainFabricCanvas.renderAll();\n that._trigger(\"selectedWells\", null, {selectedAddress: that.getSelectedAddress()});\n if (that.options.scrollToGroup === undefined || that.options.scrollToGroup) {\n that.selectObjectInBottomTab();\n }\n });\n },\n\n setSelection: function(areas, focalWell) {\n this.selectedAreas = areas;\n this.focalWell = focalWell;\n this.allSelectedObjects = this._areasToTiles(areas);\n this._setSelectedTiles();\n this._setFocalWellRect(this.focalWell);\n document.activeElement.blur();\n },\n\n _setFocalWellRect: function(well) {\n var flag;\n // check if not allow to add or delete existing wells\n if (this.disableAddDeleteWell) {\n var address = this.locToAddress({\n r: well.row,\n c: well.col\n });\n if (this.addressAllowToEdit.indexOf(address) < 0) {\n flag = false;\n this.setFieldsDisabled(true);\n } else {\n flag = true;\n this.setFieldsDisabled(false);\n }\n } else if (well) {\n flag = true;\n }\n\n if (flag) {\n var rect = this._areaToRect(this._wellToArea(well));\n var strokeWidth = 2;\n if (this.focalWellRect) {\n //update focalWellRect\n this.focalWellRect.top = rect.top;\n this.focalWellRect.left = rect.left;\n this.focalWellRect.width = rect.width - strokeWidth;\n this.focalWellRect.height = rect.height - strokeWidth;\n } else {\n //create focalWellRect\n this.focalWellRect = new fabric.Rect({\n width: rect.width - strokeWidth,\n height: rect.height - strokeWidth,\n left: rect.left,\n top: rect.top,\n fill: null,\n strokeWidth: strokeWidth,\n stroke: \"black\",\n selectable: false\n });\n this.mainFabricCanvas.add(this.focalWellRect);\n }\n } else {\n //clear focalWellRect\n this.mainFabricCanvas.remove(this.focalWellRect);\n this.focalWellRect = null;\n }\n },\n\n _setSelectedTiles: function() {\n // Update selected tile display only\n var selectedTiles = this.allSelectedObjects;\n this.allTiles.forEach(function(tile) {\n var selected = selectedTiles.indexOf(tile) >= 0;\n tile.highlight.visible = selected;\n })\n },\n\n _getSelectedWells: function() {\n var that = this;\n return this.allSelectedObjects.map(function(tile) {\n var well = that.engine.derivative[tile.index];\n if (!well) {\n well = that.defaultWell;\n }\n return well;\n });\n },\n\n _getCommonFields: function(wells) {\n if (wells.length) {\n var referenceWell = wells[0];\n var referenceFields = $.extend(true, {}, referenceWell);\n for (var i = 1; i < wells.length; i++) {\n var fields = wells[i];\n for (var field in referenceFields) {\n if (Array.isArray(referenceFields[field])) {\n var refArr = referenceFields[field];\n var agrArr = [];\n for (var j = 0; j < refArr.length; j++) {\n var v = refArr[j];\n if (v && typeof (v) === \"object\") {\n if (this.containsObject(v, fields[field])) {\n agrArr.push(v);\n }\n } else {\n if ($.inArray(v, fields[field]) >= 0) {\n agrArr.push(v);\n }\n }\n }\n referenceFields[field] = agrArr;\n } else {\n if (fields[field] && typeof (fields[field]) === \"object\" && referenceFields[field] && typeof (referenceFields[field]) === \"object\") {\n if ((fields[field].value !== referenceFields[field].value) || (fields[field].unit !== referenceFields[field].unit)) {\n delete referenceFields[field];\n }\n } else if (referenceFields[field] != fields[field]) {\n delete referenceFields[field];\n }\n }\n }\n }\n return referenceFields\n } else {\n return {};\n }\n },\n\n containsObject: function(obj, list) {\n var equality = [];\n if (list) {\n list.forEach(function(val) {\n //evaluate val and obj\n var evaluate = [];\n Object.keys(val).forEach(function(listKey) {\n if (Object.keys(obj).indexOf(listKey) >= 0) {\n var curVal = val[listKey];\n if (typeof (curVal) === 'object' && curVal) {\n if (obj[listKey]) {\n evaluate.push((curVal.unit === obj[listKey].unit) && (curVal.value === obj[listKey].value));\n } else {\n // when obj[listKey] is null but curVal is not\n evaluate.push(false);\n }\n } else {\n evaluate.push(curVal === obj[listKey]);\n }\n }\n });\n equality.push(evaluate.indexOf(false) < 0);\n });\n return equality.indexOf(true) >= 0;\n } else {\n return false;\n }\n },\n\n _getCommonWell: function(wells) {\n if (wells.length) {\n var referenceWell = wells[0];\n var referenceFields = $.extend(true, {}, referenceWell);\n for (var i = 1; i < wells.length; i++) {\n var well = wells[i];\n var fields = well;\n for (var field in referenceFields) {\n if (Array.isArray(referenceFields[field])) {\n var refArr = referenceFields[field];\n var agrArr = [];\n for (var j = 0; j < refArr.length; j++) {\n var v = refArr[j];\n // for multiplex field\n if (typeof (refArr[j]) === \"object\") {\n if (this.containsObject(v, fields[field])) {\n agrArr.push(v);\n }\n } else {\n if ($.inArray(v, fields[field]) >= 0) {\n agrArr.push(v);\n }\n }\n }\n referenceFields[field] = agrArr;\n } else {\n if (fields[field] && typeof (fields[field]) === \"object\" && referenceFields[field] && typeof (referenceFields[field]) === \"object\") {\n if ((fields[field].value !== referenceFields[field].value) || (fields[field].unit !== referenceFields[field].unit)) {\n referenceFields[field] = null;\n }\n } else if (referenceFields[field] != fields[field]) {\n referenceFields[field] = null;\n }\n\n }\n }\n }\n return referenceFields;\n } else {\n return this.defaultWell;\n }\n },\n\n _getAllMultipleVal: function(wells) {\n var multipleFieldList = this.multipleFieldList;\n\n multipleFieldList.forEach(function(multiplexField) {\n if (wells.length) {\n var curMultipleVal = {};\n wells.forEach(function(wellData) {\n var id = multiplexField.id;\n if (wellData[id]) {\n if (wellData[id].length > 0) {\n wellData[id].forEach(function(multipleVal) {\n if (typeof (multipleVal) === 'object') {\n if (multipleVal[id] in curMultipleVal) {\n curMultipleVal[multipleVal[id]]++;\n } else {\n curMultipleVal[multipleVal[id]] = 1;\n }\n } else {\n if (multipleVal in curMultipleVal) {\n curMultipleVal[multipleVal]++;\n\n } else {\n curMultipleVal[multipleVal] = 1;\n }\n }\n })\n }\n }\n });\n multiplexField.allSelectedMultipleVal = curMultipleVal;\n } else {\n multiplexField.allSelectedMultipleVal = null\n }\n });\n },\n\n decideSelectedFields: function() {\n var wells = this._getSelectedWells();\n this._getAllMultipleVal(wells);\n this.applyFieldWarning(wells);\n var well = this._getCommonWell(wells);\n this._addDataToTabFields(well);\n },\n\n // get well value differences for each well in wellsHash\n getDifferentWellsVals: function(wellsHash) {\n var wells = [];\n for (var wellId in wellsHash) {\n wells.push(wellsHash[wellId]);\n }\n var differentWellsVals = {};\n if (wells.length > 1) {\n var commonWell = this._getCommonWell(wells);\n var allFieldVal = {};\n for (var fieldIdx in wellsHash[0]) {\n allFieldVal[fieldIdx] = [];\n }\n for (var wellIdx in wells) {\n var diffWellVal = {};\n var curWellData = wells[wellIdx];\n for (var fieldId in curWellData) {\n var commonVal = commonWell[fieldId];\n var curVal = curWellData[fieldId];\n var newVal = null;\n if (Array.isArray(curVal)) {\n // get uncommonVal\n newVal = [];\n for (var idx = 0; idx < curVal.length; idx++) {\n var curMultiVal = curVal[idx];\n // multiplex field\n if (curMultiVal && typeof (curMultiVal === \"object\")) {\n if (!this.containsObject(curMultiVal, commonVal)) {\n newVal.push(curMultiVal);\n if (!this.containsObject(curMultiVal, allFieldVal[fieldId])) {\n allFieldVal[fieldId].push(curMultiVal);\n }\n }\n } else {\n if (commonVal.indexOf(curMultiVal) >= 0) {\n newVal.push(curMultiVal);\n if (!allFieldVal[fieldId].indexOf(curMultiVal) >= 0) {\n allFieldVal[fieldId].push(curMultiVal);\n }\n }\n }\n }\n } else if (curVal && typeof (curVal) === \"object\") {\n if (commonVal && typeof (commonVal) === \"object\") {\n if (!((curVal.value === commonVal.value) || (curVal.unit === commonVal.unit))) {\n newVal = curVal;\n if (!this.containsObject(curVal, allFieldVal[fieldId])) {\n allFieldVal[fieldId].push(curVal);\n }\n }\n } else {\n newVal = curVal;\n if (!this.containsObject(curVal, allFieldVal[fieldId])) {\n allFieldVal[fieldId].push(curVal);\n }\n }\n } else if (curVal !== commonVal) {\n newVal = curVal;\n if (!allFieldVal[fieldId].indexOf(curVal) >= 0) {\n allFieldVal[fieldId].push(curVal);\n }\n }\n diffWellVal[fieldId] = newVal;\n }\n\n\n differentWellsVals[wellIdx] = diffWellVal;\n }\n\n // clean up step for fields that are empty\n for (var fieldId in allFieldVal) {\n if (allFieldVal[fieldId].length === 0) {\n for (var wellIdx in differentWellsVals) {\n delete differentWellsVals[wellIdx][fieldId];\n }\n }\n }\n\n return differentWellsVals;\n } else if (wellsHash[0]) {\n var well = {};\n for (var fieldId in wellsHash[0]) {\n var curVal = wellsHash[0][fieldId];\n if (Array.isArray(curVal)) {\n if (curVal.length > 0) {\n well[fieldId] = curVal\n }\n } else if (curVal) {\n well[fieldId] = curVal;\n }\n }\n return {\n 0: well\n };\n }\n },\n\n // get all wells that has data\n getWellSetAddressWithData: function() {\n var address = [];\n var derivative = this.engine.derivative;\n for (var id in derivative) {\n address.push(this.indexToAddress(id));\n }\n return address;\n }\n\n };\n }\n})(jQuery, fabric);","var plateLayOutWidget = plateLayOutWidget || {};\n\nplateLayOutWidget.assets = function() {\n return {\n _assets: {\n doImg: '✓',\n dontImg: '',\n warningImg: '⚠'\n }\n };\n};\n","var plateLayOutWidget = plateLayOutWidget || {};\n\n(function($, fabric) {\n\n plateLayOutWidget.interface = function() {\n // interface holds all the methods to put the interface in place\n return {\n\n _createInterface: function() {\n\n var divIdentifier = '
';\n this.container = this._createElement(divIdentifier).addClass(\"plate-setup-wrapper\");\n this.topSection = this._createElement(divIdentifier).addClass(\"plate-setup-top-section\");\n\n this.topLeft = this._createElement(divIdentifier).addClass(\"plate-setup-top-left\");\n this.topRight = this._createElement(divIdentifier).addClass(\"plate-setup-top-right\");\n\n this.overLayContainer = this._createElement(divIdentifier).addClass(\"plate-setup-overlay-container\");\n this.canvasContainer = this._createElement(divIdentifier).addClass(\"plate-setup-canvas-container\");\n\n this._createOverLay();\n $(this.topLeft).append(this.overLayContainer);\n\n this._createCanvas();\n $(this.topLeft).append(this.canvasContainer);\n\n\n $(this.topSection).append(this.topLeft);\n $(this.topSection).append(this.topRight);\n\n $(this.container).append(this.topSection);\n $(this.element).append(this.container);\n\n this._initiateFabricCanvas();\n\n this._createTabAtRight();\n this._createTabs();\n\n this._placePresetTabs();\n // Bottom of the screen\n this._bottomScreen();\n // Canvas\n this._canvas();\n\n this.bottomForFirstTime();\n\n var that = this;\n this._setShortcuts();\n $(document.body).keyup(function(e) {\n that._handleShortcuts(e);\n });\n\n this._configureUndoRedoArray();\n },\n\n _createElement: function(element) {\n return $(element);\n },\n\n _setShortcuts: function() {\n var that = this;\n window.addEventListener(\"cut\", function(e) {\n if (document.activeElement == document.body) {\n that.copyCriteria();\n that.clearCriteria();\n e.preventDefault();\n }\n });\n window.addEventListener(\"copy\", function(e) {\n if (document.activeElement == document.body) {\n that.copyCriteria();\n e.preventDefault();\n }\n });\n window.addEventListener(\"paste\", function(e) {\n if (document.activeElement == document.body) {\n that.pasteCriteria();\n e.preventDefault();\n }\n });\n },\n\n _handleShortcuts: function(e) {\n if (document.activeElement === document.body) {\n if (e.keyCode == 46) {\n this.clearCriteria();\n e.preventDefault();\n } else if (e.ctrlKey || e.metaKey) {\n if (e.keyCode == 90) {\n if (e.shiftKey) {\n this.redo();\n } else {\n this.undo();\n }\n e.preventDefault();\n } else if (e.keyCode == 89) {\n this.redo();\n e.preventDefault();\n }\n }\n }\n },\n };\n }\n})(jQuery, fabric);","var plateLayOutWidget = plateLayOutWidget || {};\n\n(function($, fabric) {\n\n plateLayOutWidget.loadPlate = function(THIS) {\n // Methods which look after data changes and stack up accordingly\n // Remember THIS points to plateLayOutWidget and 'this' points to engine\n return {\n\n getPlates: function(data) {\n //sanitize input\n var derivative = {};\n for (var index in data.derivative) {\n var well = data.derivative[index];\n derivative[index] = this.sanitizeWell(well);\n }\n\n var checkboxes = data.checkboxes || [];\n var selection = this.sanitizeAreas(data.selectedAreas, data.focalWell);\n\n var sanitized = {\n \"derivative\": derivative,\n \"checkboxes\": checkboxes,\n \"selectedAreas\": selection.selectedAreas,\n \"focalWell\": selection.focalWell\n };\n\n this.setData(sanitized);\n },\n\n sanitizeAreas: function(selectedAreas, focalWell) {\n var that = this;\n var rows = this.dimensions.rows;\n var cols = this.dimensions.cols;\n\n if (!selectedAreas) {\n selectedAreas = [];\n }\n if (selectedAreas.length) {\n selectedAreas = selectedAreas.map(function(area) {\n return {\n minCol: that._coordIndex(Math.min(area.minCol, area.maxCol), cols),\n minRow: that._coordIndex(Math.min(area.minRow, area.maxRow), rows),\n maxCol: that._coordIndex(Math.max(area.minCol, area.maxCol), cols),\n maxRow: that._coordIndex(Math.max(area.minRow, area.maxRow), rows)\n };\n });\n var area = selectedAreas[selectedAreas.length - 1];\n if (focalWell && !this._wellInArea(focalWell, area)) {\n focalWell = null;\n }\n if (!focalWell) {\n focalWell = {\n row: area.minRow,\n col: area.minCol\n };\n }\n } else {\n if (!focalWell) {\n focalWell = {\n row: 0,\n col: 0\n };\n }\n selectedAreas = [this._wellToArea(focalWell)];\n }\n return {\n selectedAreas: selectedAreas,\n focalWell: focalWell\n };\n },\n\n sanitizeWell: function(well) {\n var newWell = {};\n for (var i = 0; i < this.fieldList.length; i++) {\n var field = this.fieldList[i];\n newWell[field.id] = field.parseValue(well[field.id]);\n }\n return newWell;\n },\n\n setData: function(data) {\n this.engine.derivative = $.extend(true, {}, data.derivative);\n this.setCheckboxes(data.checkboxes);\n this.setSelection(data.selectedAreas, data.focalWell);\n this._colorMixer();\n this.decideSelectedFields();\n this.mainFabricCanvas.renderAll();\n },\n\n }\n }\n})(jQuery, fabric);","var GET_PLATES = 'getPlates';\nvar IS_READ_ONLY = 'isReadOnly';\nvar IS_DISABLE_ADD_DELETE_WELL = 'isDisableAddDeleteWell';\nvar GET_SELECTED_OBJECT = 'getSelectedObject';\nvar SETSELECTEDWELL = 'setSelectedWell';","var plateLayOutWidget = plateLayOutWidget || {};\n\n(function($, fabric) {\n\n plateLayOutWidget.overlay = function() {\n // overlay holds all the methods to put the part just above the canvas which contains all those\n // 'completion percentage' annd 'copy Criteria' button etc ...\n return {\n\n _createOverLay: function() {\n\n var that = this;\n this.overLayTextContainer = this._createElement(\"
\").addClass(\"plate-setup-overlay-text-container\");\n this.overLayTextContainer.text(\"Completion Percentage:\");\n this.overLayContainer.append(this.overLayTextContainer);\n this.overLayButtonContainer = this._createElement(\"
\").addClass(\"plate-setup-overlay-button-container\");\n this.overLayContainer.append(this.overLayButtonContainer);\n\n this.clearCriteriaButton = this._createElement(\" \").addClass(\"plate-setup-button\");\n this.clearCriteriaButton.text(\"Clear\");\n this.overLayButtonContainer.append(this.clearCriteriaButton);\n\n this.clearCriteriaButton.click(function(evt) {\n that.clearCriteria();\n });\n\n this.copyCriteriaButton = this._createElement(\" \").addClass(\"plate-setup-button\");\n this.copyCriteriaButton.text(\"Copy\");\n this.overLayButtonContainer.append(this.copyCriteriaButton);\n\n this.copyCriteriaButton.click(function(evt) {\n that.copyCriteria();\n });\n\n this.pasteCriteriaButton = this._createElement(\" \").addClass(\"plate-setup-button\");\n this.pasteCriteriaButton.text(\"Paste\");\n this.overLayButtonContainer.append(this.pasteCriteriaButton);\n\n this.pasteCriteriaButton.click(function(evt) {\n that.pasteCriteria();\n });\n\n this.undoButton = this._createElement(\" \").addClass(\"plate-setup-button\");\n this.undoButton.text(\"Undo\");\n this.overLayButtonContainer.append(this.undoButton);\n\n this.undoButton.click(function(evt) {\n that.undo();\n });\n\n this.redoButton = this._createElement(\" \").addClass(\"plate-setup-button\");\n this.redoButton.text(\"Redo\");\n this.overLayButtonContainer.append(this.redoButton);\n\n this.redoButton.click(function(evt) {\n that.redo();\n });\n\n },\n\n clearCriteria: function() {\n if (this.allSelectedObjects) {\n var noOfSelectedObjects = this.allSelectedObjects.length;\n var hasWellUpdate = false;\n for (var objectIndex = 0; objectIndex < noOfSelectedObjects; objectIndex++) {\n var tile = this.allSelectedObjects[objectIndex];\n if (tile.index in this.engine.derivative) {\n // handling for clearing well when not allowed to add or delete wells\n if (this.emptyWellWithDefaultVal && this.disableAddDeleteWell) {\n var well = JSON.parse(JSON.stringify(this.defaultWell));\n var defaultValue = this.emptyWellWithDefaultVal;\n for (var key in defaultValue) {\n if (key in well) {\n well[key] = defaultValue[key];\n this._applyFieldData(key, defaultValue[key]);\n } else {\n console.log(\"Well does not contain key: \" + key + \", please contact support\");\n }\n }\n this.engine.derivative[tile.index] = well;\n } else {\n delete this.engine.derivative[tile.index];\n }\n hasWellUpdate = true;\n }\n }\n if (hasWellUpdate) {\n this.derivativeChange();\n }\n\n this._colorMixer();\n this.decideSelectedFields();\n } else {\n alert(\"Please select any well\");\n }\n },\n\n copyCriteria: function() {\n if (this.allSelectedObjects) {\n var wells = this._getSelectedWells();\n this.commonWell = this._getCommonFields(wells);\n } else {\n alert(\"Please select any well.\");\n }\n },\n\n pasteCriteria: function() {\n if (this.commonWell) {\n this._addAllData(this.commonWell);\n this.decideSelectedFields();\n this.mainFabricCanvas.renderAll();\n }\n }\n };\n }\n})(jQuery, fabric);","$.widget(\"DNA.plateLayOut\", {\n\n plateLayOutWidget: {},\n\n options: {\n value: 0\n },\n\n allTiles: [], // All tiles containes all thise circles in the canvas\n\n addressToLoc: function(layoutAddress) {\n var m = /^([A-Z]+)(\\d+)$/.exec(layoutAddress.trim().toUpperCase())\n if (m) {\n var row_v = m[1];\n var col = parseInt(m[2]) - 1;\n var row;\n for (var i = 0; i < row_v.length; i++) {\n var c = row_v.charCodeAt(i) - 65;\n if (i) {\n row += 1;\n row *= 26;\n row += c;\n } else {\n row = c;\n }\n }\n return {\n r: row,\n c: col\n };\n } else {\n throw layoutAddress + \" not a proper layout address\";\n }\n },\n\n locToIndex: function(loc, dimensions) {\n if (!dimensions) {\n dimensions = this.dimensions;\n }\n if (loc.r < 0) {\n t\n }\n if (!(loc.r >= 0 && loc.r < dimensions.rows)) {\n throw \"Row index \" + (loc.r + 1) + \" invalid\";\n }\n if (!(loc.c >= 0 && loc.c < dimensions.cols)) {\n throw \"Column index \" + (loc.c + 1) + \" invalid\";\n }\n return loc.r * dimensions.cols + loc.c;\n },\n\n addressToIndex: function(layoutAddress, dimensions) {\n var loc = this.addressToLoc(layoutAddress);\n return this.locToIndex(loc, dimensions);\n },\n\n _rowKey: function(i) {\n var c1 = i % 26;\n var c2 = (i - c1) / 26;\n var code = String.fromCharCode(65 + c1);\n if (c2 > 0) {\n code = String.fromCharCode(64 + c2) + code;\n }\n return code;\n },\n\n indexToLoc: function(index, dimensions) {\n if (!dimensions) {\n dimensions = this.dimensions;\n }\n\n if (index >= dimensions.rows * dimensions.cols) {\n throw \"Index too high: \" + index.toString(10);\n }\n var loc = {};\n loc.c = index % dimensions.cols;\n loc.r = (index - loc.c) / dimensions.cols;\n\n return loc;\n },\n\n locToAddress: function(loc) {\n return this._rowKey(loc.r) + (loc.c + 1).toString(10);\n },\n\n indexToAddress: function(index, dimensions) {\n var loc = this.indexToLoc(index, dimensions);\n return this.locToAddress(loc);\n },\n\n getDimensions: function() {\n return $.extend(true, {}, this.dimensions);\n },\n\n _create: function() {\n var rows = parseInt(this.options.numRows || 8);\n var cols = parseInt(this.options.numCols || 12);\n this.dimensions = {\n rows: rows,\n cols: cols\n };\n this.rowIndex = [];\n for (var i = 0; i < rows; i++) {\n this.rowIndex.push(this._rowKey(i));\n }\n\n this.target = (this.element[0].id) ? \"#\" + this.element[0].id : \".\" + this.element[0].className;\n\n // Import classes from other files.. Here we import it using extend and add it to this\n // object. internally we add to widget.DNA.getPlates.prototype.\n // Helpers are methods which return other methods and objects.\n // add Objects to plateLayOutWidget and it will be added to this object.\n // set read only well\n if (this.options.readOnly) {\n this.isReadOnly(true);\n }\n\n for (var component in plateLayOutWidget) {\n // Incase some properties has to initialize with data from options hash,\n // we provide it sending this object.\n $.extend(this, new plateLayOutWidget[component](this));\n }\n\n this._createInterface();\n\n this._trigger(\"created\", null, this);\n\n return this;\n },\n\n _init: function() {\n // This is invoked when the user use the plugin after _create is called.\n // The point is _create is invoked for the very first time and for all other\n // times _init is used.\n },\n\n addData: function() {\n alert(\"wow this is good\");\n },\n\n // wellsData follows syntax: {0:{field1: val1, field2: val2}, 1:{field1: val1, field2: val2}}\n getTextDerivative: function(wellsData) {\n var textDerivative = {};\n var fieldMap = this.fieldMap;\n for (var idx in wellsData) {\n var textValWell = {};\n var textFieldIdWell = {};\n var curWellData = wellsData[idx];\n for (var fieldId in curWellData) {\n if (fieldId in this.fieldMap) {\n var field = this.fieldMap[fieldId];\n var textVal = field.parseText(curWellData[fieldId]);\n textFieldIdWell[field.name] = textVal;\n textValWell[fieldId] = textVal;\n } else {\n // do not convert if not a field (ex: layout_address)\n textFieldIdWell[fieldId] = curWellData[fieldId];\n textValWell[fieldId] = curWellData[fieldId];\n }\n }\n textDerivative[idx] = {\n textVal: textValWell,\n textFieldVal: textFieldIdWell\n };\n }\n\n return textDerivative;\n },\n\n // wellsData follows syntax: {0:{field1: val1, field2: val2}, 1:{field1: val1, field2: val2}}\n getWellsDifferences: function(wellsData) {\n return this.getDifferentWellsVals(wellsData);\n },\n\n setFieldsDisabled: function(flag) {\n this.fieldList.forEach(function(field) {\n field.disabled(flag);\n });\n },\n\n isReadOnly: function(flag) {\n if (flag) {\n this.readOnly = true;\n } else {\n this.readOnly = false;\n }\n this.readOnlyHandler();\n },\n\n readOnlyHandler: function() {\n if (this.readOnly) {\n this.overLayButtonContainer.css(\"display\", \"none\");\n $('.multiple-field-manage-delete-button').css(\"display\", \"none\");\n this.setFieldsDisabled(true);\n } else {\n this.overLayButtonContainer.css(\"display\", \"flex\");\n $('.multiple-field-manage-delete-button').css(\"display\", \"none\");\n if (!this.disableAddDeleteWell) {\n this.setFieldsDisabled(false);\n }\n }\n },\n\n disableAddDeleteWell: null,\n // column_with_default_val will be used to determine empty wells, format: {field_name: default_val}\n isDisableAddDeleteWell: function(flag, column_with_default_val) {\n if (flag) {\n this.disableAddDeleteWell = true;\n this.addressAllowToEdit = this.getWellSetAddressWithData();\n // configure undo redo action\n this.actionPointer = 0;\n this.undoRedoArray = [];\n this.undoRedoArray.push(this.createObject());\n if (column_with_default_val) {\n this.emptyWellWithDefaultVal = column_with_default_val;\n }\n } else {\n this.disableAddDeleteWell = false;\n this.setFieldsDisabled(false);\n this.emptyWellWithDefaultVal = null;\n }\n this._fabricEvents();\n },\n\n getSelectedObject: function() {\n var selectedAddress = [];\n for (var i = 0; i < this.allSelectedObjects.length; i++) {\n selectedAddress.push(this.allSelectedObjects[i].address);\n }\n var selectedObjects = {};\n var derivative = this.engine.derivative;\n for (var index in derivative) {\n var address = this.indexToAddress(index);\n if (selectedAddress.indexOf(address) >= 0) {\n var well = JSON.parse(JSON.stringify(derivative[index]));\n well.colorIndex = this.engine.colorMap.get(Number(index));\n selectedObjects[address] = well;\n }\n }\n return selectedObjects;\n },\n\n selectObjectInBottomTab: function() {\n var selectedObjects = this.getSelectedObject();\n var selectedObjectAddress;\n for (var prop in selectedObjects) {\n if (!selectedObjectAddress) {\n selectedObjectAddress = prop;\n } else {\n return; // scroll to matching group only if a single well has been selected\n }\n }\n if (selectedObjects[selectedObjectAddress]) {\n var colorIndex = selectedObjects[selectedObjectAddress].colorIndex;\n var trs = document.querySelectorAll('table.plate-setup-bottom-table tr');\n for (var i = 1; i < trs.length; i++) { // start at 1 to skip the table headers\n var tds = trs[i].children;\n var isSelected = tds[0].querySelector('button').innerHTML === colorIndex.toString();\n for (var j = 1; j < tds.length; j++) {\n if (isSelected) {\n tds[j].style.background = '#22cb94';\n } else {\n tds[j].style.background = '#ffffff';\n }\n }\n if (isSelected) {\n scrollTo(document.querySelector('.plate-setup-bottom-table-container'), tds[0].offsetTop, 300);\n }\n }\n }\n },\n\n getSelectedIndex: function() {\n return this.allSelectedObjects.map(function(selectedObj) {\n return that.addressToIndex(selectedObj.address)\n });\n },\n\n getSelectedAddress: function() {\n return this.allSelectedObjects.map(function(selectedObj) {\n return selectedObj.address;\n });\n },\n\n setSelectedWell: function(addressList) {\n var areas = [];\n var minRow = 999;\n var locMap = {};\n for (var id = 0; id < addressList.length; id++) {\n var wellIdx = this.addressToIndex(addressList[id]);\n var loc = this.indexToLoc(wellIdx);\n areas.push({\n minCol: loc.c,\n minRow: loc.r,\n maxCol: loc.c,\n maxRow: loc.r\n });\n if (loc.r <= minRow) {\n minRow = loc.r;\n if (loc.r in locMap) {\n locMap[loc.r].push(loc.c);\n } else {\n locMap[loc.r] = [loc.c];\n }\n }\n }\n var focalWell = {\n row: minRow,\n col: Math.min.apply(null, locMap[minRow])\n };\n\n this.setSelection(areas, focalWell);\n this.decideSelectedFields();\n this.mainFabricCanvas.renderAll();\n }\n\n});\n\n// https://stackoverflow.com/questions/17733076/smooth-scroll-anchor-links-without-jquery\nfunction scrollTo(element, to, duration) {\n if (duration <= 0) return;\n var difference = to - element.scrollTop;\n var perTick = difference / duration * 10;\n setTimeout(function() {\n element.scrollTop = element.scrollTop + perTick;\n if (element.scrollTop === to) return;\n scrollTo(element, to, duration - 10);\n }, 10);\n}","var plateLayOutWidget = plateLayOutWidget || {};\n\n(function($, fabric) {\n\n plateLayOutWidget.preset = function(me) {\n // All the preset action goes here\n return {\n\n presets: [],\n\n _placePresetTabs: function() {\n var presets = this.options.attributes.presets;\n\n if (presets && presets.length) {\n this.wellAttrContainer = this._createElement(\"
\").addClass(\"plate-setup-well-attr-container\")\n .text(\"Checkbox presets\");\n this.tabContainer.append(this.wellAttrContainer);\n\n this.presetTabContainer = this._createElement(\"
\").addClass(\"plate-setup-preset-container\");\n this.tabContainer.append(this.presetTabContainer);\n\n for (var i = 0; i < presets.length; i++) {\n var preset = presets[i];\n var divText = this._createElement(\"
\").addClass(\"plate-setup-prest-tab-div\")\n .text(preset.title);\n\n var presetButton = this._createElement(\"
\").addClass(\"plate-setup-prest-tab\")\n .data(\"preset\", preset.fields).append(divText);\n this.presetTabContainer.append(presetButton);\n\n var that = this;\n presetButton.click(function() {\n var preset = $(this);\n that._selectPreset(preset);\n });\n this.presets.push(presetButton);\n }\n }\n },\n\n _clearPresetSelection: function() {\n for (var j = 0; j < this.presets.length; j++) {\n var p = this.presets[j];\n p.removeClass(\"plate-setup-prest-tab-selected\")\n .addClass(\"plate-setup-prest-tab\");\n }\n },\n\n _selectPreset: function(preset) {\n this.setCheckboxes(preset.data(\"preset\"));\n preset.removeClass(\"plate-setup-prest-tab\")\n .addClass(\"plate-setup-prest-tab-selected\");\n },\n };\n }\n})(jQuery, fabric);","var plateLayOutWidget = plateLayOutWidget || {};\n\n(function($, fabric) {\n\n plateLayOutWidget.tabs = function() {\n // Tabs crete and manage tabs at the right side of the canvas.\n return {\n\n allTabs: [],\n\n defaultWell: {},\n\n allDataTabs: [], // To hold all the tab contents. this contains all the tabs and its elements and elements\n // Settings as a whole. its very usefull, when we have units for a specific field.\n // it goes like tabs-> individual field-> units and checkbox\n\n _createTabAtRight: function() {\n this.tabContainer = this._createElement(\"
\").addClass(\"plate-setup-tab-container\");\n $(this.topRight).append(this.tabContainer);\n },\n\n _createTabs: function() {\n // this could be done using z-index. just imagine few cards stacked up.\n // Check if options has tab data.\n // Originally we will be pulling tab data from developer.\n // Now we are building upon dummy data.\n this.tabHead = this._createElement(\"
\").addClass(\"plate-setup-tab-head\");\n $(this.tabContainer).append(this.tabHead);\n\n var tabData = this.options.attributes.tabs;\n var that = this;\n\n tabData.forEach(function(tab, tabIndex) {\n that.allTabs[tabIndex] = that._createElement(\"
\").addClass(\"plate-setup-tab\");\n $(that.allTabs[tabIndex]).data(\"index\", tabIndex)\n .text(tab.name);\n\n $(that.allTabs[tabIndex]).click(function() {\n that._tabClickHandler(this);\n });\n\n $(that.tabHead).append(that.allTabs[tabIndex]);\n });\n\n this.tabDataContainer = this._createElement(\"
\").addClass(\"plate-setup-tab-data-container\");\n $(this.tabContainer).append(this.tabDataContainer);\n\n this._addDataTabs(tabData);\n\n $(this.allTabs[0]).click();\n\n this._addTabData();\n },\n\n _tabClickHandler: function(clickedTab) {\n\n if (this.selectedTab) {\n $(this.selectedTab).removeClass(\"plate-setup-tab-selected\")\n .addClass(\"plate-setup-tab\");\n\n var previouslyClickedTabIndex = $(this.selectedTab).data(\"index\");\n $(this.allDataTabs[previouslyClickedTabIndex]).css(\"z-index\", 0);\n this.readOnlyHandler();\n }\n\n $(clickedTab).addClass(\"plate-setup-tab-selected\");\n\n this.selectedTab = clickedTab;\n\n var clickedTabIndex = $(clickedTab).data(\"index\");\n $(this.allDataTabs[clickedTabIndex]).css(\"z-index\", 1000);\n },\n\n _addDataTabs: function(tabs) {\n\n var tabIndex = 0;\n\n for (var tabData in tabs) {\n this.allDataTabs[tabIndex++] = this._createElement(\"
\").addClass(\"plate-setup-data-div\")\n .css(\"z-index\", 0);\n $(this.tabDataContainer).append(this.allDataTabs[tabIndex - 1]);\n }\n }\n };\n }\n})(jQuery, fabric);","var plateLayOutWidget = plateLayOutWidget || {};\n\n(function($, fabric) {\n\n plateLayOutWidget.undoRedoManager = function(THIS) {\n\n return {\n\n undoRedoArray: [],\n\n actionPointer: null,\n\n addToUndoRedo: function(data) {\n\n if (this.actionPointer != null) {\n var i = this.actionPointer + 1;\n if (i < this.undoRedoArray.length) {\n this.undoRedoArray.splice(i, this.undoRedoArray.length - i);\n }\n }\n this.actionPointer = null;\n this.undoRedoArray.push($.extend(true, {}, data));\n },\n\n _configureUndoRedoArray: function() {\n\n var data = {\n checkboxes: [],\n derivative: {},\n selectedAreas: [{\n minRow: 0,\n minCol: 0,\n maxRow: 0,\n maxCol: 0\n }],\n focalWell: {\n row: 0,\n col: 0\n }\n };\n\n this.undoRedoArray = [];\n this.actionPointer = null;\n this.undoRedoArray.push($.extend({}, data));\n },\n\n undo: function() {\n console.log(\"undo\");\n return this.shiftUndoRedo(-1);\n },\n\n redo: function() {\n console.log(\"redo\");\n return this.shiftUndoRedo(1);\n },\n\n shiftUndoRedo: function(pointerDiff) {\n var pointer = this.actionPointer;\n if (pointer == null) {\n pointer = this.undoRedoArray.length - 1;\n }\n pointer += pointerDiff;\n return this.setUndoRedo(pointer);\n },\n\n setUndoRedo: function(pointer) {\n if (pointer < 0) {\n return false;\n }\n if (pointer >= this.undoRedoArray.length) {\n return false;\n }\n this.undoRedoActive = true;\n this.setData(this.undoRedoArray[pointer]);\n this.actionPointer = pointer;\n this.undoRedoActive = false;\n this.derivativeChange();\n return true;\n }\n }\n };\n\n})(jQuery, fabric);","var plateLayOutWidget = plateLayOutWidget || {};\n\n(function($, fabric) {\n\n plateLayOutWidget.wellArea = function(fabric) {\n\n return {\n\n _areasToTiles: function(areas) {\n //Convert areas to tiles\n var cols = this.dimensions.cols;\n var that = this;\n return areas.reduce(function(tiles, area) {\n if (area) {\n for (var r = area.minRow; r <= area.maxRow; r++) {\n for (var c = area.minCol; c <= area.maxCol; c++) {\n var tile = that.allTiles[c + cols * r];\n if (tiles.indexOf(tile) < 0) {\n if (that.disableAddDeleteWell) {\n if (that.addressAllowToEdit.indexOf(tile.address) >= 0) {\n tiles.push(tile);\n }\n } else {\n tiles.push(tile);\n }\n }\n }\n }\n }\n return tiles;\n }, []);\n },\n\n _encodeArea: function(area) {\n //Encode area as string\n if ((area.minRow == area.maxRow) && (area.minCol == area.maxCol)) {\n return this.rowIndex[area.minRow] + area.minCol.toString(10);\n } else {\n return this.rowIndex[area.minRow] + area.minCol.toString(10) + \":\" + this.rowIndex[area.maxRow] + area.maxCol.toString(10);\n }\n },\n\n _encodeAreas: function(areas) {\n //Encode an array of areas as a string\n var that = this;\n return areas.map(function(area) {\n return that._encodeArea(area);\n }).join(\",\");\n },\n\n _decodeWell: function(wellAddress) {\n var that = this;\n var adRx = new RegExp(\"^\\\\s*(\" + that.rowIndex.join(\"|\") + \")(\\\\d+)\\\\s*$\")\n var rcRx = /^\\s*R(\\d+)C(\\d+)\\s*$/i;\n\n var match;\n match = wellAddress.match(adRx);\n if (match) {\n var row = that.rowIndex.indexOf(match[1]);\n if (row >= 0) {\n return {\n row: row,\n col: parseInt(match[2]) - 1\n };\n }\n }\n match = wellAddress.match(rcRx);\n if (match) {\n return {\n row: parseInt(match[1]) - 1,\n col: parseInt(match[2]) - 1\n };\n }\n\n throw \"Invalid well address: \" + wellAddress;\n },\n\n _decodeArea: function(areaAddress) {\n //Decode single area as string\n var that = this;\n var wells = areaAddress.split(\":\").map(function(wellAddress) {\n return that._decodeWell(wellAddress);\n })\n if (wells.length == 1) {\n return {\n minRow: wells[0].row,\n minCol: wells[0].col,\n maxRow: wells[0].row,\n maxCol: wells[0].col\n }\n } else if (wells.length == 2) {\n var minRow = Math.min(wells[0].row, wells[1].row)\n return {\n minRow: Math.min(wells[0].row, wells[1].row),\n minCol: Math.min(wells[0].col, wells[1].col),\n maxRow: Math.max(wells[0].row, wells[1].row),\n maxCol: Math.max(wells[0].col, wells[1].col)\n }\n } else {\n throw \"Invalid address: \" + areaAddress;\n }\n },\n\n _decodeAreas: function(areasAddress) {\n //Decode single area as string\n var that = this;\n return areasAddress.split(\",\").map(function(areaAddress) {\n return that._decodeArea(areaAddress);\n });\n },\n\n _wellToArea: function(well) {\n //Convert a well to an area\n return {\n minCol: well.col,\n minRow: well.row,\n maxCol: well.col,\n maxRow: well.row\n }\n },\n\n _wellInArea: function(well, area) {\n //Determine if a well lies within an area\n return well.row >= area.minRow && well.row <= area.maxRow && well.col >= area.minCol && well.col <= area.maxCol;\n },\n\n _coordsToRect: function(startCoords, endCoords) {\n //Convert two XY coords to a bounding box\n var left = Math.min(startCoords.x, endCoords.x);\n var top = Math.min(startCoords.y, endCoords.y);\n var height = Math.abs(endCoords.y - startCoords.y);\n var width = Math.abs(endCoords.x - startCoords.x);\n return {\n top: top,\n left: left,\n height: height,\n width: width\n };\n },\n\n _coordIndex: function(v, count) {\n var i;\n if (v < 0) {\n i = 0;\n } else if (v >= count) {\n i = count - 1;\n } else {\n i = Math.floor(v);\n }\n return i;\n },\n\n _coordsToWell: function(coord) {\n //Convert a coordinate to a well\n var cols = this.dimensions.cols;\n var rows = this.dimensions.rows;\n\n var w = this.sizes.spacing;\n var m = this.sizes.label_spacing;\n\n var x = (coord.x - m) / w;\n var y = (coord.y - m) / w;\n\n var row = this._coordIndex(y, rows);\n var col = this._coordIndex(x, cols);\n\n return {\n row: row,\n col: col,\n };\n },\n\n _wellToCoords: function(well, center) {\n //Convert a well to a coordinate\n var w = this.sizes.spacing;\n var m = this.sizes.label_spacing;\n var x = well.col * w + m;\n var y = well.row * w + m;\n if (center) {\n var hw = w / 2;\n x = x + hw;\n y = y + hw;\n }\n\n return {\n x: x,\n y: y\n };\n },\n\n _areaToRect: function(area) {\n //Convert area to rectangle\n var rows = area.maxRow - area.minRow + 1;\n var cols = area.maxCol - area.minCol + 1;\n\n var w = this.sizes.spacing;\n var m = this.sizes.label_spacing;\n\n return {\n top: area.minRow * w + m,\n left: area.minCol * w + m,\n height: rows * w,\n width: cols * w\n }\n },\n\n _rectToArea: function(rect) {\n //Convert a rectangular region to an area\n var rows = this.dimensions.rows;\n var cols = this.dimensions.cols;\n\n var w = this.sizes.spacing;\n var m = this.sizes.label_spacing;\n\n var left = (rect.left - m) / w;\n var top = (rect.top - m) / w;\n var height = rect.height / w;\n var width = rect.width / w;\n var right = left + width;\n var bottom = top + height;\n\n //select whole row\n if (right < 0) {\n right = cols;\n }\n if (left >= cols) {\n left = 0;\n }\n //select whole col\n if (bottom < 0) {\n bottom = rows;\n }\n if (top <= 0) {\n top = 0;\n }\n\n return {\n minCol: this._coordIndex(left, cols),\n minRow: this._coordIndex(top, rows),\n maxCol: this._coordIndex(right, cols),\n maxRow: this._coordIndex(bottom, rows)\n };\n }\n\n }\n }\n})(jQuery, fabric);"]}
\ No newline at end of file