Skip to content

Add DOM-guarded CSS/JS injection to DataFrameHtmlFormatter to prevent duplicate style/script inserts #1171

@kosiew

Description

@kosiew

Description:

Currently, DataFrameHtmlFormatter tracks a _styles_loaded class flag in Python to avoid re-injecting styles and scripts across notebook cells. However, this approach:

  • Doesn’t survive module reloads or redefinitions
  • Can conflict if multiple notebooks share the same kernel
  • Still requires manual state resets in tests

We should move the “only-once” guard into the browser DOM/JS layer so that every call to format_html can blindly emit the header scripts/styles, but the browser will insert them only once per page.

Proposed Change:

  1. Remove the _styles_loaded class variable and related Python guard logic.
  2. Always call _build_html_header() and _get_javascript() on each format_html.
  3. Inside those methods, wrap the CSS/JS in small <script> blocks that:
  • Check document.getElementById('df-styles') (or a global flag) before appending a <style> tag
  • Check a window.df_formatter_js_loaded flag before defining the toggle function

example snippet:

--- a/python/datafusion/dataframe_formatter.py
+++ b/python/datafusion/dataframe_formatter.py
@@ -XXX,XX +XXX,XX @@ class DataFrameHtmlFormatter:
-    # Class var: _styles_loaded = False

     def _build_html_header(self) -> list[str]:
-        html = []
-        # Only include styles and scripts if needed
-        if include_styles:
-            html.extend(self._build_css_and_script())
-            if self.use_shared_styles:
-                DataFrameHtmlFormatter._styles_loaded = True
-        return html
+        return ["""
<script>
// Only inject CSS once per page
if (!document.getElementById('df-styles')) {
  const style = document.createElement('style');
  style.id = 'df-styles';
  style.textContent = `
    /* DataFrameHtmlFormatter CSS… */
  `;
  document.head.appendChild(style);
}
</script>
"""] + ([f"<style>{self.custom_css}</style>"] if self.custom_css else [])

     def _get_javascript(self) -> str:
-        return """
-<script> …existing JS… </script>
-"""
+        return """
<script>
// Only inject toggle logic once
if (!window.__df_formatter_js_loaded__) {
  window.__df_formatter_js_loaded__ = true;
  window.toggleDataFrameCellText = function(table_uuid, row, col) {
    /* …existing toggle logic… */
  };
}
</script>
"""

Benefits:

  • Guaranteed “inject once” directly in the browser, regardless of Python reloads
  • Simplifies Python state—no _styles_loaded flag to manage
  • Safe in multi-notebook or testing scenarios

Metadata

Metadata

Assignees

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