ExportStructure from multiple marvinSketcherInstance

User 646de8ab9c

21-01-2015 16:28:21

Hi,


 


I have multiple marvinSketcherInstances in a single html page. And I want to export the structures of all the instances through an hidden element of a form.


First I tried this:


function initControl () {
        $("#btn-valid").on("click", function (e) {
                marvinSketcherInstance[0].exportStructure("mol").then(function(source) {
                    document.getElementById('entree1').value=source;
                }, function(error) {
                    alert("Molecule export failed:"+error);    
                });
                marvinSketcherInstance[1].exportStructure("mol").then(function(source) {
                    document.getElementById('entree2').value=source;
                }, function(error) {
                    alert("Molecule export failed:"+error);    
                });
                submitform();
        });
 }

This is not working. Only one element is completed.


Finally, after one day of working on, I find this solution: add setTimeout around the submitform function to wait that all the element are completed.


function initControl () {
        $("#btn-valid").on("click", function (e) {
                marvinSketcherInstance[0].exportStructure("mol").then(function(source) {
                    document.getElementById('entree1').value=source;
                }, function(error) {
                    alert("Molecule export failed:"+error);    
                });
                marvinSketcherInstance[1].exportStructure("mol").then(function(source) {
                    document.getElementById('entree2').value=source;
                }, function(error) {
                    alert("Molecule export failed:"+error);    
                });
            setTimeout(function(){
                submitform();
            }, 500);    
        });
 }

 


And now and tried to work with loops in order to work with more than 2 instances. I can initialize the instances whitout any problem, BUT I tried to used a "for" loop to export the structures and complete the elements whitout success:


function initControl () {
        $("#btn-valid").on("click", function (e) {  
            for (i = 0; i < currCible; i++) {
                var j = i + 1;
                var entree = "entree"+j;
                marvinSketcherInstance.exportStructure("mol").then(function(source) {
                    document.getElementById(entree).value=source;
                }, function(error) {
                    alert("Molecule export failed:"+error);    
                });
            }
            setTimeout(function(){
                submitform();
            }, 500);
        });
    }

Here only the second element is completed.


A solution?


And why do I need to put "wait" function ?


Lionel

ChemAxon 7c2d26e5cf

28-01-2015 18:11:10

You can retrieve editor content only asynchronous way.


marvinSketcherInstance.exportStructure("mol") returns with a Promise object.


In the then function of the Promise object you can specify what should happen when result of the exportStructure request received.


The Promise.then(...) statement does not wait till the molecule sources receive.


I guess that setTimeOut is not the best way to resolve this synchronization problem.


If I were you, I would trigger events in the callback functions. By defining a new event handler you can catch these events. I would launch the submitform() function after all expected events are received.

User 646de8ab9c

29-01-2015 11:13:16

Thanks Tamas for your answer.


I understand that setTimeOut is not the best method but I only found this to identify and correct my problem.


I am not an expert in javascript thus I am no sure to understand your solution but I will try to modify my code.

ChemAxon 7c2d26e5cf

29-01-2015 17:51:04

If you have only 2 sketchers, I guess it is the simplest way to serialize the requests.


function initControl () {
  $("#btn-valid").on("click", function (e) {
    marvinSketcherInstance[0].exportStructure("mol").then(function(source) {
      document.getElementById('entree1').value=source;
     
// retrieve 2nd mol after the first one received
      marvinSketcherInstance[1].exportStructure("mol").then(function(source) {
        document.getElementById('entree2').value=source;
       
// submit the form after 2nd mol received
        submitform();
      }, function(error) {
        alert("First molecule export failed:"+error);
      });
    }, function(error) {
      alert("Second molecule export failed:"+error);
    });
  });
}


To tell the truth, I am curious why more than one sketcher is required on a web page.

User 646de8ab9c

30-01-2015 08:45:46

Yes, I understand your solution but I am not sure that it i the best solution, I will explain why:


My company receive "demands for products and/or projects". Thus in these demands you have the name of the customer (name, address, etc...), the date of the demand and the list of the compounds the customer asked for. Importantly, each demand can be composed of no compounds, 1 compound or many compounds.


We want to register independently each asked compounds and link them to the demand.


The first solution is to register the demand through a first form, and then to register each compounds one by one through another form (for one compound). I did it and it work BUT it is not friendly user. 


I tried to build a single form where the user can: 1- register the demand, and 2- register many compounds. Thus the new form is composed of a fixed part for the demand details, and then a button that can add to the form a subpart for adding a compound (with its structure through a marvin applet). If the user hit again the button, a second subpart will appear for adding a second compound, etc... That is why I can have many marvin applets in one form (HTML page).


 


In conclusion, I do know only when the user valid the form, how many compounds have been drawn / how many marvin applet have been initialized. That is why I tried to use a "for" loop, and that is why your solution will not work for me (because you have to fix at the beginning how many applets you have).


For the moment my solution is to limit the maximum of applet the user can create in the form (5 or 10), and then in the ' $("btn-valid").on("click", function (e) { ', to enclose each potential marvin applet in a "if  exist" loop to export the structures but still with the submitform function enclose in the SetTimeout function.


 


Here after my current code with a maximum of 5 marvin applet and with the var "currCible" that contain the number of opened marvin applets:


function initControl () {
        $("#btn-valid").on("click", function (e) {
            if (currCible > 0) {
                marvinSketcherInstance[0].exportStructure("mol").then(function(source) {
                    document.getElementById('entree1').value=source;
                }, function(error) {
                    alert("Molecule export failed:"+error);    
                });
            }

            if (currCible > 1) {
                marvinSketcherInstance[1].exportStructure("mol").then(function(source) {
                    document.getElementById('entree2').value=source;
                }, function(error) {
                    alert("Molecule export failed:"+error);    
                });
            }

            if (currCible > 2) {
                marvinSketcherInstance[2].exportStructure("mol").then(function(source) {
                    document.getElementById('entree3').value=source;
                }, function(error) {
                    alert("Molecule export failed:"+error);    
                });
            }

            if (currCible > 3) {
                marvinSketcherInstance[3].exportStructure("mol").then(function(source) {
                    document.getElementById('entree4').value=source;
                }, function(error) {
                    alert("Molecule export failed:"+error);    
                });
            }

            if (currCible > 4) {
                marvinSketcherInstance[4].exportStructure("mol").then(function(source) {
                    document.getElementById('entree5').value=source;
                }, function(error) {
                    alert("Molecule export failed:"+error);    
                });
            }

            setTimeout(function(){
                submitform();
            }, 500); 
 
        });
}

That is why using a "for" loop would be the best way for me.

ChemAxon 996dedebe0

12-02-2015 10:02:33

Dear lcollia,


I highly recommend you to use my collegue, Tamas's solution, if the result code would be too noisy, i suggest you to extract the code inside the "then" part to a separate recursive method, somehow like this:


function initControl () {
var instanceCount = 5; // the number of editors
$("#btn-valid").on("click", function (e) {
export(0);
});
function export(i){
marvinSketcherInstance.exportStructure("mol").then(function(source) {
document.getElementById('entree'+i.toString())).value=source; // do whatever you wish.

if(i<instanceCount){
export(i+1); // invoke this function on the next editor.
} else {
submitform(); // all editors have finished exporting.
}
}, function(error) {
alert("Molecule export failed in editor "+i.toString()+":"+error);
});
}
}



the "setTimeout" way is unsafe, since you can not be sure if the feature is ready in time.


 


regards,


Janos

User 646de8ab9c

12-02-2015 11:45:12

Hi Janos,


Many thanks for your solution. It work perfectly AND now I do not have the use of the unsafe "Set TimeOut" function.


Just to know, the only modification I added to your code is to take into account the possibility where no Marvin instance was started.


Thanks again,


Lionel