-
Notifications
You must be signed in to change notification settings - Fork 5
Open
Description
Recommendation: Namespace + ES6 Class Pattern
After analyzing all 26 JavaScript files across the plugin, here are the findings and recommendation.
Current Problems
- Global namespace pollution — 50+ functions and variables dumped directly into
windowscope across files likeutility.js,admin-scene.js,admin-modal.js, etc. - Fragile implicit dependencies —
admin-scene.js,admin-modal.js, andadmin-figure.jsall silently depend onutility.jsbeing loaded first - Duplicate code —
waitForElementById()is defined in multiple files; REST fetch patterns are copy-pasted everywhere - Untestable — global functions with global state make unit testing impossible
Recommended Pattern: Single Namespace + ES6 Classes
This is the right fit because:
- No build tools required — works with WordPress's
wp_enqueue_scriptas-is - Truly OOP — ES6 classes with encapsulated state and clear interfaces
- One global — everything lives under a single
GraphicDatanamespace instead of 50+ globals - Incremental migration — you can convert one file at a time; old and new code can coexist
How It Works
Step 1: Establish the namespace (loaded first)
// namespace.js — enqueued before all other plugin scripts
window.GraphicData = window.GraphicData || {};Step 2: Convert each file to a class on the namespace
// admin/js/admin-scene.js
(function (GD) {
'use strict';
GD.SceneAdmin = class SceneAdmin {
constructor() {
this.fieldValueSaved = false;
this.init();
}
init() {
GD.Utility.replaceFieldValuesWithTransientValues();
document.addEventListener('DOMContentLoaded', () => this.onReady());
}
onReady() {
GD.Utility.redText();
this.setupEventListeners();
}
setupEventListeners() {
// ...
}
};
})(window.GraphicData);Step 3: Shared utilities become a static class
// admin/js/utility.js
(function (GD) {
'use strict';
GD.Utility = class Utility {
static cookieExists(name) { /* ... */ }
static getCookie(name) { /* ... */ }
static redText() { /* ... */ }
static replaceFieldValuesWithTransientValues() { /* ... */ }
};
})(window.GraphicData);Step 4: Instantiate from each file's IIFE
// At bottom of admin-scene.js, inside the IIFE:
if (GD.Utility.onCorrectEditPage('scene')) {
GD.sceneAdmin = new GD.SceneAdmin();
}Suggested Namespace Structure
GraphicData
├── Utility (static class — shared helpers)
├── SceneAdmin (class — admin scene editing)
├── SceneRenderer (class — frontend scene rendering)
├── ModalAdmin (class — admin modal editing)
├── ModalRenderer (class — frontend modal rendering)
├── FigureAdmin (class — admin figure editing)
├── FigureRenderer (class — frontend figure rendering)
├── PlotlyUtility (static class — Plotly loading/helpers)
├── TimeseriesLine (class — timeseries chart type)
├── BarChart (class — bar chart type)
├── MapChart (class — map chart type)
├── ExportFigures (class — PowerPoint export)
├── CreateSvg (class — SVG generation)
├── PreviewButtons (class — admin preview functionality)
└── FileUpload (class — CSV/file upload handling)
Why NOT Other Patterns
| Pattern | Why not |
|---|---|
ES Modules (import/export) |
Requires a bundler (Webpack/Vite). Adds build complexity to a WordPress plugin. |
| Revealing Module Pattern | Functional, not OOP. The goal is object-oriented. |
| AMD/UMD | Overkill for WordPress; designed for cross-environment compatibility not needed here. |
| Web Components | Wrong abstraction level — this code manages data/forms, not reusable UI elements. |
Migration Strategy
- Add
namespace.jsand enqueue it with highest priority - Convert
utility.jsfirst (everything else depends on it) - Convert one file at a time, keeping backward-compatible global aliases temporarily:
// Temporary bridge during migration
window.redText = GraphicData.Utility.redText;- Remove bridges once all files are converted
Complete List of JavaScript Files to Convert
Admin Files (13 files)
| File | Suggested Class |
|---|---|
admin/js/utility.js |
GraphicData.Utility (static) |
admin/js/admin-scene.js |
GraphicData.SceneAdmin |
admin/js/admin-modal.js |
GraphicData.ModalAdmin |
admin/js/admin-figure.js |
GraphicData.FigureAdmin |
admin/js/admin-instance.js |
GraphicData.InstanceAdmin |
admin/js/admin-about.js |
GraphicData.AboutAdmin |
admin/js/admin-preview-buttons.js |
GraphicData.PreviewButtons |
admin/js/admin-export-figures.js |
GraphicData.ExportFigures |
admin/js/admin-create-svg.js |
GraphicData.CreateSvg |
admin/js/admin-modal-columns.js |
GraphicData.ModalColumns |
admin/js/admin-figure-columns.js |
GraphicData.FigureColumns |
admin/js/scene-quick-edit-validation.js |
GraphicData.SceneQuickEdit |
admin/js/exopite-meta-box-script.js |
GraphicData.MetaBox |
Frontend/Includes Files (13 files)
| File | Suggested Class |
|---|---|
includes/scenes/js/scene-render.js |
GraphicData.SceneRenderer |
includes/modals/js/modal-render.js |
GraphicData.ModalRenderer |
includes/figures/js/figure-render.js |
GraphicData.FigureRenderer |
includes/figures/js/code/figure-code.js |
GraphicData.FigureCode |
includes/figures/js/interactive/plotly-utility.js |
GraphicData.PlotlyUtility (static) |
includes/figures/js/interactive/plotly-timeseries-line.js |
GraphicData.TimeseriesLine |
includes/figures/js/interactive/plotly-bar.js |
GraphicData.BarChart |
includes/figures/js/interactive/plotly-map.js |
GraphicData.MapChart |
includes/figures/js/interactive/file-upload.js |
GraphicData.FileUpload |
includes/figures/js/interactive/settings-plotly-timeseries-line.js |
GraphicData.TimeseriesSettings |
includes/figures/js/interactive/settings-plotly-bar.js |
GraphicData.BarSettings |
includes/utilities/js/utility.js |
GraphicData.FrontendUtility (static) |
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels