eacortes's picture
push new db or demo version
776a711
/**
* @fileoverview ChemWriter integration with Gradio interface
* Handles bidirectional synchronization between ChemWriter editor and Gradio textbox
* @author Manny Cortes ('manny@derifyai.com')
* @version 0.3.0
*/
// ============================================================================
// GLOBAL VARIABLES
// ============================================================================
/** @type {Object|null} The ChemWriter editor instance */
let editor = null;
let chemwriter = null;
// ============================================================================
// CONSTANTS
// ============================================================================
/** @const {string} Default SMILES for initial molecule (ethanol) */
const DEFAULT_SMILES = "CN(C)CCC1=CNC2=C1C(=CC=C2)OP(=O)(O)O";
/** @const {string} CSS selector for the Gradio SMILES input element */
const SMILES_INPUT_SELECTOR = "#smiles_input textarea, #smiles_input input";
/** @const {string} CSS selector for the Gradio Mol file input element */
const MOL_INPUT_SELECTOR = "#mol_input textarea, #mol_input input";
/** @const {string} CSS selector for the Gradio search button */
const SEARCH_BUTTON_SELECTOR = "#search_btn";
/** @const {number} Delay for paste event handling (ms) */
const PASTE_DELAY = 50;
/** @const {number} Delay for initialization retry (ms) */
const INIT_RETRY_DELAY = 250;
/** @const {string[]} Events to trigger for Gradio change detection */
const GRADIO_CHANGE_EVENTS = ["input", "change"];
// ============================================================================
// CORE INITIALIZATION
// ============================================================================
/**
* Initializes ChemWriter editor and sets up event handlers
*/
function initializeChemWriter() {
try {
setupSmilesTextboxEventListeners();
setupChemWriterEventListeners();
editor.setSMILES(DEFAULT_SMILES);
// search after the rest of the gradio components load
setTimeout(() => document.getElementById("search_btn")?.click(), 500);
console.log("ChemWriter initialized successfully");
} catch (error) {
console.error("Error initializing ChemWriter:", error);
}
}
// ============================================================================
// GRADIO AND CHEMWRITER INTEGRATION
// ============================================================================
/**
* Updates the mol_input Gradio textbox with a mol file string
* Triggers appropriate events to ensure Gradio detects the change
*/
function updateGradioTextbox() {
try {
const molTextbox = document.querySelector(MOL_INPUT_SELECTOR);
const molFile = editor?.getMolfile();
molTextbox.value = molFile;
// Trigger events to ensure Gradio detects the change
GRADIO_CHANGE_EVENTS.forEach((eventType) => {
const event = new Event(eventType, {
bubbles: true,
cancelable: true,
});
molTextbox.dispatchEvent(event);
});
} catch (error) {
console.error("Error updating Gradio textbox:", error);
}
}
/**
* Updates the ChemWriter editor with a SMILES string from the textbox
* @param {string} smiles - The SMILES string to display in ChemWriter
*/
function updateChemWriterFromTextbox(smiles) {
try {
smiles = smiles.trim();
editor?.setSMILES(smiles);
} catch (error) {
console.error("Error updating ChemWriter from textbox:", error);
}
}
// ============================================================================
// UI MONITORING
// ============================================================================
function setupSmilesTextboxEventListeners() {
const textbox = document.querySelector(SMILES_INPUT_SELECTOR);
if (!textbox) {
return;
}
textbox.addEventListener("input", handleTextboxChange);
textbox.addEventListener("change", handleTextboxChange);
textbox.addEventListener("paste", handleTextboxPaste);
}
function setupChemWriterEventListeners() {
window.addEventListener("resize", () => editor.jd());
editor.addEventListener('document-edited', updateGradioTextbox);
}
/**
* Handles textbox change events
* @param {Event} event - The change event
*/
function handleTextboxChange(event) {
updateChemWriterFromTextbox(event.target.value);
}
/**
* Handles textbox paste events with a delay to ensure content is available
* @param {Event} event - The paste event
*/
function handleTextboxPaste(event) {
setTimeout(() => {
updateChemWriterFromTextbox(event.target.value);
}, PASTE_DELAY);
}
// ============================================================================
// PUBLIC API
// ============================================================================
/**
* Sets ChemWriter SMILES string
* @param {string} smiles - The SMILES string to set
* @public
*/
window.setCWSmiles = function (smiles) {
updateChemWriterFromTextbox(smiles);
};
/**
* Clears both ChemWriter and Gradio textbox
* @public
*/
window.clearCW = function () {
editor.setMolfile('\nCWRITER06142521562D\nCreated with ChemWriter - https://chemwriter.com\n 0 0 0 0 0 0 0 0 0 0999 V2000\nM END');
};
// ============================================================================
// INITIALIZATION LOGIC
// ============================================================================
/**
* Checks if ChemWriter library is loaded and initializes ChemWriter editor
*/
function initializeWhenReady() {
chemwriter = window?.chemwriter;
// The ChemWriter library normally sets up a window load event listener: window.addEventListener("load", function(){Z.De()}, false)
// However, due to race conditions, the "load" event listener may not be added or triggered in time for proper initialization.
// So we call the initialization function directly here.
chemwriter?.System?.De();
editor = chemwriter?.components?.editor;
if (typeof chemwriter?.System?.De !== "undefined" && typeof editor !== "undefined") {
console.log("ChemWriter library loaded, initializing...");
chemwriter.System.ready(initializeChemWriter);
} else {
console.log("ChemWriter library not ready, retrying...");
setTimeout(initializeWhenReady, INIT_RETRY_DELAY);
}
}
initializeWhenReady();