diff --git a/package-lock.json b/package-lock.json
index 7a2a2ca09..6e541a194 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "visualizer",
- "version": "2.173.0",
+ "version": "2.173.3",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "visualizer",
- "version": "2.173.0",
+ "version": "2.173.3",
"hasInstallScript": true,
"license": "MIT",
"dependencies": {
@@ -23,8 +23,8 @@
"mf-parser": "^1.5.0",
"mime-types": "^2.1.35",
"node-jsgraph": "2.4.15",
- "openchemlib": "^9.6.0",
- "quill": "^2.0.2",
+ "openchemlib": "^9.14.0",
+ "quill": "2.0.2",
"quill-resize-module": "^2.0.4",
"quill-table-better": "^1.2.1",
"rxn-renderer": "^1.0.2",
@@ -6834,9 +6834,9 @@
}
},
"node_modules/openchemlib": {
- "version": "9.6.0",
- "resolved": "https://registry.npmjs.org/openchemlib/-/openchemlib-9.6.0.tgz",
- "integrity": "sha512-SAMLSwOQTCDNpfNu/WTQpzLMYTRj/xwetMPRoAGHeR2J162RP/OI6vHpVcC7L4V7ThMW3ZhMf7GdH04yndmHtw==",
+ "version": "9.14.0",
+ "resolved": "https://registry.npmjs.org/openchemlib/-/openchemlib-9.14.0.tgz",
+ "integrity": "sha512-c2Rh2oNLnlXfPbdMsfhm9VHTGJkSdI6+EnvVXwY+v9oO9p0XBnfG85D/1ussxYqbOIof3l4OaBGM5Q6/4sLMjA==",
"license": "BSD-3-Clause"
},
"node_modules/optionator": {
diff --git a/package.json b/package.json
index e0208cff1..d1fb23500 100644
--- a/package.json
+++ b/package.json
@@ -82,7 +82,7 @@
"mf-parser": "^1.5.0",
"mime-types": "^2.1.35",
"node-jsgraph": "2.4.15",
- "openchemlib": "^9.6.0",
+ "openchemlib": "^9.14.0",
"quill": "2.0.2",
"quill-resize-module": "^2.0.4",
"quill-table-better": "^1.2.1",
@@ -92,6 +92,6 @@
"twig": "^1.17.1"
},
"volta": {
- "node": "20.19.1"
+ "node": "20.19.5"
}
}
diff --git a/src/modules/types/science/chemistry/folder.json b/src/modules/types/science/chemistry/folder.json
index 135e58b7c..851f36bf3 100644
--- a/src/modules/types/science/chemistry/folder.json
+++ b/src/modules/types/science/chemistry/folder.json
@@ -12,6 +12,10 @@
"moduleName": "OCL Molecule editor",
"url": "modules/types/science/chemistry/ocl_editor/"
},
+ {
+ "moduleName": "OCL Reaction editor",
+ "url": "modules/types/science/chemistry/ocl_reaction_editor/"
+ },
{
"moduleName": "Periodic table",
"url": "modules/types/science/chemistry/periodic_table/"
diff --git a/src/modules/types/science/chemistry/ocl_editor/controller.js b/src/modules/types/science/chemistry/ocl_editor/controller.js
index 313cc2bab..b9f01cf42 100644
--- a/src/modules/types/science/chemistry/ocl_editor/controller.js
+++ b/src/modules/types/science/chemistry/ocl_editor/controller.js
@@ -21,7 +21,7 @@ define([
'modules/types/science/chemistry/ocl_editor/help.html',
);
ui.dialog(
- ``,
+ ``,
{
width: Math.min(w - 40, 800),
height: h - 70,
@@ -103,7 +103,7 @@ define([
Controller.prototype.moduleInformation = {
name: 'OCL Molecule editor',
- description: 'Molecule editor using the openchemlib javascript library',
+ description: 'Molecule editor using the OpenChemLib JavaScript library',
author: 'Michael Zasso',
date: '11.05.2015',
license: 'BSD',
diff --git a/src/modules/types/science/chemistry/ocl_editor/view.js b/src/modules/types/science/chemistry/ocl_editor/view.js
index c1c383781..c1ebf939d 100644
--- a/src/modules/types/science/chemistry/ocl_editor/view.js
+++ b/src/modules/types/science/chemistry/ocl_editor/view.js
@@ -27,24 +27,10 @@ define(['modules/default/defaultview', 'src/util/ui', 'openchemlib'], function (
let pastedData = clipboardData.getData('text');
if (!pastedData) return;
- let molecule;
- try {
- if (/M {2}END/.test(pastedData)) {
- molecule = OCL.Molecule.fromMolfile(pastedData);
- } else {
- try {
- molecule = OCL.Molecule.fromSmiles(pastedData.trim());
- } catch {
- molecule = OCL.Molecule.fromIDCode(pastedData.trim());
- }
- }
- if (molecule) {
- setCurrentValue(this, molecule);
- event.preventDefault();
- }
- } catch (error) {
- // eslint-disable-next-line no-console
- console.error(error);
+ const molecule = OCL.Molecule.fromText(pastedData);
+ if (molecule) {
+ setCurrentValue(this, molecule);
+ event.preventDefault();
}
});
},
diff --git a/src/modules/types/science/chemistry/ocl_reaction_editor/controller.js b/src/modules/types/science/chemistry/ocl_reaction_editor/controller.js
new file mode 100644
index 000000000..413f68d27
--- /dev/null
+++ b/src/modules/types/science/chemistry/ocl_reaction_editor/controller.js
@@ -0,0 +1,171 @@
+'use strict';
+
+define([
+ 'modules/default/defaultcontroller',
+ 'openchemlib',
+ 'src/util/ui',
+], function (Default, OCL, ui) {
+ function Controller() {}
+
+ $.extend(true, Controller.prototype, Default);
+
+ Controller.prototype.getToolbar = function () {
+ const base = Default.getToolbar.call(this);
+ base.unshift({
+ onClick() {
+ const w = $(window).width();
+ const h = $(window).height();
+ const url = require.toUrl(
+ 'modules/types/science/chemistry/ocl_editor/help.html',
+ );
+ ui.dialog(
+ ``,
+ {
+ width: Math.min(w - 40, 800),
+ height: h - 70,
+ title: 'OpenChemLib editor Help',
+ },
+ );
+ },
+ title: 'Help',
+ cssClass: 'fa fa-question',
+ ifLocked: true,
+ });
+ base.unshift({
+ onClick: () => {
+ if (navigator.clipboard) {
+ navigator.clipboard.readText().then((text) => {
+ this.module.view.onActionReceive.addProduct.call(
+ this.module.view,
+ text,
+ );
+ });
+ }
+ },
+ title: 'Add product from clipboard (RXN, SMILES or ID code)',
+ cssClass: 'fa fa-paste',
+ ifLocked: true,
+ });
+ base.unshift({
+ onClick: () => {
+ if (navigator.clipboard) {
+ navigator.clipboard.readText().then((text) => {
+ this.module.view.onActionReceive.addReactant.call(
+ this.module.view,
+ text,
+ );
+ });
+ }
+ },
+ title: 'Add reactant from clipboard (RXN, SMILES or ID code)',
+ cssClass: 'fa fa-paste',
+ ifLocked: true,
+ });
+ base.unshift({
+ onClick: () => {
+ const rxnV3 = this.module.view.editor.getReaction().toRxnV3();
+ ui.copyToClipboard(rxnV3, {
+ successMessage: 'RXN V3000 copied to the clipboard',
+ });
+ },
+ title: 'Copy RXN V3000 to clipboard',
+ cssClass: 'fa fa-copy',
+ ifLocked: true,
+ });
+ return base;
+ };
+
+ Controller.prototype.moduleInformation = {
+ name: 'OCL Reaction Editor',
+ description: 'Reaction editor using the OpenChemLib JavaScript library',
+ author: 'Michael Zasso',
+ date: '29.10.2025',
+ license: 'BSD',
+ cssClass: 'ocl_reaction_editor',
+ };
+
+ Controller.prototype.references = {
+ rxn: { label: 'RXN V2000' },
+ rxnV3: { label: 'RXN V3000' },
+ smiles: { label: 'SMILES' },
+ reactionIdCode: { label: 'OCL reaction ID code' },
+ };
+
+ Controller.prototype.variablesIn = [
+ 'rxn',
+ 'rxnV3',
+ 'smiles',
+ 'reactionIdCode',
+ ];
+
+ Controller.prototype.events = {
+ onReactionChange: {
+ label: 'Reaction has changed',
+ refVariable: ['rxn', 'rxnV3', 'smiles', 'reactionIdCode'],
+ },
+ };
+
+ Controller.prototype.actionsIn = $.extend({}, Default.actionsIn, {
+ addReactant: 'Add a reactant from text (molfile, SMILES, or ID code)',
+ addProduct: 'Add a product from text (molfile, SMILES, or ID code)',
+ });
+
+ Controller.prototype.configurationStructure = function () {
+ return {
+ groups: {
+ group: {
+ options: { type: 'list' },
+ fields: {
+ prefs: {
+ type: 'checkbox',
+ title: 'Options',
+ options: {
+ queryFeatures: 'Enable query features',
+ inPlace: 'Modify input variable',
+ },
+ },
+ },
+ },
+ },
+ };
+ };
+
+ Controller.prototype.configAliases = {
+ prefs: ['groups', 'group', 0, 'prefs', 0],
+ };
+
+ Controller.prototype.onChange = function (event, reaction) {
+ const inPlace = this.module.getConfigurationCheckbox('prefs', 'inPlace');
+ const idCode = OCL.ReactionEncoder.encode(reaction) || '';
+ const rxn = reaction.toRxn();
+ const rxnV3 = reaction.toRxnV3();
+ const smiles = reaction.toSmiles();
+ this.createDataFromEvent('onReactionChange', 'rxn', rxn);
+ this.createDataFromEvent('onReactionChange', 'rxnV3', rxnV3);
+ this.createDataFromEvent('onReactionChange', 'smiles', smiles);
+ this.createDataFromEvent('onReactionChange', 'reactionIdCode', idCode);
+
+ if (inPlace && this.module.view._currentType) {
+ const currentValue = this.module.view._currentValue;
+ switch (this.module.view._currentType) {
+ case 'rxn':
+ currentValue.setValue(rxn);
+ break;
+ case 'rxnV3':
+ currentValue.setValue(rxnV3);
+ break;
+ case 'smiles':
+ currentValue.setValue(smiles);
+ break;
+ case 'reactionIdCode':
+ currentValue.setValue(idCode);
+ break;
+ default:
+ throw new Error('invalid reaction value type');
+ }
+ this.module.model.dataTriggerChange(currentValue);
+ }
+ };
+
+ return Controller;
+});
diff --git a/src/modules/types/science/chemistry/ocl_reaction_editor/model.js b/src/modules/types/science/chemistry/ocl_reaction_editor/model.js
new file mode 100644
index 000000000..c24586af2
--- /dev/null
+++ b/src/modules/types/science/chemistry/ocl_reaction_editor/model.js
@@ -0,0 +1,9 @@
+'use strict';
+
+define(['modules/default/defaultmodel'], function (Default) {
+ function Model() {}
+
+ $.extend(true, Model.prototype, Default);
+
+ return Model;
+});
diff --git a/src/modules/types/science/chemistry/ocl_reaction_editor/style.css b/src/modules/types/science/chemistry/ocl_reaction_editor/style.css
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/modules/types/science/chemistry/ocl_reaction_editor/view.js b/src/modules/types/science/chemistry/ocl_reaction_editor/view.js
new file mode 100644
index 000000000..47d3d5f30
--- /dev/null
+++ b/src/modules/types/science/chemistry/ocl_reaction_editor/view.js
@@ -0,0 +1,152 @@
+'use strict';
+
+define(['modules/default/defaultview', 'src/util/ui', 'openchemlib'], function (
+ Default,
+ ui,
+ OCL,
+) {
+ function View() {}
+
+ $.extend(true, View.prototype, Default, {
+ init() {
+ this.editor = null;
+ this._currentReaction = OCL.Reaction.create();
+ this._currentValue = null;
+ this._currentType = null;
+ },
+
+ inDom() {
+ this.dom = $('
').css({
+ height: '99%',
+ width: '100%',
+ });
+ this.module.getDomContent().html(this.dom);
+ this.resetEditor();
+ this.resolveReady();
+ },
+
+ onResize() {
+ this.resetEditor();
+ },
+
+ blank: {
+ rxn() {
+ this.clearEditor();
+ },
+ rxnV3() {
+ this.clearEditor();
+ },
+ smiles() {
+ this.clearEditor();
+ },
+ reactionIdCode() {
+ this.clearEditor();
+ },
+ },
+
+ onActionReceive: {
+ addReactant(value) {
+ const molecule = OCL.Molecule.fromText(value);
+ if (molecule) {
+ const reaction = this.editor.getReaction();
+ reaction.addReactant(molecule);
+ this.setReaction(reaction, true);
+ }
+ },
+ addProduct(value) {
+ const molecule = OCL.Molecule.fromText(value);
+ if (molecule) {
+ const reaction = this.editor.getReaction();
+ reaction.addProduct(molecule);
+ this.setReaction(reaction, true);
+ }
+ },
+ },
+
+ update: {
+ rxn(value) {
+ this._currentValue = value;
+ this._currentType = 'rxn';
+ this.setReaction(OCL.Reaction.fromRxn(String(value.get())));
+ },
+ rxnV3(value) {
+ this._currentValue = value;
+ this._currentType = 'rxnV3';
+ this.setReaction(OCL.Reaction.fromRxn(String(value.get())));
+ },
+ smiles(value) {
+ this._currentValue = value;
+ this._currentType = 'smiles';
+ this.setReaction(OCL.Reaction.fromSmiles(String(value.get())));
+ },
+ reactionIdCode(value) {
+ const reaction = OCL.ReactionEncoder.decode(String(value.get()));
+ if (reaction) {
+ this._currentValue = value;
+ this._currentType = 'reactionIdCode';
+ this.setReaction(reaction);
+ }
+ },
+ },
+
+ resetEditor() {
+ if (this.editor) {
+ this.editor.destroy();
+ this.dom.empty();
+ }
+ this.editor = new OCL.CanvasEditor(this.dom.get(0), {
+ initialMode: 'reaction',
+ });
+ this.editor.setOnChangeListener((event) => {
+ const reaction = this.editor.getReaction();
+ this._currentReaction = reaction;
+ this.module.controller.onChange(event, reaction);
+ });
+ this.setReaction(this._currentReaction);
+ },
+
+ clearEditor() {
+ this._currentValue = null;
+ this._currentType = null;
+ this.setReaction(OCL.Reaction.create());
+ },
+
+ setReaction(reaction, updateValue = false) {
+ reaction.setFragment(
+ this.module.getConfigurationCheckbox('prefs', 'queryFeatures'),
+ );
+ this._currentReaction = reaction;
+ this.editor.setReaction(reaction);
+ if (updateValue) {
+ setCurrentValue(this, reaction);
+ }
+ },
+ });
+
+ function setCurrentValue(self, reaction) {
+ const setValue = (value) => {
+ if (self._currentValue) {
+ self._currentValue.setValue(value);
+ }
+ };
+
+ switch (self._currentType) {
+ case 'rxn':
+ setValue(reaction.toRxn());
+ break;
+ case 'rxnV3':
+ setValue(reaction.toRxnV3());
+ break;
+ case 'smiles':
+ setValue(reaction.toSmiles());
+ break;
+ case 'reactionIdCode': {
+ const idCode = OCL.ReactionEncoder.encode(reaction) || '';
+ setValue(idCode);
+ break;
+ }
+ }
+ }
+
+ return View;
+});
diff --git a/testcase/data/openchemlib-reaction-inplace/data.json b/testcase/data/openchemlib-reaction-inplace/data.json
new file mode 100644
index 000000000..9e26dfeeb
--- /dev/null
+++ b/testcase/data/openchemlib-reaction-inplace/data.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/testcase/data/openchemlib-reaction-inplace/view.json b/testcase/data/openchemlib-reaction-inplace/view.json
new file mode 100644
index 000000000..c249e9777
--- /dev/null
+++ b/testcase/data/openchemlib-reaction-inplace/view.json
@@ -0,0 +1,953 @@
+{
+ "version": "2.173.4-0",
+ "grid": {
+ "layers": {
+ "Default layer": {
+ "name": "Default layer"
+ }
+ },
+ "xWidth": 10,
+ "yHeight": 10
+ },
+ "modules": [
+ {
+ "url": "modules/types/science/chemistry/ocl_reaction_editor/",
+ "configuration": {
+ "sections": {},
+ "groups": {
+ "group": [
+ {
+ "prefs": [
+ [
+ "inPlace"
+ ]
+ ]
+ }
+ ]
+ }
+ },
+ "layers": {
+ "Default layer": {
+ "position": {
+ "left": 40,
+ "top": 0
+ },
+ "size": {
+ "width": 59,
+ "height": 39
+ },
+ "zIndex": 0,
+ "display": true,
+ "title": "",
+ "bgColor": [
+ 255,
+ 255,
+ 255,
+ 0
+ ],
+ "wrapper": true,
+ "created": true,
+ "name": "Default layer"
+ }
+ },
+ "id": 1,
+ "vars_in": [
+ {
+ "rel": "smiles",
+ "name": "smiles"
+ },
+ {
+ "rel": "rxn",
+ "name": "rxnV2000"
+ },
+ {
+ "rel": "rxnV3",
+ "name": "rxnV3000"
+ }
+ ],
+ "actions_in": [
+ {}
+ ],
+ "vars_out": [
+ {
+ "jpath": []
+ }
+ ],
+ "actions_out": [
+ {
+ "jpath": []
+ }
+ ],
+ "toolbar": {
+ "custom": [
+ [
+ {
+ "title": "",
+ "icon": "",
+ "action": "",
+ "position": "begin",
+ "color": [
+ 100,
+ 100,
+ 100,
+ 1
+ ]
+ }
+ ]
+ ],
+ "common": [
+ {
+ "toolbar": [
+ [
+ "Open Preferences"
+ ]
+ ]
+ }
+ ]
+ },
+ "css": [
+ {
+ "fontSize": [
+ ""
+ ],
+ "fontFamily": [
+ ""
+ ]
+ }
+ ],
+ "title": ""
+ },
+ {
+ "url": "modules/types/client_interaction/code_editor/",
+ "configuration": {
+ "sections": {},
+ "groups": {
+ "group": [
+ {
+ "mode": [
+ "text"
+ ],
+ "outputType": [
+ null
+ ],
+ "btnvalue": [
+ "Reset reaction from smiles"
+ ],
+ "iseditable": [
+ [
+ "editable"
+ ]
+ ],
+ "hasButton": [
+ [
+ "button"
+ ]
+ ],
+ "variable": [
+ []
+ ],
+ "storeOnChange": [
+ []
+ ],
+ "debouncing": [
+ 0
+ ],
+ "script": [
+ "COCO>>COCO"
+ ]
+ }
+ ],
+ "ace": [
+ {
+ "useSoftTabs": [
+ [
+ "yes"
+ ]
+ ],
+ "tabSize": [
+ 4
+ ]
+ }
+ ]
+ }
+ },
+ "layers": {
+ "Default layer": {
+ "position": {
+ "left": 0,
+ "top": 0
+ },
+ "size": {
+ "width": 39,
+ "height": 19
+ },
+ "zIndex": 0,
+ "display": true,
+ "title": "",
+ "bgColor": [
+ 255,
+ 255,
+ 255,
+ 0
+ ],
+ "wrapper": true,
+ "created": true,
+ "name": "Default layer"
+ }
+ },
+ "id": 2,
+ "vars_in": [
+ {}
+ ],
+ "actions_in": [
+ {}
+ ],
+ "vars_out": [
+ {
+ "event": "onButtonClick",
+ "rel": "data",
+ "jpath": [],
+ "name": "smiles"
+ }
+ ],
+ "actions_out": [
+ {
+ "jpath": []
+ }
+ ],
+ "toolbar": {
+ "custom": [
+ [
+ {
+ "title": "",
+ "icon": "",
+ "action": "",
+ "position": "begin",
+ "color": [
+ 100,
+ 100,
+ 100,
+ 1
+ ]
+ }
+ ]
+ ],
+ "common": [
+ {
+ "toolbar": [
+ [
+ "Open Preferences"
+ ]
+ ]
+ }
+ ]
+ },
+ "css": [
+ {
+ "fontSize": [
+ ""
+ ],
+ "fontFamily": [
+ ""
+ ]
+ }
+ ],
+ "title": ""
+ },
+ {
+ "url": "modules/types/display/single_value/",
+ "configuration": {
+ "sections": {},
+ "groups": {
+ "group": [
+ {
+ "append": [
+ []
+ ],
+ "maxEntries": [
+ 1
+ ],
+ "editable": [
+ []
+ ],
+ "editSearchRegexp": [
+ null
+ ],
+ "editReplace": [
+ null
+ ],
+ "debounce": [
+ 0
+ ],
+ "defaultvalue": [
+ null
+ ],
+ "font": [
+ null
+ ],
+ "fontcolor": [
+ [
+ 0,
+ 0,
+ 0,
+ 1
+ ]
+ ],
+ "fontsize": [
+ null
+ ],
+ "align": [
+ null
+ ],
+ "valign": [
+ null
+ ],
+ "rendererOptions": [
+ ""
+ ],
+ "forceType": [
+ ""
+ ],
+ "sprintf": [
+ null
+ ],
+ "sprintfOrder": [
+ null
+ ],
+ "preformatted": [
+ []
+ ]
+ }
+ ]
+ }
+ },
+ "layers": {
+ "Default layer": {
+ "position": {
+ "left": 100,
+ "top": 0
+ },
+ "size": {
+ "width": 53,
+ "height": 8
+ },
+ "zIndex": 0,
+ "display": true,
+ "title": "smiles",
+ "bgColor": [
+ 255,
+ 255,
+ 255,
+ 0
+ ],
+ "wrapper": true,
+ "created": true,
+ "name": "Default layer"
+ }
+ },
+ "id": 3,
+ "vars_in": [
+ {
+ "rel": "value",
+ "name": "smiles"
+ }
+ ],
+ "actions_in": [
+ {}
+ ],
+ "vars_out": [],
+ "actions_out": [
+ {
+ "jpath": []
+ }
+ ],
+ "toolbar": {
+ "custom": [
+ [
+ {
+ "title": "",
+ "icon": "",
+ "action": "",
+ "position": "begin",
+ "color": [
+ 100,
+ 100,
+ 100,
+ 1
+ ]
+ }
+ ]
+ ],
+ "common": [
+ {
+ "toolbar": [
+ [
+ "Open Preferences"
+ ]
+ ]
+ }
+ ]
+ },
+ "css": [
+ {
+ "fontSize": [
+ ""
+ ],
+ "fontFamily": [
+ ""
+ ]
+ }
+ ],
+ "title": "smiles"
+ },
+ {
+ "url": "modules/types/client_interaction/code_editor/",
+ "configuration": {
+ "sections": {},
+ "groups": {
+ "group": [
+ {
+ "mode": [
+ "text"
+ ],
+ "outputType": [
+ null
+ ],
+ "btnvalue": [
+ "Reset reaction from RXN V2000"
+ ],
+ "iseditable": [
+ [
+ "editable"
+ ]
+ ],
+ "hasButton": [
+ [
+ "button"
+ ]
+ ],
+ "variable": [
+ []
+ ],
+ "storeOnChange": [
+ []
+ ],
+ "debouncing": [
+ 0
+ ],
+ "script": [
+ "$RXN\n\n\nOCL_RXN_V1.0:gC``Adij@@!gFp@DiTvjh@##!R@Fq?[@@SGSJR !R?g~w@k_}m?vw@auZH`##\n 1 1\n$MOL\n\nActelion Java MolfileCreator 1.0\n\n 4 3 0 0 0 0 0 0 0 0999 V2000\n 12.3861 -10.2083 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 11.5201 -10.7083 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n 10.6541 -10.2083 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 9.7880 -10.7083 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n 1 2 1 0 0 0 0\n 2 3 1 0 0 0 0\n 3 4 1 0 0 0 0\nM END\n$MOL\n\nActelion Java MolfileCreator 1.0\n\n 6 6 0 0 0 0 0 0 0 0999 V2000\n 18.6250 -9.0833 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 18.6250 -10.0833 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 19.4910 -10.5833 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 20.3571 -10.0833 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 20.3571 -9.0833 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 19.4910 -8.5833 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 1 2 1 0 0 0 0\n 2 3 1 0 0 0 0\n 3 4 1 0 0 0 0\n 4 5 1 0 0 0 0\n 5 6 1 0 0 0 0\n 6 1 1 0 0 0 0\nM END\n"
+ ]
+ }
+ ],
+ "ace": [
+ {
+ "useSoftTabs": [
+ [
+ "yes"
+ ]
+ ],
+ "tabSize": [
+ 4
+ ]
+ }
+ ]
+ }
+ },
+ "layers": {
+ "Default layer": {
+ "position": {
+ "left": 0,
+ "top": 20
+ },
+ "size": {
+ "width": 39,
+ "height": 19
+ },
+ "zIndex": 0,
+ "display": true,
+ "title": "",
+ "bgColor": [
+ 255,
+ 255,
+ 255,
+ 0
+ ],
+ "wrapper": true,
+ "created": true,
+ "name": "Default layer"
+ }
+ },
+ "id": 4,
+ "vars_in": [
+ {}
+ ],
+ "actions_in": [
+ {}
+ ],
+ "vars_out": [
+ {
+ "event": "onButtonClick",
+ "rel": "data",
+ "jpath": [],
+ "name": "rxnV2000"
+ }
+ ],
+ "actions_out": [
+ {
+ "jpath": []
+ }
+ ],
+ "toolbar": {
+ "custom": [
+ [
+ {
+ "title": "",
+ "icon": "",
+ "action": "",
+ "position": "begin",
+ "color": [
+ 100,
+ 100,
+ 100,
+ 1
+ ]
+ }
+ ]
+ ],
+ "common": [
+ {
+ "toolbar": [
+ [
+ "Open Preferences"
+ ]
+ ]
+ }
+ ]
+ },
+ "css": [
+ {
+ "fontSize": [
+ ""
+ ],
+ "fontFamily": [
+ ""
+ ]
+ }
+ ],
+ "title": ""
+ },
+ {
+ "url": "modules/types/client_interaction/code_editor/",
+ "configuration": {
+ "sections": {},
+ "groups": {
+ "group": [
+ {
+ "mode": [
+ "text"
+ ],
+ "outputType": [
+ null
+ ],
+ "btnvalue": [
+ "Send script"
+ ],
+ "iseditable": [
+ [
+ "editable"
+ ]
+ ],
+ "hasButton": [
+ []
+ ],
+ "variable": [
+ []
+ ],
+ "storeOnChange": [
+ []
+ ],
+ "debouncing": [
+ 0
+ ],
+ "script": [
+ null
+ ]
+ }
+ ],
+ "ace": [
+ {
+ "useSoftTabs": [
+ [
+ "yes"
+ ]
+ ],
+ "tabSize": [
+ 4
+ ]
+ }
+ ]
+ }
+ },
+ "layers": {
+ "Default layer": {
+ "position": {
+ "left": 100,
+ "top": 9
+ },
+ "size": {
+ "width": 53,
+ "height": 27
+ },
+ "zIndex": 0,
+ "display": true,
+ "title": "rxnV2000",
+ "bgColor": [
+ 255,
+ 255,
+ 255,
+ 0
+ ],
+ "wrapper": true,
+ "created": true,
+ "name": "Default layer"
+ }
+ },
+ "id": 5,
+ "vars_in": [
+ {
+ "rel": "data",
+ "name": "rxnV2000"
+ }
+ ],
+ "actions_in": [
+ {}
+ ],
+ "vars_out": [
+ {
+ "jpath": []
+ }
+ ],
+ "actions_out": [
+ {
+ "jpath": []
+ }
+ ],
+ "toolbar": {
+ "custom": [
+ [
+ {
+ "title": "",
+ "icon": "",
+ "action": "",
+ "position": "begin",
+ "color": [
+ 100,
+ 100,
+ 100,
+ 1
+ ]
+ }
+ ]
+ ],
+ "common": [
+ {
+ "toolbar": [
+ [
+ "Open Preferences"
+ ]
+ ]
+ }
+ ]
+ },
+ "css": [
+ {
+ "fontSize": [
+ ""
+ ],
+ "fontFamily": [
+ ""
+ ]
+ }
+ ],
+ "title": "rxnV2000"
+ },
+ {
+ "url": "modules/types/client_interaction/code_editor/",
+ "configuration": {
+ "sections": {},
+ "groups": {
+ "group": [
+ {
+ "mode": [
+ "text"
+ ],
+ "outputType": [
+ null
+ ],
+ "btnvalue": [
+ "Send script"
+ ],
+ "iseditable": [
+ [
+ "editable"
+ ]
+ ],
+ "hasButton": [
+ []
+ ],
+ "variable": [
+ []
+ ],
+ "storeOnChange": [
+ []
+ ],
+ "debouncing": [
+ 0
+ ],
+ "script": [
+ null
+ ]
+ }
+ ],
+ "ace": [
+ {
+ "useSoftTabs": [
+ [
+ "yes"
+ ]
+ ],
+ "tabSize": [
+ 4
+ ]
+ }
+ ]
+ }
+ },
+ "layers": {
+ "Default layer": {
+ "position": {
+ "left": 100,
+ "top": 37
+ },
+ "size": {
+ "width": 53,
+ "height": 27
+ },
+ "zIndex": 0,
+ "display": true,
+ "title": "rxnV3000",
+ "bgColor": [
+ 255,
+ 255,
+ 255,
+ 0
+ ],
+ "wrapper": true,
+ "created": true,
+ "name": "Default layer"
+ }
+ },
+ "id": 6,
+ "vars_in": [
+ {
+ "rel": "data",
+ "name": "rxnV3000"
+ }
+ ],
+ "actions_in": [
+ {}
+ ],
+ "vars_out": [
+ {
+ "jpath": []
+ }
+ ],
+ "actions_out": [
+ {
+ "jpath": []
+ }
+ ],
+ "toolbar": {
+ "custom": [
+ [
+ {
+ "title": "",
+ "icon": "",
+ "action": "",
+ "position": "begin",
+ "color": [
+ 100,
+ 100,
+ 100,
+ 1
+ ]
+ }
+ ]
+ ],
+ "common": [
+ {
+ "toolbar": [
+ [
+ "Open Preferences"
+ ]
+ ]
+ }
+ ]
+ },
+ "css": [
+ {
+ "fontSize": [
+ ""
+ ],
+ "fontFamily": [
+ ""
+ ]
+ }
+ ],
+ "title": "rxnV3000"
+ },
+ {
+ "url": "modules/types/client_interaction/code_editor/",
+ "configuration": {
+ "sections": {},
+ "groups": {
+ "group": [
+ {
+ "mode": [
+ "text"
+ ],
+ "outputType": [
+ null
+ ],
+ "btnvalue": [
+ "Reset reaction from RXN V3000"
+ ],
+ "iseditable": [
+ [
+ "editable"
+ ]
+ ],
+ "hasButton": [
+ [
+ "button"
+ ]
+ ],
+ "variable": [
+ []
+ ],
+ "storeOnChange": [
+ []
+ ],
+ "debouncing": [
+ 0
+ ],
+ "script": [
+ "$RXN\n\n\nOCL_RXN_V1.0:gC``Adij@@!gFp@DiTvjh@##!R@Fq?[@@SGSJR !R?g~w@k_}m?vw@auZH`##\n 1 1\n$MOL\n\nActelion Java MolfileCreator 1.0\n\n 4 3 0 0 0 0 0 0 0 0999 V2000\n 12.3861 -10.2083 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 11.5201 -10.7083 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n 10.6541 -10.2083 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 9.7880 -10.7083 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n 1 2 1 0 0 0 0\n 2 3 1 0 0 0 0\n 3 4 1 0 0 0 0\nM END\n$MOL\n\nActelion Java MolfileCreator 1.0\n\n 6 6 0 0 0 0 0 0 0 0999 V2000\n 18.6250 -9.0833 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 18.6250 -10.0833 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 19.4910 -10.5833 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 20.3571 -10.0833 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 20.3571 -9.0833 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 19.4910 -8.5833 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 1 2 1 0 0 0 0\n 2 3 1 0 0 0 0\n 3 4 1 0 0 0 0\n 4 5 1 0 0 0 0\n 5 6 1 0 0 0 0\n 6 1 1 0 0 0 0\nM END\n"
+ ]
+ }
+ ],
+ "ace": [
+ {
+ "useSoftTabs": [
+ [
+ "yes"
+ ]
+ ],
+ "tabSize": [
+ 4
+ ]
+ }
+ ]
+ }
+ },
+ "layers": {
+ "Default layer": {
+ "position": {
+ "left": 0,
+ "top": 40
+ },
+ "size": {
+ "width": 39,
+ "height": 40
+ },
+ "zIndex": 0,
+ "display": true,
+ "title": "We pretend it is a V3000 but in fact we check in place modification",
+ "bgColor": [
+ 255,
+ 255,
+ 255,
+ 0
+ ],
+ "wrapper": true,
+ "created": true,
+ "name": "Default layer"
+ }
+ },
+ "id": 7,
+ "vars_in": [
+ {}
+ ],
+ "actions_in": [
+ {}
+ ],
+ "vars_out": [
+ {
+ "event": "onButtonClick",
+ "rel": "data",
+ "jpath": [],
+ "name": "rxnV3000"
+ }
+ ],
+ "actions_out": [
+ {
+ "jpath": []
+ }
+ ],
+ "toolbar": {
+ "custom": [
+ [
+ {
+ "title": "",
+ "icon": "",
+ "action": "",
+ "position": "begin",
+ "color": [
+ 100,
+ 100,
+ 100,
+ 1
+ ]
+ }
+ ]
+ ],
+ "common": [
+ {
+ "toolbar": [
+ [
+ "Open Preferences"
+ ]
+ ]
+ }
+ ]
+ },
+ "css": [
+ {
+ "fontSize": [
+ ""
+ ],
+ "fontFamily": [
+ ""
+ ]
+ }
+ ],
+ "title": "We pretend it is a V3000 but in fact we check in place modification"
+ }
+ ],
+ "variables": [],
+ "aliases": [],
+ "configuration": {
+ "title": "No title"
+ }
+}
\ No newline at end of file
diff --git a/testcase/data/openchemlib-reaction/data.json b/testcase/data/openchemlib-reaction/data.json
new file mode 100644
index 000000000..9e26dfeeb
--- /dev/null
+++ b/testcase/data/openchemlib-reaction/data.json
@@ -0,0 +1 @@
+{}
\ No newline at end of file
diff --git a/testcase/data/openchemlib-reaction/view.json b/testcase/data/openchemlib-reaction/view.json
new file mode 100644
index 000000000..3e20df1ac
--- /dev/null
+++ b/testcase/data/openchemlib-reaction/view.json
@@ -0,0 +1,1542 @@
+{
+ "version": "2.173.4-0",
+ "grid": {
+ "layers": {
+ "Default layer": {
+ "name": "Default layer"
+ }
+ },
+ "xWidth": 10,
+ "yHeight": 10
+ },
+ "modules": [
+ {
+ "url": "modules/types/science/chemistry/ocl_reaction_editor/",
+ "configuration": {
+ "sections": {},
+ "groups": {
+ "group": [
+ {
+ "prefs": [
+ []
+ ]
+ }
+ ]
+ }
+ },
+ "layers": {
+ "Default layer": {
+ "position": {
+ "left": 31,
+ "top": 0
+ },
+ "size": {
+ "width": 63,
+ "height": 54
+ },
+ "zIndex": 0,
+ "display": true,
+ "title": "",
+ "bgColor": [
+ 255,
+ 255,
+ 255,
+ 0
+ ],
+ "wrapper": true,
+ "created": true,
+ "name": "Default layer"
+ }
+ },
+ "id": 1,
+ "vars_in": [
+ {
+ "rel": "rxn",
+ "name": "rxnIn"
+ },
+ {
+ "rel": "rxnV3",
+ "name": "rxnV3In"
+ },
+ {
+ "rel": "smiles",
+ "name": "smilesIn"
+ },
+ {
+ "rel": "reactionIdCode",
+ "name": "idCodeIn"
+ }
+ ],
+ "actions_in": [
+ {
+ "rel": "addReactant",
+ "name": "addReactant"
+ },
+ {
+ "rel": "addProduct",
+ "name": "addProduct"
+ }
+ ],
+ "vars_out": [
+ {
+ "event": "onReactionChange",
+ "rel": "rxn",
+ "jpath": [],
+ "name": "rxnOut"
+ },
+ {
+ "event": "onReactionChange",
+ "rel": "rxnV3",
+ "jpath": [],
+ "name": "rxnV3Out"
+ },
+ {
+ "event": "onReactionChange",
+ "rel": "smiles",
+ "jpath": [],
+ "name": "smilesOut"
+ },
+ {
+ "event": "onReactionChange",
+ "rel": "reactionIdCode",
+ "jpath": [],
+ "name": "idCodeOut"
+ }
+ ],
+ "actions_out": [
+ {
+ "jpath": []
+ }
+ ],
+ "toolbar": {
+ "custom": [
+ [
+ {
+ "title": "",
+ "icon": "",
+ "action": "",
+ "position": "begin",
+ "color": [
+ 100,
+ 100,
+ 100,
+ 1
+ ]
+ }
+ ]
+ ],
+ "common": [
+ {
+ "toolbar": [
+ [
+ "Open Preferences"
+ ]
+ ]
+ }
+ ]
+ },
+ "css": [
+ {
+ "fontSize": [
+ ""
+ ],
+ "fontFamily": [
+ ""
+ ]
+ }
+ ],
+ "title": ""
+ },
+ {
+ "url": "modules/types/client_interaction/code_editor/",
+ "configuration": {
+ "sections": {},
+ "groups": {
+ "group": [
+ {
+ "mode": [
+ "text"
+ ],
+ "outputType": [
+ null
+ ],
+ "btnvalue": [
+ "Add reactant"
+ ],
+ "iseditable": [
+ [
+ "editable"
+ ]
+ ],
+ "hasButton": [
+ [
+ "button"
+ ]
+ ],
+ "variable": [
+ []
+ ],
+ "storeOnChange": [
+ []
+ ],
+ "debouncing": [
+ 0
+ ],
+ "script": [
+ "COCO"
+ ]
+ }
+ ],
+ "ace": [
+ {
+ "useSoftTabs": [
+ [
+ "yes"
+ ]
+ ],
+ "tabSize": [
+ 4
+ ]
+ }
+ ]
+ }
+ },
+ "layers": {
+ "Default layer": {
+ "position": {
+ "left": 0,
+ "top": 0
+ },
+ "size": {
+ "width": 31,
+ "height": 12
+ },
+ "zIndex": 0,
+ "display": true,
+ "title": "",
+ "bgColor": [
+ 255,
+ 255,
+ 255,
+ 0
+ ],
+ "wrapper": true,
+ "created": true,
+ "name": "Default layer"
+ }
+ },
+ "id": 2,
+ "vars_in": [
+ {}
+ ],
+ "actions_in": [
+ {}
+ ],
+ "vars_out": [
+ {
+ "jpath": []
+ }
+ ],
+ "actions_out": [
+ {
+ "event": "onButtonClick",
+ "rel": "data",
+ "jpath": [],
+ "name": "addReactant"
+ }
+ ],
+ "toolbar": {
+ "custom": [
+ [
+ {
+ "title": "",
+ "icon": "",
+ "action": "",
+ "position": "begin",
+ "color": [
+ 100,
+ 100,
+ 100,
+ 1
+ ]
+ }
+ ]
+ ],
+ "common": [
+ {
+ "toolbar": [
+ [
+ "Open Preferences"
+ ]
+ ]
+ }
+ ]
+ },
+ "css": [
+ {
+ "fontSize": [
+ ""
+ ],
+ "fontFamily": [
+ ""
+ ]
+ }
+ ],
+ "title": ""
+ },
+ {
+ "url": "modules/types/client_interaction/code_editor/",
+ "configuration": {
+ "sections": {},
+ "groups": {
+ "group": [
+ {
+ "mode": [
+ "text"
+ ],
+ "outputType": [
+ null
+ ],
+ "btnvalue": [
+ "Add product"
+ ],
+ "iseditable": [
+ [
+ "editable"
+ ]
+ ],
+ "hasButton": [
+ [
+ "button"
+ ]
+ ],
+ "variable": [
+ []
+ ],
+ "storeOnChange": [
+ []
+ ],
+ "debouncing": [
+ 0
+ ],
+ "script": [
+ "COCO"
+ ]
+ }
+ ],
+ "ace": [
+ {
+ "useSoftTabs": [
+ [
+ "yes"
+ ]
+ ],
+ "tabSize": [
+ 4
+ ]
+ }
+ ]
+ }
+ },
+ "layers": {
+ "Default layer": {
+ "position": {
+ "left": 0,
+ "top": 12
+ },
+ "size": {
+ "width": 31,
+ "height": 12
+ },
+ "zIndex": 0,
+ "display": true,
+ "title": "",
+ "bgColor": [
+ 255,
+ 255,
+ 255,
+ 0
+ ],
+ "wrapper": true,
+ "created": true,
+ "name": "Default layer"
+ }
+ },
+ "id": 3,
+ "vars_in": [
+ {}
+ ],
+ "actions_in": [
+ {}
+ ],
+ "vars_out": [
+ {
+ "jpath": []
+ }
+ ],
+ "actions_out": [
+ {
+ "event": "onButtonClick",
+ "rel": "data",
+ "jpath": [],
+ "name": "addProduct"
+ }
+ ],
+ "toolbar": {
+ "custom": [
+ [
+ {
+ "title": "",
+ "icon": "",
+ "action": "",
+ "position": "begin",
+ "color": [
+ 100,
+ 100,
+ 100,
+ 1
+ ]
+ }
+ ]
+ ],
+ "common": [
+ {
+ "toolbar": [
+ [
+ "Open Preferences"
+ ]
+ ]
+ }
+ ]
+ },
+ "css": [
+ {
+ "fontSize": [
+ ""
+ ],
+ "fontFamily": [
+ ""
+ ]
+ }
+ ],
+ "title": ""
+ },
+ {
+ "url": "modules/types/client_interaction/code_editor/",
+ "configuration": {
+ "sections": {},
+ "groups": {
+ "group": [
+ {
+ "mode": [
+ "text"
+ ],
+ "outputType": [
+ null
+ ],
+ "btnvalue": [
+ "Set reaction from RXN V2000"
+ ],
+ "iseditable": [
+ [
+ "editable"
+ ]
+ ],
+ "hasButton": [
+ [
+ "button"
+ ]
+ ],
+ "variable": [
+ []
+ ],
+ "storeOnChange": [
+ []
+ ],
+ "debouncing": [
+ 0
+ ],
+ "script": [
+ "$RXN\n\n\nOCL_RXN_V1.0:gC``Adij@@!gFp@DiTvjh@##!R@Fq?[@@SGSJR !R?g~w@k_}m?vw@auZH`##\n 1 1\n$MOL\n\nActelion Java MolfileCreator 1.0\n\n 4 3 0 0 0 0 0 0 0 0999 V2000\n 12.3861 -10.2083 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 11.5201 -10.7083 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n 10.6541 -10.2083 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 9.7880 -10.7083 0.0000 O 0 0 0 0 0 0 0 0 0 0 0 0\n 1 2 1 0 0 0 0\n 2 3 1 0 0 0 0\n 3 4 1 0 0 0 0\nM END\n$MOL\n\nActelion Java MolfileCreator 1.0\n\n 6 6 0 0 0 0 0 0 0 0999 V2000\n 18.6250 -9.0833 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 18.6250 -10.0833 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 19.4910 -10.5833 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 20.3571 -10.0833 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 20.3571 -9.0833 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 19.4910 -8.5833 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0\n 1 2 1 0 0 0 0\n 2 3 1 0 0 0 0\n 3 4 1 0 0 0 0\n 4 5 1 0 0 0 0\n 5 6 1 0 0 0 0\n 6 1 1 0 0 0 0\nM END\n"
+ ]
+ }
+ ],
+ "ace": [
+ {
+ "useSoftTabs": [
+ [
+ "yes"
+ ]
+ ],
+ "tabSize": [
+ 4
+ ]
+ }
+ ]
+ }
+ },
+ "layers": {
+ "Default layer": {
+ "position": {
+ "left": 0,
+ "top": 24
+ },
+ "size": {
+ "width": 31,
+ "height": 16
+ },
+ "zIndex": 0,
+ "display": true,
+ "title": "",
+ "bgColor": [
+ 255,
+ 255,
+ 255,
+ 0
+ ],
+ "wrapper": true,
+ "created": true,
+ "name": "Default layer"
+ }
+ },
+ "id": 4,
+ "vars_in": [
+ {}
+ ],
+ "actions_in": [
+ {}
+ ],
+ "vars_out": [
+ {
+ "event": "onButtonClick",
+ "rel": "data",
+ "jpath": [],
+ "name": "rxnIn"
+ }
+ ],
+ "actions_out": [
+ {
+ "jpath": []
+ }
+ ],
+ "toolbar": {
+ "custom": [
+ [
+ {
+ "title": "",
+ "icon": "",
+ "action": "",
+ "position": "begin",
+ "color": [
+ 100,
+ 100,
+ 100,
+ 1
+ ]
+ }
+ ]
+ ],
+ "common": [
+ {
+ "toolbar": [
+ [
+ "Open Preferences"
+ ]
+ ]
+ }
+ ]
+ },
+ "css": [
+ {
+ "fontSize": [
+ ""
+ ],
+ "fontFamily": [
+ ""
+ ]
+ }
+ ],
+ "title": ""
+ },
+ {
+ "url": "modules/types/client_interaction/code_editor/",
+ "configuration": {
+ "sections": {},
+ "groups": {
+ "group": [
+ {
+ "mode": [
+ "text"
+ ],
+ "outputType": [
+ null
+ ],
+ "btnvalue": [
+ "Add product"
+ ],
+ "iseditable": [
+ [
+ "editable"
+ ]
+ ],
+ "hasButton": [
+ []
+ ],
+ "variable": [
+ []
+ ],
+ "storeOnChange": [
+ []
+ ],
+ "debouncing": [
+ 0
+ ],
+ "script": [
+ ""
+ ]
+ }
+ ],
+ "ace": [
+ {
+ "useSoftTabs": [
+ [
+ "yes"
+ ]
+ ],
+ "tabSize": [
+ 4
+ ]
+ }
+ ]
+ }
+ },
+ "layers": {
+ "Default layer": {
+ "position": {
+ "left": 94,
+ "top": 0
+ },
+ "size": {
+ "width": 42,
+ "height": 25
+ },
+ "zIndex": 0,
+ "display": true,
+ "title": "",
+ "bgColor": [
+ 255,
+ 255,
+ 255,
+ 0
+ ],
+ "wrapper": true,
+ "created": true,
+ "name": "Default layer"
+ }
+ },
+ "id": 5,
+ "vars_in": [
+ {
+ "rel": "data",
+ "name": "rxnOut"
+ }
+ ],
+ "actions_in": [
+ {}
+ ],
+ "vars_out": [
+ {
+ "event": "onButtonClick",
+ "rel": "data",
+ "jpath": [],
+ "name": "rxnv2000"
+ }
+ ],
+ "actions_out": [
+ {
+ "event": "onButtonClick",
+ "rel": "data",
+ "jpath": [],
+ "name": "addProduct"
+ }
+ ],
+ "toolbar": {
+ "custom": [
+ [
+ {
+ "title": "",
+ "icon": "",
+ "action": "",
+ "position": "begin",
+ "color": [
+ 100,
+ 100,
+ 100,
+ 1
+ ]
+ }
+ ]
+ ],
+ "common": [
+ {
+ "toolbar": [
+ [
+ "Open Preferences"
+ ]
+ ]
+ }
+ ]
+ },
+ "css": [
+ {
+ "fontSize": [
+ ""
+ ],
+ "fontFamily": [
+ ""
+ ]
+ }
+ ],
+ "title": ""
+ },
+ {
+ "url": "modules/types/client_interaction/code_editor/",
+ "configuration": {
+ "sections": {},
+ "groups": {
+ "group": [
+ {
+ "mode": [
+ "text"
+ ],
+ "outputType": [
+ null
+ ],
+ "btnvalue": [
+ "Add product"
+ ],
+ "iseditable": [
+ [
+ "editable"
+ ]
+ ],
+ "hasButton": [
+ []
+ ],
+ "variable": [
+ []
+ ],
+ "storeOnChange": [
+ []
+ ],
+ "debouncing": [
+ 0
+ ],
+ "script": [
+ ""
+ ]
+ }
+ ],
+ "ace": [
+ {
+ "useSoftTabs": [
+ [
+ "yes"
+ ]
+ ],
+ "tabSize": [
+ 4
+ ]
+ }
+ ]
+ }
+ },
+ "layers": {
+ "Default layer": {
+ "position": {
+ "left": 94,
+ "top": 25
+ },
+ "size": {
+ "width": 42,
+ "height": 25
+ },
+ "zIndex": 0,
+ "display": true,
+ "title": "",
+ "bgColor": [
+ 255,
+ 255,
+ 255,
+ 0
+ ],
+ "wrapper": true,
+ "created": true,
+ "name": "Default layer"
+ }
+ },
+ "id": 6,
+ "vars_in": [
+ {
+ "rel": "data",
+ "name": "rxnV3Out"
+ }
+ ],
+ "actions_in": [
+ {}
+ ],
+ "vars_out": [
+ {
+ "event": "onButtonClick",
+ "rel": "data",
+ "jpath": [],
+ "name": "rxnv2000"
+ }
+ ],
+ "actions_out": [
+ {
+ "event": "onButtonClick",
+ "rel": "data",
+ "jpath": [],
+ "name": "addProduct"
+ }
+ ],
+ "toolbar": {
+ "custom": [
+ [
+ {
+ "title": "",
+ "icon": "",
+ "action": "",
+ "position": "begin",
+ "color": [
+ 100,
+ 100,
+ 100,
+ 1
+ ]
+ }
+ ]
+ ],
+ "common": [
+ {
+ "toolbar": [
+ [
+ "Open Preferences"
+ ]
+ ]
+ }
+ ]
+ },
+ "css": [
+ {
+ "fontSize": [
+ ""
+ ],
+ "fontFamily": [
+ ""
+ ]
+ }
+ ],
+ "title": ""
+ },
+ {
+ "url": "modules/types/client_interaction/code_editor/",
+ "configuration": {
+ "sections": {},
+ "groups": {
+ "group": [
+ {
+ "mode": [
+ "text"
+ ],
+ "outputType": [
+ null
+ ],
+ "btnvalue": [
+ "Add product"
+ ],
+ "iseditable": [
+ [
+ "editable"
+ ]
+ ],
+ "hasButton": [
+ []
+ ],
+ "variable": [
+ []
+ ],
+ "storeOnChange": [
+ []
+ ],
+ "debouncing": [
+ 0
+ ],
+ "script": [
+ ""
+ ]
+ }
+ ],
+ "ace": [
+ {
+ "useSoftTabs": [
+ [
+ "yes"
+ ]
+ ],
+ "tabSize": [
+ 4
+ ]
+ }
+ ]
+ }
+ },
+ "layers": {
+ "Default layer": {
+ "position": {
+ "left": 94,
+ "top": 50
+ },
+ "size": {
+ "width": 42,
+ "height": 7
+ },
+ "zIndex": 0,
+ "display": true,
+ "title": "",
+ "bgColor": [
+ 255,
+ 255,
+ 255,
+ 0
+ ],
+ "wrapper": true,
+ "created": true,
+ "name": "Default layer"
+ }
+ },
+ "id": 7,
+ "vars_in": [
+ {
+ "rel": "data",
+ "name": "smilesOut"
+ }
+ ],
+ "actions_in": [
+ {}
+ ],
+ "vars_out": [
+ {
+ "event": "onButtonClick",
+ "rel": "data",
+ "jpath": [],
+ "name": "rxnv2000"
+ }
+ ],
+ "actions_out": [
+ {
+ "event": "onButtonClick",
+ "rel": "data",
+ "jpath": [],
+ "name": "addProduct"
+ }
+ ],
+ "toolbar": {
+ "custom": [
+ [
+ {
+ "title": "",
+ "icon": "",
+ "action": "",
+ "position": "begin",
+ "color": [
+ 100,
+ 100,
+ 100,
+ 1
+ ]
+ }
+ ]
+ ],
+ "common": [
+ {
+ "toolbar": [
+ [
+ "Open Preferences"
+ ]
+ ]
+ }
+ ]
+ },
+ "css": [
+ {
+ "fontSize": [
+ ""
+ ],
+ "fontFamily": [
+ ""
+ ]
+ }
+ ],
+ "title": ""
+ },
+ {
+ "url": "modules/types/client_interaction/code_editor/",
+ "configuration": {
+ "sections": {},
+ "groups": {
+ "group": [
+ {
+ "mode": [
+ "text"
+ ],
+ "outputType": [
+ null
+ ],
+ "btnvalue": [
+ "Add product"
+ ],
+ "iseditable": [
+ [
+ "editable"
+ ]
+ ],
+ "hasButton": [
+ []
+ ],
+ "variable": [
+ []
+ ],
+ "storeOnChange": [
+ []
+ ],
+ "debouncing": [
+ 0
+ ],
+ "script": [
+ ""
+ ]
+ }
+ ],
+ "ace": [
+ {
+ "useSoftTabs": [
+ [
+ "yes"
+ ]
+ ],
+ "tabSize": [
+ 4
+ ]
+ }
+ ]
+ }
+ },
+ "layers": {
+ "Default layer": {
+ "position": {
+ "left": 94,
+ "top": 57
+ },
+ "size": {
+ "width": 42,
+ "height": 7
+ },
+ "zIndex": 0,
+ "display": true,
+ "title": "",
+ "bgColor": [
+ 255,
+ 255,
+ 255,
+ 0
+ ],
+ "wrapper": true,
+ "created": true,
+ "name": "Default layer"
+ }
+ },
+ "id": 8,
+ "vars_in": [
+ {
+ "rel": "data",
+ "name": "idCodeOut"
+ }
+ ],
+ "actions_in": [
+ {}
+ ],
+ "vars_out": [
+ {
+ "event": "onButtonClick",
+ "rel": "data",
+ "jpath": [],
+ "name": "rxnv2000"
+ }
+ ],
+ "actions_out": [
+ {
+ "event": "onButtonClick",
+ "rel": "data",
+ "jpath": [],
+ "name": "addProduct"
+ }
+ ],
+ "toolbar": {
+ "custom": [
+ [
+ {
+ "title": "",
+ "icon": "",
+ "action": "",
+ "position": "begin",
+ "color": [
+ 100,
+ 100,
+ 100,
+ 1
+ ]
+ }
+ ]
+ ],
+ "common": [
+ {
+ "toolbar": [
+ [
+ "Open Preferences"
+ ]
+ ]
+ }
+ ]
+ },
+ "css": [
+ {
+ "fontSize": [
+ ""
+ ],
+ "fontFamily": [
+ ""
+ ]
+ }
+ ],
+ "title": ""
+ },
+ {
+ "url": "modules/types/client_interaction/code_editor/",
+ "configuration": {
+ "sections": {},
+ "groups": {
+ "group": [
+ {
+ "mode": [
+ "text"
+ ],
+ "outputType": [
+ null
+ ],
+ "btnvalue": [
+ "Set reaction from RXN V3000"
+ ],
+ "iseditable": [
+ [
+ "editable"
+ ]
+ ],
+ "hasButton": [
+ [
+ "button"
+ ]
+ ],
+ "variable": [
+ []
+ ],
+ "storeOnChange": [
+ []
+ ],
+ "debouncing": [
+ 0
+ ],
+ "script": [
+ "$RXN V3000\n\n\nOCL_RXN_V1.0:gFp@DiTt@@@!daD@@DjUZxHH@@##!R?g~w@k_}m?vw@aw|T` !Rb@K~_{\\BbOvH?[]}?g|]FiH##\nM V30 COUNTS 1 1\nM V30 BEGIN REACTANT\nM V30 BEGIN CTAB\nM V30 COUNTS 6 6 0 0 0\nM V30 BEGIN ATOM\nM V30 1 C 7.6666 -10.8333 0 0\nM V30 2 C 7.6666 -11.8333 0 0\nM V30 3 C 8.5326 -12.3333 0 0\nM V30 4 C 9.3987 -11.8333 0 0\nM V30 5 C 9.3987 -10.8333 0 0\nM V30 6 C 8.5326 -10.3333 0 0\nM V30 END ATOM\nM V30 BEGIN BOND\nM V30 1 2 1 2\nM V30 2 1 2 3\nM V30 3 2 3 4\nM V30 4 1 4 5\nM V30 5 2 5 6\nM V30 6 1 6 1\nM V30 END BOND\nM V30 END CTAB\nM V30 END REACTANT\nM V30 BEGIN PRODUCT\nM V30 BEGIN CTAB\nM V30 COUNTS 8 8 0 0 0\nM V30 BEGIN ATOM\nM V30 1 C 15.6666 -10.5416 0 0\nM V30 2 C 15.6666 -11.5416 0 0\nM V30 3 C 16.5326 -12.0416 0 0\nM V30 4 C 17.3987 -11.5416 0 0\nM V30 5 C 17.3987 -10.5416 0 0\nM V30 6 C 16.5326 -10.0416 0 0\nM V30 7 C 18.2647 -10.0416 0 0\nM V30 8 C 19.1307 -10.5416 0 0\nM V30 END ATOM\nM V30 BEGIN BOND\nM V30 1 2 1 2\nM V30 2 1 2 3\nM V30 3 2 3 4\nM V30 4 1 4 5\nM V30 5 2 5 6\nM V30 6 1 6 1\nM V30 7 1 5 7\nM V30 8 1 7 8\nM V30 END BOND\nM V30 END CTAB\nM V30 END PRODUCT\nM END\n"
+ ]
+ }
+ ],
+ "ace": [
+ {
+ "useSoftTabs": [
+ [
+ "yes"
+ ]
+ ],
+ "tabSize": [
+ 4
+ ]
+ }
+ ]
+ }
+ },
+ "layers": {
+ "Default layer": {
+ "position": {
+ "left": 0,
+ "top": 40
+ },
+ "size": {
+ "width": 31,
+ "height": 16
+ },
+ "zIndex": 0,
+ "display": true,
+ "title": "",
+ "bgColor": [
+ 255,
+ 255,
+ 255,
+ 0
+ ],
+ "wrapper": true,
+ "created": true,
+ "name": "Default layer"
+ }
+ },
+ "id": 9,
+ "vars_in": [
+ {}
+ ],
+ "actions_in": [
+ {}
+ ],
+ "vars_out": [
+ {
+ "event": "onButtonClick",
+ "rel": "data",
+ "jpath": [],
+ "name": "rxnV3In"
+ }
+ ],
+ "actions_out": [
+ {
+ "jpath": []
+ }
+ ],
+ "toolbar": {
+ "custom": [
+ [
+ {
+ "title": "",
+ "icon": "",
+ "action": "",
+ "position": "begin",
+ "color": [
+ 100,
+ 100,
+ 100,
+ 1
+ ]
+ }
+ ]
+ ],
+ "common": [
+ {
+ "toolbar": [
+ [
+ "Open Preferences"
+ ]
+ ]
+ }
+ ]
+ },
+ "css": [
+ {
+ "fontSize": [
+ ""
+ ],
+ "fontFamily": [
+ ""
+ ]
+ }
+ ],
+ "title": ""
+ },
+ {
+ "url": "modules/types/client_interaction/code_editor/",
+ "configuration": {
+ "sections": {},
+ "groups": {
+ "group": [
+ {
+ "mode": [
+ "text"
+ ],
+ "outputType": [
+ null
+ ],
+ "btnvalue": [
+ "Set reaction from SMILES"
+ ],
+ "iseditable": [
+ [
+ "editable"
+ ]
+ ],
+ "hasButton": [
+ [
+ "button"
+ ]
+ ],
+ "variable": [
+ []
+ ],
+ "storeOnChange": [
+ []
+ ],
+ "debouncing": [
+ 0
+ ],
+ "script": [
+ "C1CCPCCC1>>CC(C)O"
+ ]
+ }
+ ],
+ "ace": [
+ {
+ "useSoftTabs": [
+ [
+ "yes"
+ ]
+ ],
+ "tabSize": [
+ 4
+ ]
+ }
+ ]
+ }
+ },
+ "layers": {
+ "Default layer": {
+ "position": {
+ "left": 0,
+ "top": 56
+ },
+ "size": {
+ "width": 31,
+ "height": 9
+ },
+ "zIndex": 0,
+ "display": true,
+ "title": "",
+ "bgColor": [
+ 255,
+ 255,
+ 255,
+ 0
+ ],
+ "wrapper": true,
+ "created": true,
+ "name": "Default layer"
+ }
+ },
+ "id": 10,
+ "vars_in": [
+ {}
+ ],
+ "actions_in": [
+ {}
+ ],
+ "vars_out": [
+ {
+ "event": "onButtonClick",
+ "rel": "data",
+ "jpath": [],
+ "name": "smilesIn"
+ }
+ ],
+ "actions_out": [
+ {
+ "jpath": []
+ }
+ ],
+ "toolbar": {
+ "custom": [
+ [
+ {
+ "title": "",
+ "icon": "",
+ "action": "",
+ "position": "begin",
+ "color": [
+ 100,
+ 100,
+ 100,
+ 1
+ ]
+ }
+ ]
+ ],
+ "common": [
+ {
+ "toolbar": [
+ [
+ "Open Preferences"
+ ]
+ ]
+ }
+ ]
+ },
+ "css": [
+ {
+ "fontSize": [
+ ""
+ ],
+ "fontFamily": [
+ ""
+ ]
+ }
+ ],
+ "title": ""
+ },
+ {
+ "url": "modules/types/client_interaction/code_editor/",
+ "configuration": {
+ "sections": {},
+ "groups": {
+ "group": [
+ {
+ "mode": [
+ "text"
+ ],
+ "outputType": [
+ null
+ ],
+ "btnvalue": [
+ "Set reaction from ID code"
+ ],
+ "iseditable": [
+ [
+ "editable"
+ ]
+ ],
+ "hasButton": [
+ [
+ "button"
+ ]
+ ],
+ "variable": [
+ []
+ ],
+ "storeOnChange": [
+ []
+ ],
+ "debouncing": [
+ 0
+ ],
+ "script": [
+ "dcl@@DjYU_egX@@@@@@!dml@@DjYeR[aeZjjjh@@ diT@@DjeVfxZjjh@@##!B?g~H@k\\BbOvw?_x@?`C~_?y?mpJw?P !BTv]SFF@ZGqk~_q}eKAc~@EMgGvT !BXAiSFBqgGvW~@BpXTv_~_p"
+ ]
+ }
+ ],
+ "ace": [
+ {
+ "useSoftTabs": [
+ [
+ "yes"
+ ]
+ ],
+ "tabSize": [
+ 4
+ ]
+ }
+ ]
+ }
+ },
+ "layers": {
+ "Default layer": {
+ "position": {
+ "left": 0,
+ "top": 65
+ },
+ "size": {
+ "width": 31,
+ "height": 9
+ },
+ "zIndex": 0,
+ "display": true,
+ "title": "",
+ "bgColor": [
+ 255,
+ 255,
+ 255,
+ 0
+ ],
+ "wrapper": true,
+ "created": true,
+ "name": "Default layer"
+ }
+ },
+ "id": 11,
+ "vars_in": [
+ {}
+ ],
+ "actions_in": [
+ {}
+ ],
+ "vars_out": [
+ {
+ "event": "onButtonClick",
+ "rel": "data",
+ "jpath": [],
+ "name": "idCodeIn"
+ }
+ ],
+ "actions_out": [
+ {
+ "jpath": []
+ }
+ ],
+ "toolbar": {
+ "custom": [
+ [
+ {
+ "title": "",
+ "icon": "",
+ "action": "",
+ "position": "begin",
+ "color": [
+ 100,
+ 100,
+ 100,
+ 1
+ ]
+ }
+ ]
+ ],
+ "common": [
+ {
+ "toolbar": [
+ [
+ "Open Preferences"
+ ]
+ ]
+ }
+ ]
+ },
+ "css": [
+ {
+ "fontSize": [
+ ""
+ ],
+ "fontFamily": [
+ ""
+ ]
+ }
+ ],
+ "title": ""
+ }
+ ],
+ "variables": [],
+ "aliases": [],
+ "configuration": {
+ "title": "No title"
+ }
+}
\ No newline at end of file
diff --git a/testcase/index.html b/testcase/index.html
index b0279c7d7..6f5d2d991 100644
--- a/testcase/index.html
+++ b/testcase/index.html
@@ -100,11 +100,19 @@
{ description: 'Property explorer', folder: 'OCL_Explorer' },
{ description: 'OCL table', folder: 'ocl_list' },
{ description: 'OCL idCode editor', folder: 'ocl_edit_idcode' },
- { description: 'Openchemlib editor', folder: 'openchemlib-editor' },
+ { description: 'OpenChemlib editor', folder: 'openchemlib-editor' },
{
- description: 'Openchemlib export buttons',
+ description: 'OpenChemlib export buttons',
folder: 'openchemlib-export',
},
+ {
+ description: 'OpenChemlib reaction editor',
+ folder: 'openchemlib-reaction',
+ },
+ {
+ description: 'OpenChemlib reaction in-place editor',
+ folder: 'openchemlib-reaction-inplace',
+ },
],
'Client interaction': [
{ description: 'Drag and drop / paste', folder: 'dragdrop' },