how to render access to a JS argument variable?

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

how to render access to a JS argument variable?

Chris Muller-4
Hi all, by using a process of "simplifying until it works" I think I'm
slowly "getting it".  However, now I've arrived at something very
simple which isn't working, and I don't know what I'm doing wrong.

Can someone tell me whats wrong with this Javascript that I'm getting
the message "Uncaught SyntaxError: Unexpected token ("?

   <span class="PufMessageWidget" id="id3"
onclick="function(event){console.log(&quot;event&quot;)}">my
content</span>

Here's the code I'm using to render the above:

    html span
         class: 'PufMessageWidget' ;
         id: (self assureHtmlIdUsing: html) ;
         onClick: ((html javascript logger call: 'log' with: 'event')
asFunction: #('event')).

And, this leads to my second question.  Even if the script above
didn't cause a SyntaxError, I want to log the event *variable* in the
console, not the string "event".

Any help is greatly appreciated..

PS -- Okay, I just noticed if I don't pass the #asFunction:
#('event'), I get 'event' in the console without any SyntaxErrors.
But, clearly, what I'm wanting to do should work should't it?
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: how to render access to a JS argument variable?

Chris Muller-3
Found something.  JSAlias.

>     html span
>          class: 'PufMessageWidget' ;
>          id: (self assureHtmlIdUsing: html) ;
>          onClick: ((html javascript logger call: 'log' with: 'event')
> asFunction: #('event')).

I gave up on onClick: since I guess its better to set up event
bindings through jQuery's API.  This binding does what I want, no
syntax error.

     html script defer with:
          ((html jQuery id: (self assureHtmlIdUsing: html)) onClick:
               ((html javascript logger call: 'log' with: (html
javascript alias: 'event')) asFunction: #('event'))).

It seems like a pretty wordy way to write console.log(event), but the
intent reads clearly so, that's good..
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: how to render access to a JS argument variable?

Johan Brichau-2
Hi Chris,

I notice you figured out the use of #alias:

Use the JS generation facilities only when you need to *generate* code. For example, to embed a server-side callback or, in general, when the code can only be dynamically constructed.
In your case, I would do the following:

(JSStream on: ‘console.log(event)’)

Just because you can write it in Smalltalk does not mean you should :)

Johan

ps: your contributions are in my inbox, I will process them asap

> On 09 Oct 2015, at 03:46, Chris Muller <[hidden email]> wrote:
>
> Found something.  JSAlias.
>
>>    html span
>>         class: 'PufMessageWidget' ;
>>         id: (self assureHtmlIdUsing: html) ;
>>         onClick: ((html javascript logger call: 'log' with: 'event')
>> asFunction: #('event')).
>
> I gave up on onClick: since I guess its better to set up event
> bindings through jQuery's API.  This binding does what I want, no
> syntax error.
>
>     html script defer with:
>          ((html jQuery id: (self assureHtmlIdUsing: html)) onClick:
>               ((html javascript logger call: 'log' with: (html
> javascript alias: 'event')) asFunction: #('event'))).
>
> It seems like a pretty wordy way to write console.log(event), but the
> intent reads clearly so, that's good..
> _______________________________________________
> 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: how to render access to a JS argument variable?

Chris Muller-3
Thanks Johan, that's the kind of advice I need, as there are many ways to do things.

Now, I am stumped (for hours!) on another very similar problem, except instead of a single variable, I simply want to pass an argument of type "jQuery" into jQuery's replaceWith() function, called within a onClick handler method.  So, in my renderContentOn:, I wrote:

     | ajaxRequest |
     ajaxRequest := (html jQuery post
          url: html actionUrl;
          dataType: 'html') html: [  : replaceHtml | self invoke.  replaceHtml render: resultWidget ].
           ....
     html script defer with:
          ((html jQuery id: buttonId) onClick:
               ((html jQuery id: replacementId) replaceWith: ajaxRequest asJavascript) asFunction).

However, as before, the argument to replaceWith() is being rendered as a Javascript string literal instead of the code itself.  (See red quotes, below, I want it to stop rendering those quotes!).

    $("#id3").click(function(){$("#id4").replaceWith("$.post(&quot;/puf&quot;,[&quot;_s=C8vA8l5UNoUsGTpf&quot;,&quot;_k=B_Wk6EYdovACqAgV&quot;,&quot;2&quot;].join(&quot;&amp;&quot;),&quot;html&quot;)")})

I tried many different variations, no success.  This must be something simple...

Thank you.

On Fri, Oct 9, 2015 at 2:25 AM, Johan Brichau <[hidden email]> wrote:
Hi Chris,

I notice you figured out the use of #alias:

Use the JS generation facilities only when you need to *generate* code. For example, to embed a server-side callback or, in general, when the code can only be dynamically constructed.
In your case, I would do the following:

(JSStream on: ‘console.log(event)’)

Just because you can write it in Smalltalk does not mean you should :)

Johan

ps: your contributions are in my inbox, I will process them asap

> On 09 Oct 2015, at 03:46, Chris Muller <[hidden email]> wrote:
>
> Found something.  JSAlias.
>
>>    html span
>>         class: 'PufMessageWidget' ;
>>         id: (self assureHtmlIdUsing: html) ;
>>         onClick: ((html javascript logger call: 'log' with: 'event')
>> asFunction: #('event')).
>
> I gave up on onClick: since I guess its better to set up event
> bindings through jQuery's API.  This binding does what I want, no
> syntax error.
>
>     html script defer with:
>          ((html jQuery id: (self assureHtmlIdUsing: html)) onClick:
>               ((html javascript logger call: 'log' with: (html
> javascript alias: 'event')) asFunction: #('event'))).
>
> It seems like a pretty wordy way to write console.log(event), but the
> intent reads clearly so, that's good..
> _______________________________________________
> 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: how to render access to a JS argument variable?

Chris Muller-3
Wow, all I need to do is work up an email question, and it seems to lead myself to a solution!   :-)   In this case, I can't use JQueryInstance>>#replaceWith: only lets the user pass a String argument, not a jQuery argument.  Because the version of JSObject>>#render: always returns a String no matter what, which will never let a JSObject subclass render its code onto the stream.  Strange!

And, so, the solution was to #call: 'replaceWith' with: myJQPost myself.  Here is the code, for comparison to the original:

     html script defer with:
          ((html jQuery id: buttonId) onClick:
               ((html jQuery id: replacementId) call: 'replaceWith' with: ajaxRequest) asFunction).

I think this is slowing my learning of Seaside -- the thought that I should be able to use all the convenience methods and get all the power of JQuery, but, in fact, some of these methods provide no way to render the other versions of the jQuery calls which take different argument types.  Only the string types are supported.  Am I right about this?

Another example is the "data" argument of a $.ajax(...) request.  Seaside renders a Javascript array, but then calls .join("&") on it!  Strings only....  :(


On Fri, Oct 9, 2015 at 4:52 PM, Chris Muller <[hidden email]> wrote:
Thanks Johan, that's the kind of advice I need, as there are many ways to do things.

Now, I am stumped (for hours!) on another very similar problem, except instead of a single variable, I simply want to pass an argument of type "jQuery" into jQuery's replaceWith() function, called within a onClick handler method.  So, in my renderContentOn:, I wrote:

     | ajaxRequest |
     ajaxRequest := (html jQuery post
          url: html actionUrl;
          dataType: 'html') html: [  : replaceHtml | self invoke.  replaceHtml render: resultWidget ].
           ....
     html script defer with:
          ((html jQuery id: buttonId) onClick:
               ((html jQuery id: replacementId) replaceWith: ajaxRequest asJavascript) asFunction).

However, as before, the argument to replaceWith() is being rendered as a Javascript string literal instead of the code itself.  (See red quotes, below, I want it to stop rendering those quotes!).

    $("#id3").click(function(){$("#id4").replaceWith("$.post(&quot;/puf&quot;,[&quot;_s=C8vA8l5UNoUsGTpf&quot;,&quot;_k=B_Wk6EYdovACqAgV&quot;,&quot;2&quot;].join(&quot;&amp;&quot;),&quot;html&quot;)")})

I tried many different variations, no success.  This must be something simple...

Thank you.

On Fri, Oct 9, 2015 at 2:25 AM, Johan Brichau <[hidden email]> wrote:
Hi Chris,

I notice you figured out the use of #alias:

Use the JS generation facilities only when you need to *generate* code. For example, to embed a server-side callback or, in general, when the code can only be dynamically constructed.
In your case, I would do the following:

(JSStream on: ‘console.log(event)’)

Just because you can write it in Smalltalk does not mean you should :)

Johan

ps: your contributions are in my inbox, I will process them asap

> On 09 Oct 2015, at 03:46, Chris Muller <[hidden email]> wrote:
>
> Found something.  JSAlias.
>
>>    html span
>>         class: 'PufMessageWidget' ;
>>         id: (self assureHtmlIdUsing: html) ;
>>         onClick: ((html javascript logger call: 'log' with: 'event')
>> asFunction: #('event')).
>
> I gave up on onClick: since I guess its better to set up event
> bindings through jQuery's API.  This binding does what I want, no
> syntax error.
>
>     html script defer with:
>          ((html jQuery id: (self assureHtmlIdUsing: html)) onClick:
>               ((html javascript logger call: 'log' with: (html
> javascript alias: 'event')) asFunction: #('event'))).
>
> It seems like a pretty wordy way to write console.log(event), but the
> intent reads clearly so, that's good..
> _______________________________________________
> 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: how to render access to a JS argument variable?

Johan Brichau-2
Hi Chris,

jQuery’s replaceWith accepts either an html string or a javascript function. I believe this is also true for the Seaside binding implementation.
Does the following code not do what you want?

 html script defer with:
          ((html jQuery id: buttonId) onClick:
               ((html jQuery id: replacementId) call: 'replaceWith' with: ajaxRequest asFunction)).

The JSObject>>render: method should always produce a string, as it is called when the object needs to be rendered on a stream. It does not produce a ‘javascript string’.
What you want is to construct a function and give it as an argument to the replaceWith function (see code above). Imho, that should work.

Johan

On 10 Oct 2015, at 00:14, Chris Muller <[hidden email]> wrote:

Wow, all I need to do is work up an email question, and it seems to lead myself to a solution!   :-)   In this case, I can't use JQueryInstance>>#replaceWith: only lets the user pass a String argument, not a jQuery argument.  Because the version of JSObject>>#render: always returns a String no matter what, which will never let a JSObject subclass render its code onto the stream.  Strange!

And, so, the solution was to #call: 'replaceWith' with: myJQPost myself.  Here is the code, for comparison to the original:

     html script defer with:
          ((html jQuery id: buttonId) onClick:
               ((html jQuery id: replacementId) call: 'replaceWith' with: ajaxRequest) asFunction).

I think this is slowing my learning of Seaside -- the thought that I should be able to use all the convenience methods and get all the power of JQuery, but, in fact, some of these methods provide no way to render the other versions of the jQuery calls which take different argument types.  Only the string types are supported.  Am I right about this?

Another example is the "data" argument of a $.ajax(...) request.  Seaside renders a Javascript array, but then calls .join("&") on it!  Strings only....  :(


On Fri, Oct 9, 2015 at 4:52 PM, Chris Muller <[hidden email]> wrote:
Thanks Johan, that's the kind of advice I need, as there are many ways to do things.

Now, I am stumped (for hours!) on another very similar problem, except instead of a single variable, I simply want to pass an argument of type "jQuery" into jQuery's replaceWith() function, called within a onClick handler method.  So, in my renderContentOn:, I wrote:

     | ajaxRequest |
     ajaxRequest := (html jQuery post
          url: html actionUrl;
          dataType: 'html') html: [  : replaceHtml | self invoke.  replaceHtml render: resultWidget ].
           ....
     html script defer with:
          ((html jQuery id: buttonId) onClick:
               ((html jQuery id: replacementId) replaceWith: ajaxRequest asJavascript) asFunction).

However, as before, the argument to replaceWith() is being rendered as a Javascript string literal instead of the code itself.  (See red quotes, below, I want it to stop rendering those quotes!).

    $("#id3").click(function(){$("#id4").replaceWith("$.post(&quot;/puf&quot;,[&quot;_s=C8vA8l5UNoUsGTpf&quot;,&quot;_k=B_Wk6EYdovACqAgV&quot;,&quot;2&quot;].join(&quot;&amp;&quot;),&quot;html&quot;)")})

I tried many different variations, no success.  This must be something simple...

Thank you.

On Fri, Oct 9, 2015 at 2:25 AM, Johan Brichau <[hidden email]> wrote:
Hi Chris,

I notice you figured out the use of #alias:

Use the JS generation facilities only when you need to *generate* code. For example, to embed a server-side callback or, in general, when the code can only be dynamically constructed.
In your case, I would do the following:

(JSStream on: ‘console.log(event)’)

Just because you can write it in Smalltalk does not mean you should :)

Johan

ps: your contributions are in my inbox, I will process them asap

> On 09 Oct 2015, at 03:46, Chris Muller <[hidden email]> wrote:
>
> Found something.  JSAlias.
>
>>    html span
>>         class: 'PufMessageWidget' ;
>>         id: (self assureHtmlIdUsing: html) ;
>>         onClick: ((html javascript logger call: 'log' with: 'event')
>> asFunction: #('event')).
>
> I gave up on onClick: since I guess its better to set up event
> bindings through jQuery's API.  This binding does what I want, no
> syntax error.
>
>     html script defer with:
>          ((html jQuery id: (self assureHtmlIdUsing: html)) onClick:
>               ((html javascript logger call: 'log' with: (html
> javascript alias: 'event')) asFunction: #('event'))).
>
> It seems like a pretty wordy way to write console.log(event), but the
> intent reads clearly so, that's good..
> _______________________________________________
> 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


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

Re: how to render access to a JS argument variable?

Chris Muller-4
Hi,

> jQuery’s replaceWith accepts either an html string or a javascript function.

I was looking at the JQuery API at

   http://api.jquery.com/replaceWith

which says it can take a "htmlString or Element or Array or jQuery",
OR a Function.  I mistakenly thought Seasides helper methods could
support all the types.  They don't.

> I believe this is also true for the Seaside binding implementation.
> Does the following code not do what you want?
>
>  html script defer with:
>           ((html jQuery id: buttonId) onClick:
>                ((html jQuery id: replacementId) call: 'replaceWith' with:
> ajaxRequest asFunction)).

Yes, call:with: does.  I was just suprised that Seaside's helper
method, JQueryInstance>>#replaceWith: can only support the htmlString
argument variation, not Element nor Array nor jQuery nor Function.
For those, one must write the #call:with: variation.  Given all the
other ways Seaside lets me write terse code, I was fooled for an
entire afternoon into thinking I could shoe-horn it in via
replaceWith: helper method.    :/

> The JSObject>>render: method should always produce a string, as it is called
> when the object needs to be rendered on a stream. It does not produce a
> ‘javascript string’.

Hm, looking closely, it seems like replaceWith: does only ever produce
a javascript string.  By the implementation passing in a String from
render::

    self call: 'someFunction' with: (self render: aRenderable)

and by call:with: implemented as:

    self call: aString withArguments: (Array with: anObject)

then what we get for the withArguments: is always an Array of one
String, which is rendered in double-quotes as a javascript "string".

It seems like if the replaceWith: were implemented as:

     self call 'replaceWith' with: aRenderable

then maybe they could support all the argument variations specified at
api.jquery.com, and not only the String variations.

And, indeed, the *vast majority* of senders of call:with: simply pass
the argument directly, thus truly providing merely the syntactic sugar
and nothing more..  But, for some reason, #after:, #append:, #before:,
#html:, #prepend:, #replaceWith:, #wrap:, #wrapAll:, #wrapInner: all
have that (self render: aRenderable) which forces the String arg...
_______________________________________________
seaside mailing list
[hidden email]
http://lists.squeakfoundation.org/cgi-bin/mailman/listinfo/seaside
Reply | Threaded
Open this post in threaded view
|

Re: how to render access to a JS argument variable?

Johan Brichau-2
Hi Chris,

You are right, I was looking at the wrong places and responded too quickly.

> It seems like if the replaceWith: were implemented as:
>
>     self call 'replaceWith' with: aRenderable
>
> then maybe they could support all the argument variations specified at
> api.jquery.com, and not only the String variations.

True, but that will break the most common use of those methods: passing in a Smalltalk block or a Seaside component (i.e. any Renderable).

Somehow, your use case has never popped up before, but it’s interesting to see if we could make that work.
The JSObject>>render:on: is used when the script is actually rendered in the html, so it seems difficult to change it there.

Instead of ommitting the call to #render: from #replaceWith:, I’m guessing a different method needs to be introduced which renders any renderable but does nothing with a JSObject.
We can try...

> And, indeed, the *vast majority* of senders of call:with: simply pass
> the argument directly, thus truly providing merely the syntactic sugar
> and nothing more..  But, for some reason, #after:, #append:, #before:,
> #html:, #prepend:, #replaceWith:, #wrap:, #wrapAll:, #wrapInner: all
> have that (self render: aRenderable) which forces the String arg...


If I understand what you are trying to do in the example snippets, the typical way we would write this in the Seaside binding is like this:

(html jQuery id: buttonId) onClick: (html jQuery ajax script: [:s | s << ((s jQuery id: replacementId) replaceWith: resultWidget) ])

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