Skip to content

refactor javascript files #437

@superjai

Description

@superjai

Recommendation: Namespace + ES6 Class Pattern

After analyzing all 26 JavaScript files across the plugin, here are the findings and recommendation.

Current Problems

  1. Global namespace pollution — 50+ functions and variables dumped directly into window scope across files like utility.js, admin-scene.js, admin-modal.js, etc.
  2. Fragile implicit dependenciesadmin-scene.js, admin-modal.js, and admin-figure.js all silently depend on utility.js being loaded first
  3. Duplicate codewaitForElementById() is defined in multiple files; REST fetch patterns are copy-pasted everywhere
  4. 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_script as-is
  • Truly OOP — ES6 classes with encapsulated state and clear interfaces
  • One global — everything lives under a single GraphicData namespace 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

  1. Add namespace.js and enqueue it with highest priority
  2. Convert utility.js first (everything else depends on it)
  3. Convert one file at a time, keeping backward-compatible global aliases temporarily:
// Temporary bridge during migration
window.redText = GraphicData.Utility.redText;
  1. 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)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions