rawpython / remi

Python REMote Interface library. Platform independent. In about 100 Kbytes, perfect for your diet.
Apache License 2.0
3.53k stars 402 forks source link

Javascript gets unloaded after remi reloads with "handshake complete" #523

Open diovudau opened 1 year ago

diovudau commented 1 year ago

Here is the code for two simple files, "main.py" and "custom.js", living in the same directory. The purpose is to simulate loading of a 3rd party javascript library. In this example it simply rewrites the innerHTML of a <div> to "Hello World".

However, I cannot get Remi to permanently make it work. What happens is that briefly on load/refresh the javascript is executed and "hello world" appears on the page, but Remi triggers some kind of second loading, indicated with handshake complete in the terminal, which makes "hello world" disappear.

I would expect such a simple, everyday usecase of html and javascript to work. I am looking forward to comments and explanations.

Here is the code:

main.py

#! /usr/bin/env python3
# -*- coding: utf-8 -*-

import os.path
import remi.gui as gui
from remi import start, App

class CustomJavascriptApp(App):
    def __init__(self, *args):
        res_path = os.path.dirname(os.path.abspath(__file__))
        super().__init__(*args, static_file_path={'static': res_path})

    def main(self):
        self.page.children['head'].add_child('customjs', "<script defer src='/static:custom.js'></script>")
        self.containerWidget = gui.VBox()

        self.label = gui.Label("Below this should be the text: 'Hello World'."
        "It will disappear after the page is fully loaded,"
        "with the handshake. Maybe it will show again for a short while after F5 refresh.")

        self.mywidget = gui.Widget( _type="div", width=250, height=200, margin="10px")
        self.mywidget.attributes["id"] = "mywidget"

        self.containerWidget.append(self.label)
        self.containerWidget.append(self.mywidget)

        return self.containerWidget

start(CustomJavascriptApp, address="0.0.0.0", port=2020)

custom.js

   document.getElementById("mywidget").innerHTML = "Hello World";
momostafas commented 1 year ago

To fix this, you can delay the execution of the JavaScript code until the page is fully loaded using the window.onload event. Here's how you can modify your custom.js:

window.onload = function() { document.getElementById("mywidget").innerHTML = "Hello World"; };

By using window.onload, you ensure that the JavaScript code will only execute after the entire page, including all its resources (like images and stylesheets), has finished loading.

Additionally, there's a syntax error in your main.py code. You need to close the gui.Label constructor with an extra closing parenthesis. Here's the corrected line:

self.label = gui.Label("Below this should be the text: 'Hello World'." "It will disappear after the page is fully loaded," "with the handshake. Maybe it will show again for a short while after F5 refresh.")

diovudau commented 1 year ago

Thanks for the answer. The closing parenthesis is already in the original code.

I know that I can use the onload callback. Remember, this is about a real external library, but nobody would read my bug report if I submit hundreds of code lines with additional external libraries, hence the minimal example. In reality I need to load an external file. And iirc when I tried the onload route the text was indeed there after a full reload, but then when switching the root widget for "pagination" it disappeared. So the outcome was equally bad.

In any case, the solution must depend on external javascript files, not inline code.

dddomodossola commented 1 year ago

Hello @diovudau ,

Your example loads correctly the js library. You can inspect your page to check it is structured correctly. As @momostafas correctly suggests, you should execute it on a specific event (onload should be fine, or eventually onpageshow). About pagination, remi dynamically updates page elements. You should eventually trigger the JS execution when page gets updated.

However I suggest every time to not to use JS external libraries if the same job can be done with python.

Kind Regards