Sending messages to javascript objects

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

Sending messages to javascript objects

Andres Fortier-2
Hi list,
           from the examples I've seen so far, the
basic mechanism to update (a part of) a page is to
split the page rendering in many #renderXYZOn: and then
using an updater to refresh a specific part of the page
by calling the appropriate #renderXYZOn:.

Now, even though possible, in some cases it is a waste
of user time and bandwidth to re-render a whole
component, when that can be done by just sending a
javascript message. To be concrete, suppose I have a
page with a google map component and a checkbox to
decide whether the map should show the google bar or
not. Using the first approach, the page would look like:

html checkbox
                value: self map isGoogleBarEnabled;
                onChange: (html updater
                                                id: self map containerId;
                                                callback: [:renderer |
                                                                                self map toggleGoogleBar.
                                                                                renderer render: self map]).

however, this means that toggling a checkbox would
reload the whole map, which is definitely perceived by
the user and expensive in terms of network bandwidth.
Now, in terms of javascript this can be achieved by
just sending the message enable/disableGoogleBar() to
the map object, which can be coded as:

html checkbox
                id: 'choice_chk';
                value: self map isGoogleBarEnabled;
                onChange: ('if
(document.getElementById(''choice_chk'').checked)
                                                        {' , self map id , '.enableGoogleBar();}
                                                        else {' , self map id , '.disableGoogleBar();}').

However, this approach means that:
1. The map model living in the Smalltalk image (i.e.
"self map") is not synchronized with the map in the
page, since it didn't receive the toggle notification.
2. The script is "static" in terms that it can't take
decisions in terms of the current state of the St
image. It can just code the app state in the script at
the time the page was rendered, something that may not
be consistent over time.
3. Even though a definitely minor issue, I have to
write javascript.

To solve the first problem the first thing that comes
to my mind is replicating the effort, by also attaching
a callback that updates the model, which I'm not very
fond of.  The second one seems a bit more weird, since
I would need to coordinate St objects with javascript
objects. So I was wondering if there already is a
standard mechanism to handle this kind of situations. I
started thinking about a seamless way of interacting
with javascript objects from  Smalltalk by some sort of
proxies, but I don't want to put up a new machinery if
there this has already been solved.

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

Re: Sending messages to javascript objects

Sophie424
"Andres Fortier" <[hidden email]> wrote in message

> Now, even though possible, in some cases it is a waste of user time and
> bandwidth to re-render a whole component

Updater can update any element with an html id, even an individual checkbox.

e.g.

onClick: (html updater
    id: tinyElementId;
    callback: [ : r | self renderTinyElementOn: r]);


You can assign elements ids while they are being rendered using
    html nextId

Hth,

Sophie



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

Re: Re: Sending messages to javascript objects

Igor Stasenko
2008/4/25 itsme213 <[hidden email]>:

> "Andres Fortier" <[hidden email]> wrote in message
>
>
>  > Now, even though possible, in some cases it is a waste of user time and
>  > bandwidth to re-render a whole component
>
>  Updater can update any element with an html id, even an individual checkbox.
>
>  e.g.
>
>  onClick: (html updater
>     id: tinyElementId;
>     callback: [ : r | self renderTinyElementOn: r]);
>
>
>  You can assign elements ids while they are being rendered using
>     html nextId
>

This is not an option for given case.
Using scripts for handling user interaction is good way to prevent
excess network activity and we need to think about, how
to make it more easy.

>From my own experience this was not very easy.
In my case, when user clicked on button , i wanted to show an element
if it's not visible, and hide it if it was visible.
In own turn an element contents, when shown first time, should be
loaded using updater, so initially page doesn't contain everything and
this is not plain simple show/hide switch.
The script which i produced was a bit long (check element visibility,
call updater when showing first time and after update finished, make
it appear with fancy effect), and it would be much better to place it
in separate js function, otherwise, if i having 20 switches on page,
page contains too much repeating code.

So, i proposing something like:
onClick: (html callMethod: #foo of: self  with: self element id with:
10 with: 20)

now, a MyComponent>>foo:x:y: can look like:

foo
^
'function foo (element, x, y) {
   element.position.x = x; element.position.y = y; } '

And in HTML, seaside should generate something like:
.. <tag ... onClick = "foo(5,10,20)"> ..

And finally, don't forget that we need to add new script to #updateRoot:

updateRoot: htmlRoot
  htmlRoot addScript: self foo.

What i don't like in code above:
- script it is added manually, it would be more convenient to add it
automatically (as result of call to html callMethod: #foo of: ...)
- html root having no option to inline script in html, instead it
generates <script src=..>, it would be good to have an option (a
method, like WAHtmlRoot>>addScriptInline:, which will generate script
with source inlined on page, because browser losing much more time to
load script using separate request rather than simply parse few lines
of code , and if your page contains too much scripts , a page load
time can be  slowed down dramatically.



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



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

Re: Re: Sending messages to javascript objects

Randal L. Schwartz
>>>>> "Igor" == Igor Stasenko <[hidden email]> writes:

Igor> Using scripts for handling user interaction is good way to prevent
Igor> excess network activity and we need to think about, how
Igor> to make it more easy.

This is precisely why I want to support YUI... the widgets are mature,
supported, and rich.  Unfortunately, I've been too busy making Smalltalk
famous again to work on my client's project where YUI will be needed. :)

--
Randal L. Schwartz - Stonehenge Consulting Services, Inc. - +1 503 777 0095
<[hidden email]> <URL:http://www.stonehenge.com/merlyn/>
Perl/Unix/security consulting, Technical writing, Comedy, etc. etc.
See PerlTraining.Stonehenge.com for onsite and open-enrollment Perl training!
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

RE: Re: Sending messages to javascript objects

Ramon Leon-5
In reply to this post by Igor Stasenko
> And finally, don't forget that we need to add new script to
> #updateRoot:

Why?

>
> updateRoot: htmlRoot
>   htmlRoot addScript: self foo.
>
> What i don't like in code above:
> - script it is added manually, it would be more convenient to
> add it automatically (as result of call to html callMethod:
> #foo of: ...)
> - html root having no option to inline script in html,
> instead it generates <script src=..>, it would be good to
> have an option (a method, like WAHtmlRoot>>addScriptInline:,
> which will generate script with source inlined on page,
> because browser losing much more time to load script using
> separate request rather than simply parse few lines of code ,
> and if your page contains too much scripts , a page load time
> can be  slowed down dramatically.

You most certainly can render inline script directly, no need to attach to
head...

renderContentOn: html
 html script: 'alert("hello")'

Ramon Leon
http://onsmalltalk.com

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

Re: Re: Sending messages to javascript objects

Igor Stasenko
2008/4/25 Ramon Leon <[hidden email]>:

> > And finally, don't forget that we need to add new script to
>  > #updateRoot:
>
>  Why?
>
>
>  >
>  > updateRoot: htmlRoot
>  >   htmlRoot addScript: self foo.
>  >
>  > What i don't like in code above:
>  > - script it is added manually, it would be more convenient to
>  > add it automatically (as result of call to html callMethod:
>  > #foo of: ...)
>  > - html root having no option to inline script in html,
>  > instead it generates <script src=..>, it would be good to
>  > have an option (a method, like WAHtmlRoot>>addScriptInline:,
>  > which will generate script with source inlined on page,
>  > because browser losing much more time to load script using
>  > separate request rather than simply parse few lines of code ,
>  > and if your page contains too much scripts , a page load time
>  > can be  slowed down dramatically.
>
>  You most certainly can render inline script directly, no need to attach to
>  head...
>
>  renderContentOn: html
>   html script: 'alert("hello")'
>

This is not an option, suppose i'm using a component which represents
an item in list.
Now, for each item in list it will call  html script: '' and produce
many <script> tags for each item, while i need to add it only once.

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



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

Re: Re: Sending messages to javascript objects

Andres Fortier-2
Hi everybody,
                       thanks for the replies. So it
seems that there is no standard solution :(. What I am
thinking about is in modelling a scripting environment,
in Smalltalk, that would be translated into javascript.
So far I got the following things:

- A ScriptingEnvironment. This object is rendered
inside a div, with it's own particular id and is where
the javascript will be dynamically placed (btw, I
really don't like the name "Scripting Environment", but
I couldn't come up with something better).
- An extension to the WARenderCanvas to support the
message #scriptingEnvironment.
- The objects that will receive messages dynamically
must have an id (and maybe in the future they will have
to be subclass of a specific class -something like
ScriptableObject-)

So the idea is to do things like:

env:=(html scriptingEnvironment
                        callback: [:renderer | | proxy |
                                                        proxy:=self map scriptingProxy.
                                                        proxy enableGoogleBar.
                                                        renderer render: proxy.
                                                        ].
and:

html checkbox
                value: (self map isEnabled: anItemName);
                onChange: env.

the proxy via #dnu: encodes the message as a javascript
message send and the idea is that a scripting
environment uses an updater to reload a div, where the
script is coded, thus reinterpreting the script and
effectively sending the messages to the javascript
objects. This objects are defined as global variables
in the /window/ object, and thus are global to all
scripts. This last part is kind of a hack, but it works
ok (at least on FF).

Now, what I would really like to have is:

env:=(html scriptingEnvironment
                                callback: [self map enableGoogleBar].

and that the code inside the block is reinterpreted
because it is being executed in a scripting
environment; this means that the messages should be
sent to the proxy and the proxy should be rendered
afterwards. I'm looking into BlockContext at the moment
to see if this is possible. If we could do such a thing
we could dynamically send messages to javascript, but
writing everything as we are used in Smalltalk.

Any ideas are most appreciated.


Thanks again,
                        Andrés

Igor Stasenko escribió:

> 2008/4/25 Ramon Leon <[hidden email]>:
>>> And finally, don't forget that we need to add new script to
>>  > #updateRoot:
>>
>>  Why?
>>
>>
>>  >
>>  > updateRoot: htmlRoot
>>  >   htmlRoot addScript: self foo.
>>  >
>>  > What i don't like in code above:
>>  > - script it is added manually, it would be more convenient to
>>  > add it automatically (as result of call to html callMethod:
>>  > #foo of: ...)
>>  > - html root having no option to inline script in html,
>>  > instead it generates <script src=..>, it would be good to
>>  > have an option (a method, like WAHtmlRoot>>addScriptInline:,
>>  > which will generate script with source inlined on page,
>>  > because browser losing much more time to load script using
>>  > separate request rather than simply parse few lines of code ,
>>  > and if your page contains too much scripts , a page load time
>>  > can be  slowed down dramatically.
>>
>>  You most certainly can render inline script directly, no need to attach to
>>  head...
>>
>>  renderContentOn: html
>>   html script: 'alert("hello")'
>>
>
> This is not an option, suppose i'm using a component which represents
> an item in list.
> Now, for each item in list it will call  html script: '' and produce
> many <script> tags for each item, while i need to add it only once.
>
>>  Ramon Leon
>>  http://onsmalltalk.com
>>
>>
>>
>>  _______________________________________________
>>  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