From 431f0bd53545c93163db8c8ed63692aa74f315c4 Mon Sep 17 00:00:00 2001 From: Sergey Linev Date: Mon, 8 Jun 2026 10:45:23 +0200 Subject: [PATCH] [jupyter] use display.Javascript to embed custom JS code In previous implementation only display.HTML with embed was used. But dependeing from security settings jupyter or web browser blocks loading of such -""" + loadJsroot_{jsDivId}(); +}}""" -TBufferJSONErrorMessage = "The TBufferJSON class is necessary for JS visualisation to work and cannot be found. Did you enable the http module (-D http=ON for CMake)?" + +TBufferJSONErrorMessage = "The TBufferJSON class is necessary for JS visualisation to work and cannot be found. Check your ROOT installation and libRIO library" def TBufferJSONAvailable(): @@ -508,9 +492,7 @@ class NotebookDrawerUrl: def __init__(self, theUrl): self.drawUrl = theUrl - def _getUrlJsCode(self): - - id = _getUniqueDivId() + def _getUrlJsCode(self, id): drawHtml = _jsFullWidthDiv.format( jsDivId=id, @@ -531,7 +513,8 @@ def _getUrlJsCode(self): return thisJsCode def Draw(self, displayFunction): - code = self._getUrlJsCode() + id = _getUniqueDivId() + code = self._getUrlJsCode(id) displayFunction(display.HTML(code)) @@ -545,7 +528,14 @@ def __init__(self, theFileName, theForce=False): self.drawFileName = theFileName self.drawForce = theForce - def _getFileJsCode(self): + def _getFileHtmlCode(self, id): + drawHtml = _jsFullWidthDiv.format( + jsDivId=id, + jsCanvasHeight=_jsCanvasHeight + ) + return drawHtml + + def _getFileJsCode(self, id): base64 = "" with ROOT.TDirectory.TContext(), ROOT.TFile.Open(self.drawFileName) as f: @@ -570,13 +560,6 @@ def _getFileJsCode(self): base64 = ROOT.TBase64.Encode(addrc, sz) - id = _getUniqueDivId() - - drawHtml = _jsFullWidthDiv.format( - jsDivId=id, - jsCanvasHeight=_jsCanvasHeight - ) - browseFileCode = _jsBrowseFileCode.format( jsDivId=id, fileBase64=base64 @@ -584,16 +567,17 @@ def _getFileJsCode(self): thisJsCode = _jsCode.format( jsDivId=id, - jsDivHtml=drawHtml, jsDrawCode=browseFileCode ) return thisJsCode def Draw(self, displayFunction): - code = self._getFileJsCode() - displayFunction(display.HTML(code)) - + id = _getUniqueDivId() + html = self._getFileHtmlCode(id) + code = self._getFileJsCode(id) + displayFunction(display.HTML(html)) + displayFunction(display.Javascript(code)) class NotebookDrawerJson: @@ -622,9 +606,17 @@ def _getJson(self): def _getJsOptions(self): return "" - def _getJsCode(self): + def _getHtmlCode(self, id): width = self._getWidth() height = self._getHeight() + drawHtml = _jsFixedSizeDiv.format( + jsDivId=id, + jsCanvasWidth=width, + jsCanvasHeight=height + ) + return drawHtml + + def _getJsCode(self, id): json = self._getJson() options = self._getJsOptions() @@ -633,14 +625,6 @@ def _getJsCode(self): zip = ROOT.TBufferJSON.zipJSON(json) - id = _getUniqueDivId() - - drawHtml = _jsFixedSizeDiv.format( - jsDivId=id, - jsCanvasWidth=width, - jsCanvasHeight=height - ) - drawJsonCode = _jsDrawJsonCode.format( jsDivId=id, jsonLength=len(json), @@ -650,9 +634,9 @@ def _getJsCode(self): thisJsCode = _jsCode.format( jsDivId=id, - jsDivHtml=drawHtml, jsDrawCode=drawJsonCode ) + return thisJsCode def _getCanvas(self): @@ -675,9 +659,12 @@ def _getPngImage(self): def Draw(self, displayFunction): global _enableJSVis + id = _getUniqueDivId() if _enableJSVis and self._canJsDisplay(): - code = self._getJsCode() - displayFunction(display.HTML(code)) + html = self._getHtmlCode(id) + code = self._getJsCode(id) + displayFunction(display.HTML(html)) + displayFunction(display.Javascript(code)) elif self._canPngDisplay(): displayFunction(self._getPngImage()) else: @@ -718,23 +705,42 @@ def _getCanvas(self): def Draw(self, displayFunction): global _enableJSVis, _canvasHandles - code = "" - if _enableJSVis and self._canJsDisplay(): - code = display.HTML(self._getJsCode()) - elif self._canPngDisplay(): - code = self._getPngImage() - else: - code = display.HTML(f"Neither JSROOT nor plain drawing of {self.drawObject.ClassName()} is implemented") + html = "" + code = "" + handle = None name = self._getCanvasId() updated = self._getUpdated() + id = _getUniqueDivId() + if updated and name and (name in _canvasHandles): - _canvasHandles[name].update(code) - elif name: - _canvasHandles[name] = displayFunction(code, display_id=True) - else: - displayFunction(code) + handle = _canvasHandles[name] + id = handle["divId"] + if _enableJSVis and self._canJsDisplay(): + html = display.HTML(self._getHtmlCode(id)) + code = display.Javascript(self._getJsCode(id)) + elif self._canPngDisplay(): + html = self._getPngImage() + else: + html = display.HTML(f"Neither JSROOT nor plain drawing of {self.drawObject.ClassName()} is implemented") + + if handle: + handle["htmlOutput"].update(html) + if handle["codeOutput"]: + handle["codeOutput"].update(code) + elif code: + handle["codeOutput"] = displayFunction(code) + else: + html = displayFunction(html, display_id=True) + if code: + code = displayFunction(code) + if name: + _canvasHandles[name] = { + "divId": id, + "htmlOutput": html, + "codeOutput": code, + } class NotebookDrawerTCanvas(NotebookDrawerCanvBase): @@ -892,15 +898,8 @@ def enhanceROOTModule(): ROOT.enableJSVis = enableJSVis -def enableCppHighlighting(): - ipDispJs = display.display_javascript - # Define highlight mode for %%cpp magic - ipDispJs(_jsMagicHighlight.format(cppMIME=cppMIME), raw=True) - - def iPythonize(): setStyle() initializeJSVis() loadMagicsAndCapturers() - # enableCppHighlighting() enhanceROOTModule()