You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Feed CapitalizeMyTitle Dictionary or model to plugin to work or
Can add aA button next to Formatter (A) button in TinyMCE iFrame of Title and Subtitle. Use DOM analyser to find the solution.
Working Knowledge till now is here:
Title Capitalizer Plugin – Developer Handoff Notes
Context
OMP (Open Monograph Press) 3.4.0.9 installation at inkbound.org.
A custom generic plugin titlecapitalizer is meant to auto-capitalize the Title and Subtitle fields in the Publication → Title & Abstract tab of the editorial workflow when an editor types or pastes text.
These are NOT plain <input> elements. They are TinyMCE rich-text editors running inside <iframe> elements.
Confirmed from live DOM inspection via browser console:
tinymce.get().map(e=>e.id)// Returns:// [// "titleAbstract-title-control-en", ← Title field// "titleAbstract-subtitle-control-en", ← Subtitle field// "titleAbstract-abstract-control-en", ← Abstract (full TinyMCE with toolbar)// "metadata-dataAvailability-control-en"// ]
The Title and Subtitle use component: "field-rich-text" with size: "oneline" (defined in Vue component state). They appear visually as plain text boxes because TinyMCE in oneline mode hides the toolbar until the field is focused.
TinyMCE Editor IDs (locale-suffixed)
Field
Editor ID
Title
titleAbstract-title-control-en
Subtitle
titleAbstract-subtitle-control-en
Note
The -en suffix is the locale. For multilingual installations it may also be -fr, -de, etc. The regex /-title-|-subtitle-/ on the editor ID correctly matches all locales.
Correct TinyMCE Hook Pattern
The PlainPaste plugin (/plugins/generic/plainPaste/js/plainPaste.js) successfully hooks into these same editors. Its working pattern is:
functioninit(){if(typeoftinymce==='undefined')returnfalse;// 1. Hook into already-initialized editorstinymce.get().forEach(function(editor){setupEditor(editor);});// 2. Hook into future editors (Vue lazy-mounts tabs)tinymce.on('AddEditor',function(e){setupEditor(e.editor);});returntrue;}// 3. Polling retry — TinyMCE may not be ready immediatelyif(!init()){varattempts=0;varpoll=setInterval(function(){attempts++;if(init()||attempts>=20)clearInterval(poll);},500);}
Caution
Do NOT use tinymce.editors — that is not a valid public API in the bundled TinyMCE version. Use tinymce.get() instead.
The plugin JS loads on the page (confirmed via document.querySelectorAll('script[src*="titleCapitalizer"]').length), and TinyMCE editors exist with the correct IDs.
However, editor._tcHooked remains undefined on the title editor after page load, meaning setupEditor() is not being called — despite tinymce.get() returning the editors in the console.
Suspected cause
There may be a timing race: tinymce.get() may return an empty array when our script first executes (Vue hasn't mounted yet), and tinymce.on('AddEditor', ...) may fire before our listener is registered (because TinyMCE initializes inside a Vue component that mounts on DOMContentLoaded, potentially before our deferred script runs).
What to try next
Console test to confirm the hook works manually:
vared=tinymce.get('titleAbstract-title-control-en');ed.on('blur',function(){vart=ed.getContent({format:'text'});ed.setContent(t.toUpperCase());});// Now click inside title field then click outside — should UPPERCASE
If manual hook works, the issue is purely timing of script load vs. TinyMCE init. Solution: load our JS earlier (e.g., hook into a Vue event or use window.pkp.eventBus if available in OMP 3.4).
Check OMP 3.4 Vue event bus for when forms are ready:
// In OMP 3.4, the Vue app may emit events when components mountwindow.pkp&&window.pkp.eventBus&&window.pkp.eventBus.$on('form-mounted',function(id){if(id==='titleAbstract'){tinymce.get().forEach(setupEditor);}});
Alternative approach — use tinymce.PluginManager to register a plugin that runs setup on every editor init:
tinymce.PluginManager.add('titleCapitalizer',function(editor){if(!/-title-|-subtitle-/.test(editor.id))return;editor.on('blur',function(){/* capitalize */});});// Then the plugin name must be added to TinyMCE's plugins list — requires PHP change
PHP Plugin File Location
/plugins/generic/titlecapitalizer/
├── TitleCapitalizerPlugin.php ← Registers hook, injects JS
├── index.php
├── version.xml
├── js/
│ └── titleCapitalizer.js ← The JS that needs to work
├── locale/
│ └── en/locale.po
└── templates/
└── settings.tpl
The PHP uses Hook::add('TemplateManager::display', [$this, 'injectJS']) with contexts => 'backend' and priority => STYLE_SEQUENCE_LAST.
window.titleCapitalizerStyle is set via addHeader before the script runs and contains the selected style ('chicago', 'apa', 'sentence', 'uppercase', 'lowercase').
Working Knowledge till now is here:
Title Capitalizer Plugin – Developer Handoff Notes
Context
OMP (Open Monograph Press) 3.4.0.9 installation at inkbound.org.
A custom generic plugin
titlecapitalizeris meant to auto-capitalize the Title and Subtitle fields in the Publication → Title & Abstract tab of the editorial workflow when an editor types or pastes text.GitHub repo: https://github.com/OJSpro/title-capitalizer
What the Title & Subtitle Fields Actually Are
Important
These are NOT plain
<input>elements. They are TinyMCE rich-text editors running inside<iframe>elements.Confirmed from live DOM inspection via browser console:
The Title and Subtitle use
component: "field-rich-text"withsize: "oneline"(defined in Vue component state). They appear visually as plain text boxes because TinyMCE in oneline mode hides the toolbar until the field is focused.TinyMCE Editor IDs (locale-suffixed)
titleAbstract-title-control-entitleAbstract-subtitle-control-enNote
The
-ensuffix is the locale. For multilingual installations it may also be-fr,-de, etc. The regex/-title-|-subtitle-/on the editor ID correctly matches all locales.Correct TinyMCE Hook Pattern
The PlainPaste plugin (
/plugins/generic/plainPaste/js/plainPaste.js) successfully hooks into these same editors. Its working pattern is:Caution
Do NOT use
tinymce.editors— that is not a valid public API in the bundled TinyMCE version. Usetinymce.get()instead.Current Plugin JS (
js/titleCapitalizer.js)Current Status: Unresolved Issue
The plugin JS loads on the page (confirmed via
document.querySelectorAll('script[src*="titleCapitalizer"]').length), and TinyMCE editors exist with the correct IDs.However,
editor._tcHookedremainsundefinedon the title editor after page load, meaningsetupEditor()is not being called — despitetinymce.get()returning the editors in the console.Suspected cause
There may be a timing race:
tinymce.get()may return an empty array when our script first executes (Vue hasn't mounted yet), andtinymce.on('AddEditor', ...)may fire before our listener is registered (because TinyMCE initializes inside a Vue component that mounts on DOMContentLoaded, potentially before our deferred script runs).What to try next
If manual hook works, the issue is purely timing of script load vs. TinyMCE init. Solution: load our JS earlier (e.g., hook into a Vue event or use
window.pkp.eventBusif available in OMP 3.4).Check OMP 3.4 Vue event bus for when forms are ready:
tinymce.PluginManagerto register a plugin that runssetupon every editor init:PHP Plugin File Location
The PHP uses
Hook::add('TemplateManager::display', [$this, 'injectJS'])withcontexts => 'backend'andpriority => STYLE_SEQUENCE_LAST.window.titleCapitalizerStyleis set viaaddHeaderbefore the script runs and contains the selected style ('chicago','apa','sentence','uppercase','lowercase').