Localhost JSROOT server

I am trying to display ROOT files coming from a remote server.
I need to execute a remote “php” script to get a list of these files, so I think I want to play with my own “localhost” JSROOT server.
I downloaded the latest JSROOT binary distribution and unpacked it into a “./jsroot” directory.
I then created a “./browser” directory with a simple “index.htm” file (see below).
I start my server using “python3 -m http.server” and then point my browser to “http://localhost:8000/browser”.
Unfortunately, no matter where I put the call to the “remoteFileList()” function, neither the “path” nor the “files” gets updated (I am sure that both values are correct in this function).

Update: the “index.htm” file below is fixed now.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Remote File Browser</title>
    <link rel="shortcut icon" href="../jsroot/img/RootIcon.ico"/>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>
    <script>
      function remoteFileList() {
          const username = "me"
          const password = "my"
	      const url = "https://" + username + ":" + password + "@remote.machine/server/"
          $.ajax({
              async: false,
              url: url + "utilities/listRootFiles.php",
              type: "POST",
              success: function(result) {
                  document.getElementById("simpleGUI").setAttribute("path", url + "data/");
                  document.getElementById("simpleGUI").setAttribute("files", result);
              }
          });
      }
    </script>
  </head>
  <body>
    <div id="simpleGUI" path="" files="">
      loading scripts ...
    </div>
    <script>remoteFileList()</script> <!-- sets simpleGUI "path" and "files" -->
    <script type="module">
      import { buildGUI } from '../jsroot/modules/gui.mjs';
      buildGUI("simpleGUI");
    </script>
  </body>
</html>

Note: a local JSROOT distribution/server is NOT really required, of course. One just needs to replace the “../jsroot” string (in two places) with the “https://root.cern/js/latest” or the “https://root.cern/js/dev” string and then use the “Open File” option of the web browser (it may be convenient to rename “index.htm” into, e.g., “browser.htm”).

Hi Wile,

You should call buildGUI function after you update attributes of simpleGUI elements.

Regards,
Sergey

I have already tried it, but it hasn’t worked:

    <script type="module">
      import { buildGUI } from '../jsroot/modules/gui.mjs';
      remoteFileList();
      buildGUI("simpleGUI");
    </script>

You should call buildGUI in the success callback of ajax.

Well, I tried different combinations but with no success.
Could you, please edit and fix my “index.htm”.

Something like:

...
   success: function(result) {
       document.getElementById("simpleGUI").setAttribute("path", url + "data/");
       document.getElementById("simpleGUI").setAttribute("files", result);
       buildGUI("simpleGUI");
   }
...

Important is that attributes are set before buildGUI is called.
It uses attributes to create GUI elements - including combo box with list of files.

Also remove empty attributes from the div:

<div id="simpleGUI">
      loading scripts ...
</div>

I have already tried it, but it hasn’t worked.

BTW. “buildGUI is not defined” when “remoteFileList” is being defined.

You should move remoteFileList into module part. Like:

 <script type="module">
      import { buildGUI } from '../jsroot/modules/gui.mjs';

     function remoteFileList() {
          const username = "me"
          const password = "my"
	      const url = "https://" + username + ":" + password + "@remote.machine/server/"
          $.ajax({
              url: url + "utilities/listRootFiles.php",
              type: "POST",
              success: function(result) {
                  document.getElementById("simpleGUI").setAttribute("path", url + "data/");
                  document.getElementById("simpleGUI").setAttribute("files", result);
                  buildGUI("simpleGUI");
              }
          });
      }

      remoteFileList();
 </script>

Many thanks for your help.

I have finally understood the problem … and a simple solution is to set “async:false” (I modified the “index.htm” in my first post here so that it can be “successfully re-used”):

          $.ajax({
              async: false,

Note: this generates a harmless “Web Console” output warning: “Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user’s experience. For more help http://xhr.spec.whatwg.org/

I didn’t want to modify the “module part” as this is something specific to the current JSROOT version (so it may change in the future, and then I would again need to fight with my custom modifications).

It is not modification of module part. You just executing your code before calling buildGUI.

Using async: false may be problematic - modern browsers always complain when sync HTTP requests are used.

But it is up to you.

Well, I am reading ROOT files from another server, so I need to use the “CORS Everywhere” plugin (for Firefox).

Can I add something in my “index.htm” to enable CORS?

I can use the “Open File” option of the web browser, instead of running a “localhost” server, if that helps.

Can I somehow enable CORS on my"localhost" server (i.e., “python3 -m http.server”)?
I’ve found some scripts on the Internet that create another server that enables CORS, so this may be a solution.

Hi,

See code I am using with http.server with JSROOT.

It adds extra headers for CORS. You can do the same approach.

Regards,
Sergey

Thanks. That’s more or less what other scripts are doing, too.

However, I am trying to tinker with a solution for “inexperienced users”, and I started to think the “Open File” approach (i.e., no “localhost” server) will be easier for them.
So, is there anything I can add to the “index.htm” itself?

No, it must be settings of server itself.

Or “CORS everywhere” plugin for browser

Well, if I use “File Open” (i.e., “file://”) in the browser, then this browser is the “server”, too.
On the other hand, the “CORS Everywhere” plugin (and there exist other similar plugins) is just a big javascript, I guess.
So, I’ve been thinking that some heavily cut-down version might exist that could be incorporated into a user’s file (just for this file).

Most probably, CORS Everywhere just changes configuration of web browser. Which are browser-specific.

Maybe yet another question.

In my “index.htm”, I explicitly embed the “username” and “password”.
They are needed for both, getting the list of “files” and then accessing them with the full “path”.
Is there any simple way to ask the user to provide the required credentials at “run time”, like the usual “this site is asking you to sign in” dialog window?

I have tried the following:

              type: "POST",
              xhrFields: { withCredentials: true },

Unfortunately, this only works when getting the list of “files” in the “remoteFileList” function. The given credentials are not (re)used in the “simpleGUI” when it accesses the “path” later.

As I see, you code user and password into path attribute for the files.
You want that this information will be requested when opening the file?
But in principle you can edit full file URL directly in the GUI.