11import Configuration from "./configuration" ;
22import Core from "./core.src" ;
3- import EditorListener from "./editorlistener" ;
43import Listeners from "./listeners" ;
54import MathML from "./mathml" ;
65import Util from "./util" ;
76import Telemeter from "./telemeter" ;
7+ import SDK from "@wiris/mathtype.integrations.sdk" ;
88
99export default class ContentManager {
1010 /**
@@ -69,14 +69,22 @@ export default class ContentManager {
6969 }
7070
7171 /**
72- * {@link EditorListener } instance. Manages the changes inside the editor.
73- * @type {EditorListener }
72+ * Tracks whether the editor content has been changed by the user.
73+ * Replaces the old EditorListener class.
74+ * @type {Boolean }
75+ */
76+ this . isContentChanged = false ;
77+
78+ /**
79+ * Whether the content manager is waiting for changes from the editor.
80+ * @type {Boolean }
7481 */
75- this . editorListener = new EditorListener ( ) ;
82+ this . waitingForChanges = false ;
7683
7784 /**
78- * MathType editor instance.
79- * @type {JsEditor }
85+ * SDK Editor instance. This is the only editor reference needed.
86+ * Created via the SDK's createEditor() factory method.
87+ * @type {import("@wiris/mathtype.integrations.sdk").Editor }
8088 */
8189 this . editor = null ;
8290
@@ -174,77 +182,93 @@ export default class ContentManager {
174182 }
175183
176184 /**
177- * Inserts MathType editor into the {@link ModalDialog.contentContainer}. It waits until
178- * editor's JavaScript is loaded .
185+ * Inserts MathType editor into the {@link ModalDialog.contentContainer} using the SDK Editor.
186+ * The SDK handles script loading and JsEditor instantiation internally .
179187 */
180188 insertEditor ( ) {
181- if ( ContentManager . isEditorLoaded ( ) ) {
182- this . editor = window . com . wiris . jsEditor . JsEditor . newInstance ( this . editorAttributes ) ;
183- this . editor . insertInto ( this . modalDialogInstance . contentContainer ) ;
184- this . editor . focus ( ) ;
189+ const container = this . modalDialogInstance . contentContainer ;
185190
186- // `editor.action("rtl");` toggles the RTL mode based on the current state, it doesn't just switch to RTL.
187- if ( this . modalDialogInstance . rtl && ! this . editor . getEditorModel ( ) . isRTL ( ) ) {
188- this . editor . action ( "rtl" ) ;
189- }
190- // Setting div in rtl in case of it's activated.
191- if ( this . editor . getEditorModel ( ) . isRTL ( ) ) {
192- this . editor . element . style . direction = "rtl" ;
193- }
191+ // Ensure the container has an id so the SDK Editor can find it.
192+ if ( ! container . id ) {
193+ container . id = "wrs_sdk_editor_container" ;
194+ }
194195
195- // Editor listener: this object manages the changes logic of editor.
196- this . editor . getEditorModel ( ) . addEditorListener ( this . editorListener ) ;
196+ // Derive the SDK base URL from the configured editorUrl.
197+ const editorUrl = ContentManager . getEditorBaseUrl ( ) ;
198+
199+ // Map the current editorAttributes to the SDK EditorConfig.
200+ const sdkEditorConfig = {
201+ language : this . editorAttributes . language || this . language ,
202+ toolbar : this . editorAttributes . toolbar || "general" ,
203+ } ;
204+
205+ // Create the SDK instance and the SDK Editor.
206+ const sdkInstance = new SDK ( { url : "patata" } ) ;
207+ console . log ( "Creating SDK Editor with config:" , sdkEditorConfig ) ;
208+ this . editor = sdkInstance . createEditor ( sdkEditorConfig ) ;
209+
210+ // Use the SDK's ContentChanged event to track changes
211+ // (replaces the old EditorListener pattern).
212+ this . editor . on ( "ContentChanged" , ( ) => {
213+ if ( this . waitingForChanges && ! this . isContentChanged ) {
214+ this . isContentChanged = true ;
215+ }
216+ } ) ;
197217
218+ // Listen for the EditorReady event to perform post-init setup.
219+ this . editor . on ( "EditorReady" , ( ) => {
198220 // iOS events.
199- if ( this . modalDialogInstance . deviceProperties . isIOS ) {
221+ if ( this . modalDialogInstance . deviceProperties ? .isIOS ) {
200222 setTimeout ( function ( ) {
201- // Make sure the modalDialogInstance is available when the timeout is over
202- // to avoid throw errors and stop execution.
203223 if ( this . hasOwnProperty ( "modalDialogInstance" ) ) this . modalDialogInstance . hideKeyboard ( ) ; // eslint-disable-line no-prototype-builtins
204224 } , 400 ) ;
205225
206226 const formulaDisplayDiv = document . getElementsByClassName ( "wrs_formulaDisplay" ) [ 0 ] ;
207- Util . addEvent ( formulaDisplayDiv , "focus" , this . modalDialogInstance . handleOpenedIosSoftkeyboard ) ;
208- Util . addEvent ( formulaDisplayDiv , "blur" , this . modalDialogInstance . handleClosedIosSoftkeyboard ) ;
227+ if ( formulaDisplayDiv ) {
228+ Util . addEvent ( formulaDisplayDiv , "focus" , this . modalDialogInstance . handleOpenedIosSoftkeyboard ) ;
229+ Util . addEvent ( formulaDisplayDiv , "blur" , this . modalDialogInstance . handleClosedIosSoftkeyboard ) ;
230+ }
209231 }
210- // Fire onLoad event. Necessary to set the MathML into the editor
211- // after is loaded.
232+
233+ // Fire onLoad event. Necessary to set the MathML into the editor after it is loaded.
212234 this . listeners . fire ( "onLoad" , { } ) ;
213- } else {
214- setTimeout ( ContentManager . prototype . insertEditor . bind ( this ) , 100 ) ;
215- }
216- }
235+ } ) ;
217236
218- /**
219- * Initializes the current class by loading MathType script.
220- */
221- init ( ) {
222- if ( ! ContentManager . isEditorLoaded ( ) ) {
223- this . addEditorAsExternalDependency ( ) ;
224- }
237+ // Kick off the SDK Editor initialization (loads script + creates editor in the container).
238+ this . editor . init ( container . id ) ;
225239 }
226240
227241 /**
228- * Adds script element to the DOM to include editor externally.
242+ * Returns the base URL for the SDK from the configured editorUrl.
243+ * Strips the trailing "/editor" segment if present.
244+ * @returns {String } The SDK-compatible base URL.
229245 */
230- addEditorAsExternalDependency ( ) {
231- const script = document . createElement ( "script" ) ;
232- script . type = "text/javascript" ;
246+ static getEditorBaseUrl ( ) {
233247 let editorUrl = Configuration . get ( "editorUrl" ) ;
234248
235- // We create an object url for parse url string and work more efficiently .
249+ // Normalize protocol .
236250 const anchorElement = document . createElement ( "a" ) ;
237-
238251 ContentManager . setHrefToAnchorElement ( anchorElement , editorUrl ) ;
239252 ContentManager . setProtocolToAnchorElement ( anchorElement ) ;
240-
241253 editorUrl = ContentManager . getURLFromAnchorElement ( anchorElement ) ;
242254
243- // Load editor URL. We add stats as GET params.
244- const stats = this . getEditorStats ( ) ;
245- script . src = `${ editorUrl } ?lang=${ this . language } &stats-editor=${ stats . editor } &stats-mode=${ stats . mode } &stats-version=${ stats . version } ` ;
255+ // The SDK appends "/editor" internally, so strip it from the configured URL.
256+ if ( editorUrl . endsWith ( "/editor" ) ) {
257+ editorUrl = editorUrl . slice ( 0 , - "/editor" . length ) ;
258+ }
246259
247- document . getElementsByTagName ( "head" ) [ 0 ] . appendChild ( script ) ;
260+ return editorUrl ;
261+ }
262+
263+ /**
264+ * Initializes the current class.
265+ * With the SDK, script loading is handled by the SDK Editor's init() method,
266+ * so this method is now a no-op. The SDK will load the editor script
267+ * when insertEditor() calls sdkEditor.init().
268+ */
269+ init ( ) {
270+ // Script loading is now deferred to insertEditor() via the SDK.
271+ // No pre-loading is needed.
248272 }
249273
250274 /**
@@ -338,18 +362,13 @@ export default class ContentManager {
338362
339363 /**
340364 * Returns true if editor is loaded. Otherwise, false.
365+ * With the SDK, the editor script loading is handled internally by the SDK Editor.
366+ * This always returns false since the SDK uses async init — callers should
367+ * rely on the 'onLoad' listener event instead.
341368 * @returns {Boolean }
342369 */
343370 static isEditorLoaded ( ) {
344- // To know if editor JavaScript is loaded we need to wait until
345- // window.com.wiris.jsEditor.JsEditor.newInstance is ready.
346- return (
347- window . com &&
348- window . com . wiris &&
349- window . com . wiris . jsEditor &&
350- window . com . wiris . jsEditor . JsEditor &&
351- window . com . wiris . jsEditor . JsEditor . newInstance
352- ) ;
371+ return false ;
353372 }
354373
355374 /**
@@ -362,28 +381,26 @@ export default class ContentManager {
362381 }
363382
364383 /**
365- * Sets a MathML into { @link ContentManager.editor} instance.
384+ * Sets a MathML into the SDK Editor instance.
366385 * @param {String } mathml - MathML string.
367- * @param {Boolean } focusDisabled - If true editor don 't get focus after the MathML is set.
386+ * @param {Boolean } focusDisabled - If true editor doesn 't get focus after the MathML is set.
368387 * False by default.
369388 */
370389 setMathML ( mathml , focusDisabled ) {
371- // By default focus is enabled.
372390 if ( typeof focusDisabled === "undefined" ) {
373391 focusDisabled = false ;
374392 }
375- // Using setMathML method is not a change produced by the user but for the API
376- // so we set to false the contentChange property of editorListener.
377- this . editor . setMathMLWithCallback ( mathml , ( ) => {
378- this . editorListener . setWaitingForChanges ( true ) ;
379- } ) ;
393+ // The SDK Editor's setMathML is synchronous.
394+ // We manage the change tracking state directly.
395+ this . editor . setMathML ( mathml ) ;
396+ this . waitingForChanges = true ;
380397
381- // We need to wait a little until the callback finish.
398+ // We need to wait a little to allow the editor to settle before
399+ // resetting the content changed flag (same timing as the original).
382400 setTimeout ( ( ) => {
383- this . editorListener . setIsContentChanged ( false ) ;
401+ this . isContentChanged = false ;
384402 } , 500 ) ;
385403
386- // In some scenarios - like closing modal object - editor mustn't be focused.
387404 if ( ! focusDisabled ) {
388405 this . onFocus ( ) ;
389406 }
@@ -410,7 +427,7 @@ export default class ContentManager {
410427 * Triggered by {@link ModalDialog.submitAction}.
411428 */
412429 submitAction ( ) {
413- if ( ! this . editor . isFormulaEmpty ( ) ) {
430+ if ( ! this . editor . isEmpty ( ) ) {
414431 let mathML = this . editor . getMathMLWithSemantics ( ) ;
415432 // Add class for custom editors.
416433 if ( this . customEditors . getActiveEditor ( ) !== null ) {
@@ -438,13 +455,14 @@ export default class ContentManager {
438455 }
439456
440457 /**
441- * Sets an empty MathML as { @link ContentManager. editor} content.
458+ * Sets an empty MathML as editor content.
442459 * This will open the MT/CT editor with the hand mode.
443460 * It adds dir rtl in case of it's activated.
444461 */
445462 setEmptyMathML ( ) {
446463 const isMobile = this . deviceProperties . isAndroid || this . deviceProperties . isIOS ;
447- const isRTL = this . editor . getEditorModel ( ) . isRTL ( ) ;
464+ // Use the RTL flag from the modal dialog instance (set during integration init).
465+ const isRTL = this . modalDialogInstance ?. rtl || false ;
448466
449467 if ( isMobile || this . integrationModel . forcedHandMode ) {
450468 // For mobile devices or forced hand mode, set an empty annotation MATHML to maintain the editor in Hand mode.
@@ -563,34 +581,36 @@ export default class ContentManager {
563581 * It will open any formula written in Keyboard mode with the hand mode with the default hand trace.
564582 *
565583 * @param {String } mathml The original KeyBoard MathML
566- * @param {Object } editor The editor object .
584+ * @param {Object } editor The SDK Editor instance .
567585 */
568586 async openHandOnKeyboardMathML ( mathml , editor ) {
569- // First, as an editor requirement, we need to update the editor object with the current MathML formula.
570- // Once the MathML formula is updated to the one we want to open with handMode, we will be able to proceed.
571- await new Promise ( ( resolve ) => {
572- editor . setMathMLWithCallback ( mathml , resolve ) ;
573- } ) ;
574-
575- // We wait until the hand editor object exists.
576- await this . waitForHand ( editor ) ;
587+ // Set the MathML first via the SDK Editor (synchronous).
588+ editor . setMathML ( mathml ) ;
589+
590+ // Use the SDK's getHand() to access the hand editor.
591+ const handAccessor = editor . getHand ( ) ;
592+ if ( ! handAccessor ) {
593+ // Wait for the hand editor to become available.
594+ await new Promise ( ( resolve ) => {
595+ const interval = setInterval ( ( ) => {
596+ if ( editor . getHand ( ) ) {
597+ clearInterval ( interval ) ;
598+ resolve ( ) ;
599+ }
600+ } , 100 ) ;
601+ } ) ;
602+ }
577603
578- // Logic to get the hand traces and open the formula in hand mode.
579- // This logic comes from the editor.
580- const handEditor = editor . hand ;
581- editor . handTemporalMathML = editor . getMathML ( ) ;
582- const handCoordinates = editor . editorModel . getHandStrokes ( ) ;
583- handEditor . setStrokes ( handCoordinates ) ;
584- handEditor . fitStrokes ( true ) ;
585- editor . openHand ( ) ;
604+ // Switch to handwriting input mode via the SDK.
605+ editor . setInputMode ( "handwriting" ) ;
586606 }
587607
588608 /**
589609 * Waits until the hand editor object exists.
590- * @param {Obect } editor The editor object .
610+ * @param {Object } editor The SDK Editor instance .
591611 */
592612 async waitForHand ( editor ) {
593- while ( ! editor . hand ) {
613+ while ( ! editor . getHand ( ) ) {
594614 await new Promise ( ( resolve ) => setTimeout ( resolve , 100 ) ) ;
595615 }
596616 }
@@ -656,16 +676,22 @@ export default class ContentManager {
656676 }
657677
658678 /**
659- * Sets the current {@link ContentManager.editor} instance toolbar.
679+ * Sets the current editor toolbar.
680+ * Note: With the SDK Editor, the toolbar is set at creation time via EditorConfig.
681+ * Runtime toolbar changes require re-creating the editor. For now, we store the value
682+ * for reference but it will only take effect on the next editor creation.
660683 * @param {String } toolbar - The toolbar name.
661684 */
662685 setToolbar ( toolbar ) {
663686 this . toolbar = toolbar ;
664- this . editor . setParams ( { toolbar : this . toolbar } ) ;
687+ // The SDK Editor does not support runtime toolbar changes via setParams.
688+ // The toolbar is applied when the editor is created in insertEditor().
689+ console . warn ( "ContentManager.setToolbar: Runtime toolbar change is not supported by the SDK Editor. It will take effect on next editor open." ) ;
665690 }
666691
667692 /**
668693 * Sets the custom headers added on editor requests.
694+ * Note: With the SDK Editor, custom headers are not supported via setParams.
669695 * @returns {Object } headers - key value headers.
670696 */
671697 setCustomHeaders ( headers ) {
@@ -678,17 +704,18 @@ export default class ContentManager {
678704 headersObj = Util . convertStringToObject ( headers ) ;
679705 }
680706
681- this . editor . setParams ( { customHeaders : headersObj } ) ;
707+ // The SDK Editor does not support setParams for custom headers.
708+ console . warn ( "ContentManager.setCustomHeaders: Custom headers are not supported by the SDK Editor." ) ;
682709 return headersObj ;
683710 }
684711
685712 /**
686713 * Returns true if the content of the editor has been changed. The logic of the changes
687- * is delegated to { @link EditorListener} class .
714+ * is tracked via the SDK Editor's ContentChanged event .
688715 * @returns {Boolean } True if the editor content has been changed. False otherwise.
689716 */
690717 hasChanges ( ) {
691- return ! this . editor . isFormulaEmpty ( ) && this . editorListener . getIsContentChanged ( ) ;
718+ return ! this . editor . isEmpty ( ) && this . isContentChanged ;
692719 }
693720
694721 /**
0 commit comments