skariel / webalchemy

Modern web development with Python
MIT License
346 stars 21 forks source link

DOM Elements are not synchronized between the server and the clients #146

Closed joaoventura closed 10 years ago

joaoventura commented 10 years ago

(This comes in sequence of a previous comment of mine)

Currently, WebAlchemy has two parallel representations of the DOM tree: one in the server and one in the client.

For instance, when you do this:

self.rdoc.body.element(h1='Hello World!!!')

webalchemy creates a new instance of type Element and appends it to the body element on the server, and then eventually sends the javascript code for the client to do the same.

This leads to two situations:

class HelloWorldApp:

    def initialize(self, **kwargs):
        self.rdoc = kwargs['remote_document']
        self.hello = self.rdoc.body.element(h1='Hello World!!!')
        self.hello.events.add(click=self.clicked, translate=True)

    def clicked(self):
        self.textContent = self.textContent[1:]
        rpc(self.handle_click_on_backend, 'some message', 'just so you see how to pass paramaters')

    def handle_click_on_backend(self, sender_id, m1, m2):
        print(self.hello._text)
        self.rdoc.body.element(h1=m1+m2)

After two clicks over Hello World, the client DOM tree will have the text as llo World, but the print(self.hello._text) on the server will throw Hello World to the server's console output. However, developers wanting to use self.hello on the server would be expecting its text to be the same as in the client.

This hasn't an easy solution, but there are some possible ways to deal with this:

Comments?

skariel commented 10 years ago

I like the second solution- Remove the DOM manipulations on the server. It's simple, memory efficient

Iftahh commented 10 years ago

I agree.

Memory is a big issue, because no one will consider this solution for a real website if the server will crash when 100 users try to use it. To be a world class solution WebAlchemy needs to be able to scale up AND support at least an order of size number of users as a classic Django/PHP/Ruby server of the same specs.

I guess the memory issue can be somewhat solved with a DB that dumps the server-side DOM to a file (and entire class instance variables as well), but that may result in other performance issues, especially for large DOM pages.

At any rate it won't solve the server and client getting out of sync problem.

So I guess (sadly) server side manipulation of the DOM should be reduced. But still the server can do some DOM manipulation "blind" write-only manipulation of (small) parts of the page using known id of existing element(s).

for example: suppose you have a notification alert that shows the number of unread messages. The server can blindly change the the inner html of that element whenever the number of messages increases.

another example: suppose you have a table of items from a DB and (this is important) you do not use the auto-generated id for the table rows but instead have the table rows id as the DB id of the items. When an item changes the server can blindly change DOM of the correct table row in the page. -- this is making some assumptions: the data isn't change by the client, all the table rows are visible on page (ie. no pagination),

skariel commented 10 years ago

What about making DOM tree tracking selective? for e.g.

container = body.element('div', tracked=True)

So everything appended to container will be tracked while appending to other elements will not be tracked. When container gets GC'd tracking memory is freed. It's not like body which is never GC'd...

Also, we could always have the client send HTML to the server for parsing and manipulation...

skariel commented 10 years ago

(closed by mistake...)

joaoventura commented 10 years ago

I'm more fan of simple solutions, and as such, I would separate the server logic from the client logic, as much as Model (server) - View (client) as possible..

A synchronization mechanism could also be a possibility, but one would have to be careful about how much traffic it would generate..

skariel commented 10 years ago

done- now there's no tracking by default. If you want tracking use for e.g. body.element(p='hi!', tracking=True)