Strategies for bulky renders/updates

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
15 messages Options
Reply | Threaded
Open this post in threaded view
|

Strategies for bulky renders/updates

radoslav hodnicak
I've been using seaside with jquery to create quite interactive
interfaces, using the simplest approach of "everything has its own
callback". This works well if the dataset you're working with is
small, but I'm now venturing into territories where it takes seconds
to receive+render a page, which isn't acceptable.

For an example of what I'm talking about imagine a page showing a list
of emails. Every line (email) has a clickable sender, subject, date,
and a bunch of more actions and icons etc. If you're creating
anchors/click actions for each field separately, that's easily
hundreds or thousands of callbacks per page, each needing to be
generated on the server and sent over the wire. So clearly I need to
instead write client side javascript that will figure out what the
user clicked and do a parametrized request. Which I can do, but I'm
wondering if someone has figured out a clever way how to map the
information on the page to smalltalk objects on the server (other than
using callback registry). Same goes for bulk actions involving
multiple items ("delete selected" and the like).

rado
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Strategies for bulky renders/updates

Philippe Marschall
2011/3/13 radoslav hodnicak <[hidden email]>:

> I've been using seaside with jquery to create quite interactive
> interfaces, using the simplest approach of "everything has its own
> callback". This works well if the dataset you're working with is
> small, but I'm now venturing into territories where it takes seconds
> to receive+render a page, which isn't acceptable.
>
> For an example of what I'm talking about imagine a page showing a list
> of emails. Every line (email) has a clickable sender, subject, date,
> and a bunch of more actions and icons etc. If you're creating
> anchors/click actions for each field separately, that's easily
> hundreds or thousands of callbacks per page, each needing to be
> generated on the server and sent over the wire. So clearly I need to
> instead write client side javascript that will figure out what the
> user clicked and do a parametrized request. Which I can do, but I'm
> wondering if someone has figured out a clever way how to map the
> information on the page to smalltalk objects on the server (other than
> using callback registry). Same goes for bulk actions involving
> multiple items ("delete selected" and the like).

I don't think there's an alternative. Unfortunately callbacks are
currently hard wired to read only one request field. In addition if
you move the code to a request handler it is hard to access the
session from there :-(

Cheers
Philippe
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Strategies for bulky renders/updates

Levente Uzonyi-2
In reply to this post by radoslav hodnicak
On Sun, 13 Mar 2011, radoslav hodnicak wrote:

> I've been using seaside with jquery to create quite interactive
> interfaces, using the simplest approach of "everything has its own
> callback". This works well if the dataset you're working with is
> small, but I'm now venturing into territories where it takes seconds
> to receive+render a page, which isn't acceptable.
>
> For an example of what I'm talking about imagine a page showing a list
> of emails. Every line (email) has a clickable sender, subject, date,
> and a bunch of more actions and icons etc. If you're creating
> anchors/click actions for each field separately, that's easily
> hundreds or thousands of callbacks per page, each needing to be
> generated on the server and sent over the wire. So clearly I need to
> instead write client side javascript that will figure out what the
> user clicked and do a parametrized request. Which I can do, but I'm
> wondering if someone has figured out a clever way how to map the
> information on the page to smalltalk objects on the server (other than
> using callback registry). Same goes for bulk actions involving
> multiple items ("delete selected" and the like).

We implemented a hack, that does the following:
Instead of Seaside callbacks we implemented our own lightweight callbacks
on top of Seaside's.
We have a method, that accepts a block and a seaside canvas. The receiver
(typically a WAComponent) of the message has an OrderedCollection which
stores the callback blocks.
When you send the method, it adds the block to the collection and returns
a piece of javascript which calls a function with the index of the block
in the collection. The returned javascript code is passed to #onClick:,
#onChange:, etc. Something like:

  html button
  onClick: (self
  lightweightCallBackOn: html
  do: [ self buttonClicked ]);
  with: 'Click me!'

The generated html will be something like:

<button onclick="c1lc(1)">Click me!</button>

The javascript function (c1lc in this case) is built using Seaside's js
code generator when the page is rendered and it's added with
#addLoadScript: to page.
The generated function triggers a Seaside JQuery callback. The callback
accepts the index as argument, looks up the block by index and evaluates
it.


Levente

>
> rado
> _______________________________________________
> seaside mailing list
> [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
>
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Strategies for bulky renders/updates

Johan Brichau-2
In reply to this post by radoslav hodnicak
We have encountered a similar issue when generating lists of thousands of elements that each needed interactivity client-side. However, the issue was more related to having a jQuery editable for each of those html elements, which took seconds to register on each element separately. But the issue is identical in the sense that we needed to revert to a single Seaside callback that is triggered by a Javascript function.

The solution boils down to the following:
- have a unique identifier for each of the objects that allows a mapping from the identifier back to the object (e.g. we have unique keys for all objects in our db)
- define a single seaside callback for the click event inside a javascript function
- define the click event on the applicable html entities to use the above javascript function (e.g. using jQuery).

The first item depends on how your application works. In the snippets below, I assume that <yourObjectRegistry> is a dictionary that allows a mapping from id to the object. These snippets illustrate how to achieve the second and third item.

* Assign the seaside callback to a javascript function upon page load:

        html document addLoadScript:
                ((html jQuery ajax
                                callback: [:id | (yourObjectRegistry at: id) doYourAction ]
                                value: (JSStream on: 'id')) asFunction: #(id))
                        assignTo: 'clickAction'

* Register the click events on each applicable html element such that they call the previously defined javascript function:

        html listItem
                onClick: (JSStream on: 'clickAction($(this).id)');
                with: [ ... ]


I hope this helps you out. But I'm not sure if that will really improve page rendering speed or size. The size of the callback url is not that much different from the size of the onClick event script.
In our case, by doing the above, we did not need to include the triggering of a jQuery editable for each generated html element. That resulted in a 10 times page rendering speedup because the load script was not registering the +1000 editables anymore.
But let us know how it went!

Johan

On 13 Mar 2011, at 03:21, radoslav hodnicak wrote:

> I've been using seaside with jquery to create quite interactive
> interfaces, using the simplest approach of "everything has its own
> callback". This works well if the dataset you're working with is
> small, but I'm now venturing into territories where it takes seconds
> to receive+render a page, which isn't acceptable.
>
> For an example of what I'm talking about imagine a page showing a list
> of emails. Every line (email) has a clickable sender, subject, date,
> and a bunch of more actions and icons etc. If you're creating
> anchors/click actions for each field separately, that's easily
> hundreds or thousands of callbacks per page, each needing to be
> generated on the server and sent over the wire. So clearly I need to
> instead write client side javascript that will figure out what the
> user clicked and do a parametrized request. Which I can do, but I'm
> wondering if someone has figured out a clever way how to map the
> information on the page to smalltalk objects on the server (other than
> using callback registry). Same goes for bulk actions involving
> multiple items ("delete selected" and the like).
>
> rado
> _______________________________________________
> seaside mailing list
> [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside

_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Strategies for bulky renders/updates

radoslav hodnicak
Yes Johan, I've been thinking along similar lines, with the exception
that what I really want to do is to register one seaside callback and
one javascript event handler on the parent object. For example, if you
have a table/list with 500 cells, you don't attach an event handler to
each cell, but one to the table itself, or to a container above it.
This will speed up page generation/rendering a lot. The handler will
then look at the id/class of the cell that generated the event and
figure out what to do/send to seaside.

rado

On Sun, Mar 13, 2011 at 1:56 PM, Johan Brichau <[hidden email]> wrote:

> We have encountered a similar issue when generating lists of thousands of elements that each needed interactivity client-side. However, the issue was more related to having a jQuery editable for each of those html elements, which took seconds to register on each element separately. But the issue is identical in the sense that we needed to revert to a single Seaside callback that is triggered by a Javascript function.
>
> The solution boils down to the following:
> - have a unique identifier for each of the objects that allows a mapping from the identifier back to the object (e.g. we have unique keys for all objects in our db)
> - define a single seaside callback for the click event inside a javascript function
> - define the click event on the applicable html entities to use the above javascript function (e.g. using jQuery).
>
> The first item depends on how your application works. In the snippets below, I assume that <yourObjectRegistry> is a dictionary that allows a mapping from id to the object. These snippets illustrate how to achieve the second and third item.
>
> * Assign the seaside callback to a javascript function upon page load:
>
>        html document addLoadScript:
>                ((html jQuery ajax
>                                callback: [:id | (yourObjectRegistry at: id) doYourAction ]
>                                value: (JSStream on: 'id')) asFunction: #(id))
>                        assignTo: 'clickAction'
>
> * Register the click events on each applicable html element such that they call the previously defined javascript function:
>
>        html listItem
>                onClick: (JSStream on: 'clickAction($(this).id)');
>                with: [ ... ]
>
>
> I hope this helps you out. But I'm not sure if that will really improve page rendering speed or size. The size of the callback url is not that much different from the size of the onClick event script.
> In our case, by doing the above, we did not need to include the triggering of a jQuery editable for each generated html element. That resulted in a 10 times page rendering speedup because the load script was not registering the +1000 editables anymore.
> But let us know how it went!
>
> Johan
>
> On 13 Mar 2011, at 03:21, radoslav hodnicak wrote:
>
>> I've been using seaside with jquery to create quite interactive
>> interfaces, using the simplest approach of "everything has its own
>> callback". This works well if the dataset you're working with is
>> small, but I'm now venturing into territories where it takes seconds
>> to receive+render a page, which isn't acceptable.
>>
>> For an example of what I'm talking about imagine a page showing a list
>> of emails. Every line (email) has a clickable sender, subject, date,
>> and a bunch of more actions and icons etc. If you're creating
>> anchors/click actions for each field separately, that's easily
>> hundreds or thousands of callbacks per page, each needing to be
>> generated on the server and sent over the wire. So clearly I need to
>> instead write client side javascript that will figure out what the
>> user clicked and do a parametrized request. Which I can do, but I'm
>> wondering if someone has figured out a clever way how to map the
>> information on the page to smalltalk objects on the server (other than
>> using callback registry). Same goes for bulk actions involving
>> multiple items ("delete selected" and the like).
>>
>> rado
>> _______________________________________________
>> seaside mailing list
>> [hidden email]
>> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
>
> _______________________________________________
> seaside mailing list
> [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
>
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Strategies for bulky renders/updates

radoslav hodnicak
I should add that my previous post is not a call for assistance. I
know how to do it :-)

On Sun, Mar 13, 2011 at 3:05 PM, radoslav hodnicak <[hidden email]> wrote:
> Yes Johan, I've been thinking along similar lines, with the exception that what I really want to do is to register one seaside callback and one javascript event handler on the parent object. For example, if you have a table/list with 500 cells, you don't attach an event handler to each cell, but one to the table itself, or to a container above it. This will speed up page generation/rendering a lot. The handler will then look at the id/class of the cell that generated the event and figure out what to do/send to seaside.
>
> rado
>
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Strategies for bulky renders/updates

mmimica
In reply to this post by Johan Brichau-2
Johan Brichau wrote:
>
> * Register the click events on each applicable html element such that they call the previously defined javascript function:
>
> html listItem
> onClick: (JSStream on: 'clickAction($(this).id)');
> with: [ ... ]
>

A was thinking about the same problem just today. A potential problem is that it
leaks IDs into HTML. One could easily guess a valid ID which maps to a database
object which he normally wouldn't have access to. Hm... unless you take special
care to obfuscate the ID.



--
Milan Mimica
http://sparklet.sf.net
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Strategies for bulky renders/updates

Philippe Marschall
2011/3/13 Milan Mimica <[hidden email]>:

> Johan Brichau wrote:
>>
>> * Register the click events on each applicable html element such that they
>> call the previously defined javascript function:
>>
>>        html listItem           onClick: (JSStream on:
>> 'clickAction($(this).id)');
>>                with: [ ... ]
>>
>
> A was thinking about the same problem just today. A potential problem is
> that it leaks IDs into HTML. One could easily guess a valid ID which maps to
> a database object which he normally wouldn't have access to. Hm... unless
> you take special care to obfuscate the ID.

Or encrypt them.

Cheers
Philippe
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Strategies for bulky renders/updates

radoslav hodnicak
In reply to this post by mmimica
Well I don't plan to use database IDs on the page directly - for one
they are like 20+ characters long (UUIDs), so that would defeat some
of the reasons for doing this (less data sent over the wire), and yes
it's a security hole. I'm just going to have an element id <-> object
mapping on the server, which isn't really different from having
callback IDs embedded in the html.

rado

On Sun, Mar 13, 2011 at 6:26 PM, Milan Mimica <[hidden email]> wrote:

> Johan Brichau wrote:
>>
>> * Register the click events on each applicable html element such that they
>> call the previously defined javascript function:
>>
>>        html listItem           onClick: (JSStream on:
>> 'clickAction($(this).id)');
>>                with: [ ... ]
>>
>
> A was thinking about the same problem just today. A potential problem is
> that it leaks IDs into HTML. One could easily guess a valid ID which maps to
> a database object which he normally wouldn't have access to. Hm... unless
> you take special care to obfuscate the ID.
>
>
>
> --
> Milan Mimica
> http://sparklet.sf.net
> _______________________________________________
> seaside mailing list
> [hidden email]
> http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
>
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Strategies for bulky renders/updates

mmimica
radoslav hodnicak wrote:
> Well I don't plan to use database IDs on the page directly - for one
> they are like 20+ characters long (UUIDs), so that would defeat some
> of the reasons for doing this (less data sent over the wire), and yes
> it's a security hole. I'm just going to have an element id <-> object
> mapping on the server, which isn't really different from having
> callback IDs embedded in the html.

The ID's are persistent, unlike Seaside callback urls. I think that's even more
important. One could reuse ID (encripted or not) later to access objects. I'm
just thinking about my aplication. It may not be an issue to some.


--
Milan Mimica
http://sparklet.sf.net
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Strategies for bulky renders/updates

sebastianconcept@gmail.co
In reply to this post by radoslav hodnicak
no pun intended, but is a design issue (and not a seaside one)

It sounds like you really need to re-think the UX 

a strong signal of that is that lists presenting thousands of items to a human being are hardly useful

alternatives?

think in some kind of aggregation (meaningful to the domain of the app) that can be navigated (drill down) to smaller lists

then you'll find out that all those issues are gone (including the security-related ones) and the app's usability gets increased



On Mar 12, 2011, at 11:21 PM, radoslav hodnicak wrote:

I've been using seaside with jquery to create quite interactive
interfaces, using the simplest approach of "everything has its own
callback". This works well if the dataset you're working with is
small, but I'm now venturing into territories where it takes seconds
to receive+render a page, which isn't acceptable.

For an example of what I'm talking about imagine a page showing a list
of emails. Every line (email) has a clickable sender, subject, date,
and a bunch of more actions and icons etc. If you're creating
anchors/click actions for each field separately, that's easily
hundreds or thousands of callbacks per page, each needing to be
generated on the server and sent over the wire. So clearly I need to
instead write client side javascript that will figure out what the
user clicked and do a parametrized request. Which I can do, but I'm
wondering if someone has figured out a clever way how to map the
information on the page to smalltalk objects on the server (other than
using callback registry). Same goes for bulk actions involving
multiple items ("delete selected" and the like).

rado
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside


_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Strategies for bulky renders/updates

Stephan Eggermont-3
In reply to this post by radoslav hodnicak
Sebastian wrote
>It sounds like you really need to re-think the UX
>a strong signal of that is that lists presenting thousands of items to a human being >are hardly useful

Excel has its usability problems, but I think you're being too harsh here :)
My OpenOffice spreadsheet shows 1700 cells at 100% in a full screen window.

Stephan


_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Strategies for bulky renders/updates

Stephan Eggermont-3
In reply to this post by radoslav hodnicak
Milan wrote:
>A potential problem is that it leaks IDs into HTML.
>One could easily guess a valid ID which maps to a database
> object which he normally wouldn't have access to.
>Hm... unless you take special care to obfuscate the ID.

Basic security would be to always use a mapping dictionary
and generate IDs.

Stephan

_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Strategies for bulky renders/updates

sebastianconcept@gmail.co
In reply to this post by Stephan Eggermont-3
caution my friend...  you're playing with the dark side here

do you really want me to start about excel?

give me the signal and I'll merciless unleash all the horses :D



On Mar 14, 2011, at 3:32 PM, Stephan Eggermont wrote:

Sebastian wrote
It sounds like you really need to re-think the UX
a strong signal of that is that lists presenting thousands of items to a human being >are hardly useful

Excel has its usability problems, but I think you're being too harsh here :)
My OpenOffice spreadsheet shows 1700 cells at 100% in a full screen window.

Stephan


_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside


_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: Strategies for bulky renders/updates

Intrader Intrader
In reply to this post by Levente Uzonyi-2
Levente, that is really clever hack. I have grids that may gain from this
technique.
Could you share the code?
Thanks


_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside