[5.4] javascript - simplify the new paradigm please

classic Classic list List threaded Threaded
30 messages Options
12
Reply | Threaded
Open this post in threaded view
|

[5.4] javascript - simplify the new paradigm please

Paul Stanton
Hi,

so like many developers (i'm guessing) I'm not quite up to speed with
all these new javascript frameworks: requirejs, closure, etc etc and to
be honest I really didn't see a problem with the namespace model of the
past. I'm not open to learning but it seems like a paradigm far removed
from what i'm used to. it doesn't seem object oriented at all for example.

that aside, can someone please point me (and other readers) to some
basic examples to get us started in this brave new world. the first
thing I would like to achieve is to be able to call some page or
component specific marshalling code with page/component context parameters.

your helpful attitudes will be appreciated!

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: [5.4] javascript - simplify the new paradigm please

Thiago H de Paula Figueiredo
On Wed, 12 Nov 2014 09:13:43 -0200, Paul Stanton <[hidden email]>  
wrote:

> Hi,

Hi!

> so like many developers (i'm guessing) I'm not quite up to speed with  
> all these new javascript frameworks: requirejs, closure, etc etc

Require.js is actually used by Tapestry 5.4. I'm not sure what you mean by  
Closure (the JavaScript concept or some JS framework?) nor the etc part.  
If you want to learn about Require.js, read its documentation. :)

> and to be honest I really didn't see a problem with the namespace model  
> of the past.

It didn't work well (or at all) when, in a zone update, the response has  
JavaScript to be invoked. That's only one reason.

> I'm not open to learning but it seems like a paradigm far removed from  
> what i'm used to. it doesn't seem object oriented at all for example.

Yes, it is object-oriented, specially because it doesn't leak variables  
and functions from one piece of code to another, placing

> that aside, can someone please point me (and other readers) to some  
> basic examples to get us started in this brave new world. the first  
> thing I would like to achieve is to be able to call some page or  
> component specific marshalling code with page/component context  
> parameters.

What has your question has to do with Require.js and namespaces? I can't  
see, I'm sorry.

What do you mean by marshalling? Don't you know that, for JavaScript to  
page or component communication in Tapestry, you're much better off using  
query parameters than the context?

--
Thiago H. de Paula Figueiredo
Tapestry, Java and Hibernate consultant and developer
http://machina.com.br

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: [5.4] javascript - simplify the new paradigm please

Paul Stanton
Hi Thiago,

Firstly thanks for the reply.

Do you think you could put aside the dissection of my question and
defence of position and just answer the question to be helpful?

I am not trying to start an idealogical conversation or criticise anyone
or any way of thinking but would love for you to show me what the simple
recommended TAPESTRY RELATED usage is.

Thanks, p.

On 12/11/2014 11:44 PM, Thiago H de Paula Figueiredo wrote:

> On Wed, 12 Nov 2014 09:13:43 -0200, Paul Stanton
> <[hidden email]> wrote:
>
>> Hi,
>
> Hi!
>
>> so like many developers (i'm guessing) I'm not quite up to speed with
>> all these new javascript frameworks: requirejs, closure, etc etc
>
> Require.js is actually used by Tapestry 5.4. I'm not sure what you
> mean by Closure (the JavaScript concept or some JS framework?) nor the
> etc part. If you want to learn about Require.js, read its
> documentation. :)
>
>> and to be honest I really didn't see a problem with the namespace
>> model of the past.
>
> It didn't work well (or at all) when, in a zone update, the response
> has JavaScript to be invoked. That's only one reason.
>
>> I'm not open to learning but it seems like a paradigm far removed
>> from what i'm used to. it doesn't seem object oriented at all for
>> example.
>
> Yes, it is object-oriented, specially because it doesn't leak
> variables and functions from one piece of code to another, placing
>
>> that aside, can someone please point me (and other readers) to some
>> basic examples to get us started in this brave new world. the first
>> thing I would like to achieve is to be able to call some page or
>> component specific marshalling code with page/component context
>> parameters.
>
> What has your question has to do with Require.js and namespaces? I
> can't see, I'm sorry.
>
> What do you mean by marshalling? Don't you know that, for JavaScript
> to page or component communication in Tapestry, you're much better off
> using query parameters than the context?
>


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: [5.4] javascript - simplify the new paradigm please

Thiago H de Paula Figueiredo
On Wed, 12 Nov 2014 18:41:48 -0200, Paul Stanton <[hidden email]>  
wrote:

> Hi Thiago,

Hi!

> Do you think you could put aside the dissection of my question and  
> defence of position and just answer the question to be helpful?

Your questions were vague, so I couldn't provide a good answer.

> I am not trying to start an idealogical conversation or criticise anyone  
> or any way of thinking but would love for you to show me what the simple  
> recommended TAPESTRY RELATED usage is.

Ok, now I've got a non-vague, answerable question. :) See the "JavaScript  
Fixes" section of Bob Harner's blog post at  
https://github.com/bobharner/blog/wiki/Jumping-Into-Tapestry-5.4-Alpha-3.  
Also this thread with very informative posts by SlimerDude:  
http://apache-tapestry-mailing-list-archives.1045711.n5.nabble.com/5-4-Javascript-best-practices-td5719568.html

--
Thiago H. de Paula Figueiredo
Tapestry, Java and Hibernate consultant and developer
http://machina.com.br

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: [5.4] javascript - simplify the new paradigm please

Paul Stanton
In reply to this post by Paul Stanton
Or try this simple question:

How do I execute some javascript in the render phase of a component
which creates an object and then refer to that object when handling an
async event for the same component?

Please excuse me if this is documented somewhere, I cannot find it.

On 13/11/2014 7:41 AM, Paul Stanton wrote:

> Hi Thiago,
>
> Firstly thanks for the reply.
>
> Do you think you could put aside the dissection of my question and
> defence of position and just answer the question to be helpful?
>
> I am not trying to start an idealogical conversation or criticise
> anyone or any way of thinking but would love for you to show me what
> the simple recommended TAPESTRY RELATED usage is.
>
> Thanks, p.
>
> On 12/11/2014 11:44 PM, Thiago H de Paula Figueiredo wrote:
>> On Wed, 12 Nov 2014 09:13:43 -0200, Paul Stanton
>> <[hidden email]> wrote:
>>
>>> Hi,
>>
>> Hi!
>>
>>> so like many developers (i'm guessing) I'm not quite up to speed
>>> with all these new javascript frameworks: requirejs, closure, etc etc
>>
>> Require.js is actually used by Tapestry 5.4. I'm not sure what you
>> mean by Closure (the JavaScript concept or some JS framework?) nor
>> the etc part. If you want to learn about Require.js, read its
>> documentation. :)
>>
>>> and to be honest I really didn't see a problem with the namespace
>>> model of the past.
>>
>> It didn't work well (or at all) when, in a zone update, the response
>> has JavaScript to be invoked. That's only one reason.
>>
>>> I'm not open to learning but it seems like a paradigm far removed
>>> from what i'm used to. it doesn't seem object oriented at all for
>>> example.
>>
>> Yes, it is object-oriented, specially because it doesn't leak
>> variables and functions from one piece of code to another, placing
>>
>>> that aside, can someone please point me (and other readers) to some
>>> basic examples to get us started in this brave new world. the first
>>> thing I would like to achieve is to be able to call some page or
>>> component specific marshalling code with page/component context
>>> parameters.
>>
>> What has your question has to do with Require.js and namespaces? I
>> can't see, I'm sorry.
>>
>> What do you mean by marshalling? Don't you know that, for JavaScript
>> to page or component communication in Tapestry, you're much better
>> off using query parameters than the context?
>>
>


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: [5.4] javascript - simplify the new paradigm please

Thiago H de Paula Figueiredo
On Wed, 12 Nov 2014 19:08:44 -0200, Paul Stanton <[hidden email]>  
wrote:

> How do I execute some javascript in the render phase of a component  
> which creates an object and then refer to that object when handling an  
> async event for the same component?

It seems you want to invoke a page or component method from JavaScript. Is  
this correct? If yes, you need to do something like this in some render  
phase event handler method:

private static final String EVENT_NAME = "yourEventName";

@Inject
private JavaScriptSupport javaScriptSupport;

public setupRender() { // It could by afterRender() or beginRender() too.
        Link eventLink = resources.createEventLink(EVENT_NAME);
        String eventUrl = eventLink.toAbsoluteURI(); // this is your event URL
        javaScriptSupport.require("yourModuleName").with(eventUrl); // you pass  
the event URL to our JavaScript.
}

/** This method will be invoked */
@OnEvent(EVENT_NAME)
JSONObject handleMyAjaxEvent() {
        JSONObject object = new JSONObject(); The object containing the response,  
if any.
        ....
        return object;
       
}

The object part is basically having a field, very probably @Persist'ed,  
initialized on setupRender() and accessed in your new event handler. Of  
course, the best way of dealing this object is very dependent on its  
nature, so the answer above isn't very precise. What exactly are you  
trying to do? What does this object represent? Why do you need to access  
it through AJAX after the component or page render?

--
Thiago H. de Paula Figueiredo
Tapestry, Java and Hibernate consultant and developer
http://machina.com.br

---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: [5.4] javascript - simplify the new paradigm please

Kalle Korhonen-2
In reply to this post by Paul Stanton
Well, let me try to answer as well. I just rewrote one, simple old school
component to new T5.4, perhaps that's one good data point. I find that the
biggest difference is in attaching the event handlers and in the
initialization, much else is the same. Objects are overrated for data
encapsulation, variables trapped in closures serve the same purpose.

As always, Tapestry's own source code is invaluable for understanding how
things work, and often (perhaps not always) a good example of best
practices. Namespace collisions are often less of a problem for a developer
writing the web application but always an issue when developing components
for general use. If you imagine multiple components from different sources
working together, you can see how they might start stepping on each other
fairly quickly, and those problems are hairy to debug and difficult to
solve, so best to avoid in the first place.

See my recent commit:
https://github.com/tynamo/tynamo-federatedaccounts/commit/b48cf6e9338107b90cea8ad3bff6e75a90868bfd
together with the origin javascript:
http://svn.codehaus.org/tynamo/trunk/tynamo-federatedaccounts/tynamo-federatedaccounts-core/src/main/resources/org/tynamo/security/federatedaccounts/components/CollapsiblePanel.js

You can see how there's even a pretty much unnecessary use of a class there.

Javascript for built-in components are at
https://github.com/apache/tapestry-5/tree/master/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core.
It's often required to take a look at the corresponding .java source
understand how it all fits together.

The documentation that Howard wrote on this is actually excellent, see
http://tapestry.apache.org/client-side-javascript.html and
http://tapestry.apache.org/javascript-modules.html, but like any other new
programming concept, requires you to actually learn it, not just just
reading it through.

Coffeescript is another topic. The good thing is you don't have to get into
it at all if you don't want to. I like the syntax but I'm still not sure if
it's worth the additional complexity. Anyway for transcompiling on-the-fly,
tapestry-webresources is great and takes all the pain away when developing
your own web app.

Kalle


On Wed, Nov 12, 2014 at 3:13 AM, Paul Stanton <[hidden email]> wrote:

> Hi,
>
> so like many developers (i'm guessing) I'm not quite up to speed with all
> these new javascript frameworks: requirejs, closure, etc etc and to be
> honest I really didn't see a problem with the namespace model of the past.
> I'm not open to learning but it seems like a paradigm far removed from what
> i'm used to. it doesn't seem object oriented at all for example.
>
> that aside, can someone please point me (and other readers) to some basic
> examples to get us started in this brave new world. the first thing I would
> like to achieve is to be able to call some page or component specific
> marshalling code with page/component context parameters.
>
> your helpful attitudes will be appreciated!
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>
>
Reply | Threaded
Open this post in threaded view
|

Re: [5.4] javascript - simplify the new paradigm please

Paul Stanton
Thank you both of you for your responses ... I am learning a lot and
think I'm close to what I need to convert at least some of my work.

However I am still stumbling on this one use case which can be summed up
by the following question:

"How do I refer back to an object which was created and returned from
within 'define'"

ie:

java:afterRender()
{
js.require("module").with("xyz");
}

java:onSomeAsyncEvent()
{
js. ??? // do something with module instance?
}

I'm getting the feeling that the answer might be "it isn't" .. that all
future communication between server and client is achieved via
triggering/handling events... however there is a lot of ambiguity
(possibly due to my lack of understanding, and the abstraction caused by
coffee?) in the source code.

Looking through the tapestry source as advised yields some questions,
for example, t5/core/confirm-click.js:

     return {
       runDialog: runDialog
     };

Why does this return this function, and how is that used/referenced
elsewhere?

and t5/core/autocomplete.js:

(function() {
   define([...], function(dom, ajax, $, _arg) {
     var exports, extendURL, init;
     ...
     init = function(spec) {
       return $field.typeahead({
         ...
       });
     };
     return exports = init;
   });
}).call(this);

I don't understand why 'init' returns the result of '$field.typeahead'
and what the "return exports = init;" achieves and how any of this is
referred to later on?

Thanks, p.

On 13/11/2014 8:26 AM, Kalle Korhonen wrote:

> Well, let me try to answer as well. I just rewrote one, simple old school
> component to new T5.4, perhaps that's one good data point. I find that the
> biggest difference is in attaching the event handlers and in the
> initialization, much else is the same. Objects are overrated for data
> encapsulation, variables trapped in closures serve the same purpose.
>
> As always, Tapestry's own source code is invaluable for understanding how
> things work, and often (perhaps not always) a good example of best
> practices. Namespace collisions are often less of a problem for a developer
> writing the web application but always an issue when developing components
> for general use. If you imagine multiple components from different sources
> working together, you can see how they might start stepping on each other
> fairly quickly, and those problems are hairy to debug and difficult to
> solve, so best to avoid in the first place.
>
> See my recent commit:
> https://github.com/tynamo/tynamo-federatedaccounts/commit/b48cf6e9338107b90cea8ad3bff6e75a90868bfd
> together with the origin javascript:
> http://svn.codehaus.org/tynamo/trunk/tynamo-federatedaccounts/tynamo-federatedaccounts-core/src/main/resources/org/tynamo/security/federatedaccounts/components/CollapsiblePanel.js
>
> You can see how there's even a pretty much unnecessary use of a class there.
>
> Javascript for built-in components are at
> https://github.com/apache/tapestry-5/tree/master/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core.
> It's often required to take a look at the corresponding .java source
> understand how it all fits together.
>
> The documentation that Howard wrote on this is actually excellent, see
> http://tapestry.apache.org/client-side-javascript.html and
> http://tapestry.apache.org/javascript-modules.html, but like any other new
> programming concept, requires you to actually learn it, not just just
> reading it through.
>
> Coffeescript is another topic. The good thing is you don't have to get into
> it at all if you don't want to. I like the syntax but I'm still not sure if
> it's worth the additional complexity. Anyway for transcompiling on-the-fly,
> tapestry-webresources is great and takes all the pain away when developing
> your own web app.
>
> Kalle
>
>
> On Wed, Nov 12, 2014 at 3:13 AM, Paul Stanton <[hidden email]> wrote:
>
>> Hi,
>>
>> so like many developers (i'm guessing) I'm not quite up to speed with all
>> these new javascript frameworks: requirejs, closure, etc etc and to be
>> honest I really didn't see a problem with the namespace model of the past.
>> I'm not open to learning but it seems like a paradigm far removed from what
>> i'm used to. it doesn't seem object oriented at all for example.
>>
>> that aside, can someone please point me (and other readers) to some basic
>> examples to get us started in this brave new world. the first thing I would
>> like to achieve is to be able to call some page or component specific
>> marshalling code with page/component context parameters.
>>
>> your helpful attitudes will be appreciated!
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: [hidden email]
>> For additional commands, e-mail: [hidden email]
>>
>>


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: [5.4] javascript - simplify the new paradigm please

JumpStart
IMHO, the JavaScript changes in T5.4 are just amazing. For the first time ever I have found myself writing significant JavaScript that worked the very first time it was run! I think it's due to the enforced modularity combined with the way that RequireJS making modularising oh so easy. In a component-oriented Tapestry world it's perfect.

To Paul, and others, do these examples cover the situations you are describing? If not, please say so, so that I will know to add others.

        http://jumpstart.doublenegative.com.au/jumpstart7/examples/javascript/javascript
        http://jumpstart.doublenegative.com.au/jumpstart7/examples/javascript/reusable
        http://jumpstart.doublenegative.com.au/jumpstart7/examples/javascript/robust
        http://jumpstart.doublenegative.com.au/jumpstart7/examples/javascript/mixin

        http://jumpstart.doublenegative.com.au/jumpstart7/examples/javascript/modal/1
        http://jumpstart.doublenegative.com.au/jumpstart7/examples/javascript/reusablemodal/1

        http://jumpstart.doublenegative.com.au/jumpstart7/examples/ajax/onevent

        http://jumpstart.doublenegative.com.au/jumpstart7/together/ajaxcomponentscrud/persons

Geoff

Do these examples help? If there's a missing situation, please let me know so I can add an example.

On 13 Nov 2014, at 12:30 pm, Paul Stanton <[hidden email]> wrote:

> Thank you both of you for your responses ... I am learning a lot and think I'm close to what I need to convert at least some of my work.
>
> However I am still stumbling on this one use case which can be summed up by the following question:
>
> "How do I refer back to an object which was created and returned from within 'define'"
>
> ie:
>
> java:afterRender()
> {
> js.require("module").with("xyz");
> }
>
> java:onSomeAsyncEvent()
> {
> js. ??? // do something with module instance?
> }
>
> I'm getting the feeling that the answer might be "it isn't" .. that all future communication between server and client is achieved via triggering/handling events... however there is a lot of ambiguity (possibly due to my lack of understanding, and the abstraction caused by coffee?) in the source code.
>
> Looking through the tapestry source as advised yields some questions, for example, t5/core/confirm-click.js:
>
>    return {
>      runDialog: runDialog
>    };
>
> Why does this return this function, and how is that used/referenced elsewhere?
>
> and t5/core/autocomplete.js:
>
> (function() {
>  define([...], function(dom, ajax, $, _arg) {
>    var exports, extendURL, init;
>    ...
>    init = function(spec) {
>      return $field.typeahead({
>        ...
>      });
>    };
>    return exports = init;
>  });
> }).call(this);
>
> I don't understand why 'init' returns the result of '$field.typeahead' and what the "return exports = init;" achieves and how any of this is referred to later on?
>
> Thanks, p.
>
> On 13/11/2014 8:26 AM, Kalle Korhonen wrote:
>> Well, let me try to answer as well. I just rewrote one, simple old school
>> component to new T5.4, perhaps that's one good data point. I find that the
>> biggest difference is in attaching the event handlers and in the
>> initialization, much else is the same. Objects are overrated for data
>> encapsulation, variables trapped in closures serve the same purpose.
>>
>> As always, Tapestry's own source code is invaluable for understanding how
>> things work, and often (perhaps not always) a good example of best
>> practices. Namespace collisions are often less of a problem for a developer
>> writing the web application but always an issue when developing components
>> for general use. If you imagine multiple components from different sources
>> working together, you can see how they might start stepping on each other
>> fairly quickly, and those problems are hairy to debug and difficult to
>> solve, so best to avoid in the first place.
>>
>> See my recent commit:
>> https://github.com/tynamo/tynamo-federatedaccounts/commit/b48cf6e9338107b90cea8ad3bff6e75a90868bfd
>> together with the origin javascript:
>> http://svn.codehaus.org/tynamo/trunk/tynamo-federatedaccounts/tynamo-federatedaccounts-core/src/main/resources/org/tynamo/security/federatedaccounts/components/CollapsiblePanel.js
>>
>> You can see how there's even a pretty much unnecessary use of a class there.
>>
>> Javascript for built-in components are at
>> https://github.com/apache/tapestry-5/tree/master/tapestry-core/src/main/coffeescript/META-INF/modules/t5/core.
>> It's often required to take a look at the corresponding .java source
>> understand how it all fits together.
>>
>> The documentation that Howard wrote on this is actually excellent, see
>> http://tapestry.apache.org/client-side-javascript.html and
>> http://tapestry.apache.org/javascript-modules.html, but like any other new
>> programming concept, requires you to actually learn it, not just just
>> reading it through.
>>
>> Coffeescript is another topic. The good thing is you don't have to get into
>> it at all if you don't want to. I like the syntax but I'm still not sure if
>> it's worth the additional complexity. Anyway for transcompiling on-the-fly,
>> tapestry-webresources is great and takes all the pain away when developing
>> your own web app.
>>
>> Kalle
>>
>>
>> On Wed, Nov 12, 2014 at 3:13 AM, Paul Stanton <[hidden email]> wrote:
>>
>>> Hi,
>>>
>>> so like many developers (i'm guessing) I'm not quite up to speed with all
>>> these new javascript frameworks: requirejs, closure, etc etc and to be
>>> honest I really didn't see a problem with the namespace model of the past.
>>> I'm not open to learning but it seems like a paradigm far removed from what
>>> i'm used to. it doesn't seem object oriented at all for example.
>>>
>>> that aside, can someone please point me (and other readers) to some basic
>>> examples to get us started in this brave new world. the first thing I would
>>> like to achieve is to be able to call some page or component specific
>>> marshalling code with page/component context parameters.
>>>
>>> your helpful attitudes will be appreciated!
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: [hidden email]
>>> For additional commands, e-mail: [hidden email]
>>>
>>>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: [5.4] javascript - simplify the new paradigm please

Paul Stanton
Hi Geoff,

I have found your examples invaluable in learning some of the basics of
this (and other) concepts. I can't thank you enough

  .. the only thing I can see is missing currently is the example I
asked about in the previous mail:

Basically, how do I interact with a js module instance after it is created?

pretend some server-side state changes between afterRender and
onSomeEvent, and the client needs to react accordingly.

jss.addScript is deprecated, so I "shouldn't" be telling the client to
execute script apparently...

cheers, p.

On 13/11/2014 2:36 PM, Geoff Callender wrote:
> do these examples cover the situations you are describing?


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: [5.4] javascript - simplify the new paradigm please

JumpStart
Have you had a look at these two:

        http://jumpstart.doublenegative.com.au/jumpstart7/examples/javascript/modal/1
        http://jumpstart.doublenegative.com.au/jumpstart7/examples/javascript/reusablemodal/1

Do they fit your scenario?

On 13 Nov 2014, at 3:40 pm, Paul Stanton <[hidden email]> wrote:

> Hi Geoff,
>
> I have found your examples invaluable in learning some of the basics of this (and other) concepts. I can't thank you enough
>
> .. the only thing I can see is missing currently is the example I asked about in the previous mail:
>
> Basically, how do I interact with a js module instance after it is created?
>
> pretend some server-side state changes between afterRender and onSomeEvent, and the client needs to react accordingly.
>
> jss.addScript is deprecated, so I "shouldn't" be telling the client to execute script apparently...
>
> cheers, p.
>
> On 13/11/2014 2:36 PM, Geoff Callender wrote:
>> do these examples cover the situations you are describing?
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>

Reply | Threaded
Open this post in threaded view
|

Re: [5.4] javascript - simplify the new paradigm please

Chris Poulsen
can't you just use javascriptsupport to require and invoke your js module
function?

--
Chris

On Thu, Nov 13, 2014 at 6:34 AM, Geoff Callender <
[hidden email]> wrote:

> Have you had a look at these two:
>
>
> http://jumpstart.doublenegative.com.au/jumpstart7/examples/javascript/modal/1
>
> http://jumpstart.doublenegative.com.au/jumpstart7/examples/javascript/reusablemodal/1
>
> Do they fit your scenario?
>
> On 13 Nov 2014, at 3:40 pm, Paul Stanton <[hidden email]> wrote:
>
> > Hi Geoff,
> >
> > I have found your examples invaluable in learning some of the basics of
> this (and other) concepts. I can't thank you enough
> >
> > .. the only thing I can see is missing currently is the example I asked
> about in the previous mail:
> >
> > Basically, how do I interact with a js module instance after it is
> created?
> >
> > pretend some server-side state changes between afterRender and
> onSomeEvent, and the client needs to react accordingly.
> >
> > jss.addScript is deprecated, so I "shouldn't" be telling the client to
> execute script apparently...
> >
> > cheers, p.
> >
> > On 13/11/2014 2:36 PM, Geoff Callender wrote:
> >> do these examples cover the situations you are describing?
> >
> >
> > ---------------------------------------------------------------------
> > To unsubscribe, e-mail: [hidden email]
> > For additional commands, e-mail: [hidden email]
> >
>
>
Reply | Threaded
Open this post in threaded view
|

Re: [5.4] javascript - simplify the new paradigm please

Howard Lewis Ship
In reply to this post by Paul Stanton
The change in JavaScript is to support several goals:
- A good transition from Prototype.js to jQuery (or perhaps something else
in the future)
- Reduce the total amount of JavaScript sent to the client
- Allow more of the JavaScript to transfer in parallel
- Make it easier to override Tapestry's built-in behaviors
- Improve page loading speed

Having a single JavaScript event handler added to document.body, rather
than having N handlers attached to N DOM elements, is a big win
performance-wise. It also allows any particular DOM element to change the
behavior by adding a specific event handler at that DOM level and not
allowing the event to propagate up.

The Tapestry docs have been updated with more information, such as:

http://tapestry.apache.org/javascript-modules.html




On Wed, Nov 12, 2014 at 3:13 AM, Paul Stanton <[hidden email]> wrote:

> Hi,
>
> so like many developers (i'm guessing) I'm not quite up to speed with all
> these new javascript frameworks: requirejs, closure, etc etc and to be
> honest I really didn't see a problem with the namespace model of the past.
> I'm not open to learning but it seems like a paradigm far removed from what
> i'm used to. it doesn't seem object oriented at all for example.
>
> that aside, can someone please point me (and other readers) to some basic
> examples to get us started in this brave new world. the first thing I would
> like to achieve is to be able to call some page or component specific
> marshalling code with page/component context parameters.
>
> your helpful attitudes will be appreciated!
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>
>


--
Howard M. Lewis Ship

Creator of Apache Tapestry

The source for Tapestry training, mentoring and support. Contact me to
learn how I can get you up and productive in Tapestry fast!

(971) 678-5210
http://howardlewisship.com
@hlship
Reply | Threaded
Open this post in threaded view
|

Re: [5.4] javascript - simplify the new paradigm please

Paul Stanton
In reply to this post by JumpStart
Oh,

so calling
require("modal").invoke("activate")

and then later
require("modal").invoke("deactivate")

.. both re-construct a seperate "modal" js object and then call one of
the two published functions...

what if you have two different modals? what if they are init-ed differently:

java:afterRender() {
     require("modal").invoke("init").with("message 1");
     require("modal").invoke("init").with("message 2");
}

and then later
java:onSomeEvent() {
     require("modal").invoke("activate");
}

this flow would essentially construct the modal module instance 3 times,
and the "activate" wouldn't know about "message 1" or "message 2".

Therefore, how would I re-aquire a handle to a specific module instance
later on? for eg:

java:onSomeEvent(){
     // activate modal with "message 1"
     require("modal").invoke("activate");
}

I know this example doesn't make much practical sense, but the concept
of communicating with something stateful is pretty key!

p.

On 13/11/2014 4:34 PM, Geoff Callender wrote:

> Have you had a look at these two:
>
> http://jumpstart.doublenegative.com.au/jumpstart7/examples/javascript/modal/1
> http://jumpstart.doublenegative.com.au/jumpstart7/examples/javascript/reusablemodal/1
>
> Do they fit your scenario?
>
> On 13 Nov 2014, at 3:40 pm, Paul Stanton <[hidden email]> wrote:
>
>> Hi Geoff,
>>
>> I have found your examples invaluable in learning some of the basics of this (and other) concepts. I can't thank you enough
>>
>> .. the only thing I can see is missing currently is the example I asked about in the previous mail:
>>
>> Basically, how do I interact with a js module instance after it is created?
>>
>> pretend some server-side state changes between afterRender and onSomeEvent, and the client needs to react accordingly.
>>
>> jss.addScript is deprecated, so I "shouldn't" be telling the client to execute script apparently...
>>
>> cheers, p.
>>
>> On 13/11/2014 2:36 PM, Geoff Callender wrote:
>>> do these examples cover the situations you are describing?
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: [hidden email]
>> For additional commands, e-mail: [hidden email]
>>
>


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: [5.4] javascript - simplify the new paradigm please

JumpStart
Yep, that's a valid case, and it's one I have to put into JumpStart.

Here's the way I handle it. I'd like to see what others do.

Have the module keep an array of objects, identified by a key. The server-side can provide the key when initialising and later whenever invoking a function. The component can use any value for the key as long as it is unique on the page and as long as it is repeatable (eg. the component might need to derive the key from its container or context).

Here's an example snippet from a module I called "activate-selectables". More than one component on my page uses this module. A typical case is when I have a list of items on the page, and a button that pops up a modal with another list of items. When an item is selected, the server-side has to set the currentElement on the correct list.

define([ "jquery", "t5/core/console" ], function($, console) {

        var selectablesContainers = [];

        SelectablesContainer = function() {

                init = function(params) {
                        containerId = params.containerId;
                        selectableClass = params.selectableCssClass;
                        selectedClass = params.selectedCssClass;
                        // etc
                        var $container = $('#' + containerId);
                        $container.on('click', '.' + selectableClass, doSelected);
                };

                doSelected = function() {
                        var $clicked = $(this);
                        $clicked.addClass(selectedClass);
                        $clicked.trigger('selected');
                };

                setCurrentElement = function(selectableName) {
                        // etc.
                };

                return {
                        init : init,
                        setCurrentElement : setCurrentElement
                };
        };

        init = function(key, params) {
                var selectablesContainer = new SelectablesContainer();
                selectablesContainer.init(params);
                selectablesContainers[key] = selectablesContainer;
        };

        setCurrentElement = function(key, currentElementName) {
                var selectablesContainer = selectablesContainers[key];
                selectablesContainer.setCurrentElement(currentElementName);
        };

        return {
                init : init,
                setCurrentElement : setCurrentElement
        };

});

And some corresponding java:

        void afterRender() {
                JSONObject params = new JSONObject();
                params.put("containerId", thingsDiv.getClientId());
                //etc
                javaScriptSupport.require("activate-selectables").invoke("init").with(SELECTABLES_KEY, params);
        }

        Object onThingSelected(Integer thingId) {
                this.thingId = thingId;
                // etc
                ajaxResponseRenderer.addCallback(makeScriptToSetCurrentElement(selectableName));
                // etc
        }

        private JavaScriptCallback makeScriptToSetCurrentElement(final String selectableName) {

                return new JavaScriptCallback() {

                        public void run(JavaScriptSupport javaScriptSupport) {
                                javaScriptSupport.require("activate-selectables").invoke("setCurrentElement")
                                                .with(SELECTABLES_KEY, selectableName);
                        }

                };

        }

In this case I get away with SELECTABLES_KEY being a constant but, as I said above, sometimes you have to derive its value from its container or event context.

Geoff

On 14 Nov 2014, at 9:18 am, Paul Stanton <[hidden email]> wrote:

> Oh,
>
> so calling
> require("modal").invoke("activate")
>
> and then later
> require("modal").invoke("deactivate")
>
> .. both re-construct a seperate "modal" js object and then call one of the two published functions...
>
> what if you have two different modals? what if they are init-ed differently:
>
> java:afterRender() {
>    require("modal").invoke("init").with("message 1");
>    require("modal").invoke("init").with("message 2");
> }
>
> and then later
> java:onSomeEvent() {
>    require("modal").invoke("activate");
> }
>
> this flow would essentially construct the modal module instance 3 times, and the "activate" wouldn't know about "message 1" or "message 2".
>
> Therefore, how would I re-aquire a handle to a specific module instance later on? for eg:
>
> java:onSomeEvent(){
>    // activate modal with "message 1"
>    require("modal").invoke("activate");
> }
>
> I know this example doesn't make much practical sense, but the concept of communicating with something stateful is pretty key!
>
> p.
>
> On 13/11/2014 4:34 PM, Geoff Callender wrote:
>> Have you had a look at these two:
>>
>> http://jumpstart.doublenegative.com.au/jumpstart7/examples/javascript/modal/1
>> http://jumpstart.doublenegative.com.au/jumpstart7/examples/javascript/reusablemodal/1
>>
>> Do they fit your scenario?
>>
>> On 13 Nov 2014, at 3:40 pm, Paul Stanton <[hidden email]> wrote:
>>
>>> Hi Geoff,
>>>
>>> I have found your examples invaluable in learning some of the basics of this (and other) concepts. I can't thank you enough
>>>
>>> .. the only thing I can see is missing currently is the example I asked about in the previous mail:
>>>
>>> Basically, how do I interact with a js module instance after it is created?
>>>
>>> pretend some server-side state changes between afterRender and onSomeEvent, and the client needs to react accordingly.
>>>
>>> jss.addScript is deprecated, so I "shouldn't" be telling the client to execute script apparently...
>>>
>>> cheers, p.
>>>
>>> On 13/11/2014 2:36 PM, Geoff Callender wrote:
>>>> do these examples cover the situations you are describing?
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: [hidden email]
>>> For additional commands, e-mail: [hidden email]
>>>
>>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [hidden email]
> For additional commands, e-mail: [hidden email]
>

Reply | Threaded
Open this post in threaded view
|

Re: [5.4] javascript - simplify the new paradigm please

JumpStart
A better example would be where the client-side objects have considerable state, eg. a Graph object or, more complex still, a Graph editor.

Of course, client-side objects may be avoided having your javascript save/retrieve all state to/from hidden fields in the relevant part of the DOM, but that's just another implementation choice.

On 14 Nov 2014, at 10:00 am, Geoff Callender <[hidden email]> wrote:

> Yep, that's a valid case, and it's one I have to put into JumpStart.
>
> Here's the way I handle it. I'd like to see what others do.
>
> Have the module keep an array of objects, identified by a key. The server-side can provide the key when initialising and later whenever invoking a function. The component can use any value for the key as long as it is unique on the page and as long as it is repeatable (eg. the component might need to derive the key from its container or context).
>
> Here's an example snippet from a module I called "activate-selectables". More than one component on my page uses this module. A typical case is when I have a list of items on the page, and a button that pops up a modal with another list of items. When an item is selected, the server-side has to set the currentElement on the correct list.
>
> define([ "jquery", "t5/core/console" ], function($, console) {
>
> var selectablesContainers = [];
>
> SelectablesContainer = function() {
>
> init = function(params) {
> containerId = params.containerId;
> selectableClass = params.selectableCssClass;
> selectedClass = params.selectedCssClass;
> // etc
> var $container = $('#' + containerId);
> $container.on('click', '.' + selectableClass, doSelected);
> };
>
> doSelected = function() {
> var $clicked = $(this);
> $clicked.addClass(selectedClass);
> $clicked.trigger('selected');
> };
>
> setCurrentElement = function(selectableName) {
> // etc.
> };
>
> return {
> init : init,
> setCurrentElement : setCurrentElement
> };
> };
>
> init = function(key, params) {
> var selectablesContainer = new SelectablesContainer();
> selectablesContainer.init(params);
> selectablesContainers[key] = selectablesContainer;
> };
>
> setCurrentElement = function(key, currentElementName) {
> var selectablesContainer = selectablesContainers[key];
> selectablesContainer.setCurrentElement(currentElementName);
> };
>
> return {
> init : init,
> setCurrentElement : setCurrentElement
> };
>
> });
>
> And some corresponding java:
>
> void afterRender() {
> JSONObject params = new JSONObject();
> params.put("containerId", thingsDiv.getClientId());
> //etc
> javaScriptSupport.require("activate-selectables").invoke("init").with(SELECTABLES_KEY, params);
> }
>
> Object onThingSelected(Integer thingId) {
> this.thingId = thingId;
> // etc
> ajaxResponseRenderer.addCallback(makeScriptToSetCurrentElement(selectableName));
> // etc
> }
>
> private JavaScriptCallback makeScriptToSetCurrentElement(final String selectableName) {
>
> return new JavaScriptCallback() {
>
> public void run(JavaScriptSupport javaScriptSupport) {
> javaScriptSupport.require("activate-selectables").invoke("setCurrentElement")
> .with(SELECTABLES_KEY, selectableName);
> }
>
> };
>
> }
>
> In this case I get away with SELECTABLES_KEY being a constant but, as I said above, sometimes you have to derive its value from its container or event context.
>
> Geoff
>
> On 14 Nov 2014, at 9:18 am, Paul Stanton <[hidden email]> wrote:
>
>> Oh,
>>
>> so calling
>> require("modal").invoke("activate")
>>
>> and then later
>> require("modal").invoke("deactivate")
>>
>> .. both re-construct a seperate "modal" js object and then call one of the two published functions...
>>
>> what if you have two different modals? what if they are init-ed differently:
>>
>> java:afterRender() {
>>    require("modal").invoke("init").with("message 1");
>>    require("modal").invoke("init").with("message 2");
>> }
>>
>> and then later
>> java:onSomeEvent() {
>>    require("modal").invoke("activate");
>> }
>>
>> this flow would essentially construct the modal module instance 3 times, and the "activate" wouldn't know about "message 1" or "message 2".
>>
>> Therefore, how would I re-aquire a handle to a specific module instance later on? for eg:
>>
>> java:onSomeEvent(){
>>    // activate modal with "message 1"
>>    require("modal").invoke("activate");
>> }
>>
>> I know this example doesn't make much practical sense, but the concept of communicating with something stateful is pretty key!
>>
>> p.
>>
>> On 13/11/2014 4:34 PM, Geoff Callender wrote:
>>> Have you had a look at these two:
>>>
>>> http://jumpstart.doublenegative.com.au/jumpstart7/examples/javascript/modal/1
>>> http://jumpstart.doublenegative.com.au/jumpstart7/examples/javascript/reusablemodal/1
>>>
>>> Do they fit your scenario?
>>>
>>> On 13 Nov 2014, at 3:40 pm, Paul Stanton <[hidden email]> wrote:
>>>
>>>> Hi Geoff,
>>>>
>>>> I have found your examples invaluable in learning some of the basics of this (and other) concepts. I can't thank you enough
>>>>
>>>> .. the only thing I can see is missing currently is the example I asked about in the previous mail:
>>>>
>>>> Basically, how do I interact with a js module instance after it is created?
>>>>
>>>> pretend some server-side state changes between afterRender and onSomeEvent, and the client needs to react accordingly.
>>>>
>>>> jss.addScript is deprecated, so I "shouldn't" be telling the client to execute script apparently...
>>>>
>>>> cheers, p.
>>>>
>>>> On 13/11/2014 2:36 PM, Geoff Callender wrote:
>>>>> do these examples cover the situations you are describing?
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: [hidden email]
>>>> For additional commands, e-mail: [hidden email]
>>>>
>>>
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: [hidden email]
>> For additional commands, e-mail: [hidden email]
>>
>

Reply | Threaded
Open this post in threaded view
|

Re: [5.4] javascript - simplify the new paradigm please

JumpStart
In reply to this post by JumpStart
I accidentally left out the object's state vars. Added below.

On 14 Nov 2014, at 10:00 am, Geoff Callender <[hidden email]> wrote:

> Yep, that's a valid case, and it's one I have to put into JumpStart.
>
> Here's the way I handle it. I'd like to see what others do.
>
> Have the module keep an array of objects, identified by a key. The server-side can provide the key when initialising and later whenever invoking a function. The component can use any value for the key as long as it is unique on the page and as long as it is repeatable (eg. the component might need to derive the key from its container or context).
>
> Here's an example snippet from a module I called "activate-selectables". More than one component on my page uses this module. A typical case is when I have a list of items on the page, and a button that pops up a modal with another list of items. When an item is selected, the server-side has to set the currentElement on the correct list.
>
> define([ "jquery", "t5/core/console" ], function($, console) {
>
> var selectablesContainers = [];
>
> SelectablesContainer = function() {

                var containerId = "", selectableClass = "", selectedClass = "", currentClass = "";

> init = function(params) {
> containerId = params.containerId;
> selectableClass = params.selectableCssClass;
> selectedClass = params.selectedCssClass;
> // etc
> var $container = $('#' + containerId);
> $container.on('click', '.' + selectableClass, doSelected);
> };
>
> doSelected = function() {
> var $clicked = $(this);
> $clicked.addClass(selectedClass);
> $clicked.trigger('selected');
> };
>
> setCurrentElement = function(selectableName) {
> // etc.
> };
>
> return {
> init : init,
> setCurrentElement : setCurrentElement
> };
> };
>
> init = function(key, params) {
> var selectablesContainer = new SelectablesContainer();
> selectablesContainer.init(params);
> selectablesContainers[key] = selectablesContainer;
> };
>
> setCurrentElement = function(key, currentElementName) {
> var selectablesContainer = selectablesContainers[key];
> selectablesContainer.setCurrentElement(currentElementName);
> };
>
> return {
> init : init,
> setCurrentElement : setCurrentElement
> };
>
> });
>
> And some corresponding java:
>
> void afterRender() {
> JSONObject params = new JSONObject();
> params.put("containerId", thingsDiv.getClientId());
> //etc
> javaScriptSupport.require("activate-selectables").invoke("init").with(SELECTABLES_KEY, params);
> }
>
> Object onThingSelected(Integer thingId) {
> this.thingId = thingId;
> // etc
> ajaxResponseRenderer.addCallback(makeScriptToSetCurrentElement(selectableName));
> // etc
> }
>
> private JavaScriptCallback makeScriptToSetCurrentElement(final String selectableName) {
>
> return new JavaScriptCallback() {
>
> public void run(JavaScriptSupport javaScriptSupport) {
> javaScriptSupport.require("activate-selectables").invoke("setCurrentElement")
> .with(SELECTABLES_KEY, selectableName);
> }
>
> };
>
> }
>
> In this case I get away with SELECTABLES_KEY being a constant but, as I said above, sometimes you have to derive its value from its container or event context.
>
> Geoff
>
> On 14 Nov 2014, at 9:18 am, Paul Stanton <[hidden email]> wrote:
>
>> Oh,
>>
>> so calling
>> require("modal").invoke("activate")
>>
>> and then later
>> require("modal").invoke("deactivate")
>>
>> .. both re-construct a seperate "modal" js object and then call one of the two published functions...
>>
>> what if you have two different modals? what if they are init-ed differently:
>>
>> java:afterRender() {
>>    require("modal").invoke("init").with("message 1");
>>    require("modal").invoke("init").with("message 2");
>> }
>>
>> and then later
>> java:onSomeEvent() {
>>    require("modal").invoke("activate");
>> }
>>
>> this flow would essentially construct the modal module instance 3 times, and the "activate" wouldn't know about "message 1" or "message 2".
>>
>> Therefore, how would I re-aquire a handle to a specific module instance later on? for eg:
>>
>> java:onSomeEvent(){
>>    // activate modal with "message 1"
>>    require("modal").invoke("activate");
>> }
>>
>> I know this example doesn't make much practical sense, but the concept of communicating with something stateful is pretty key!
>>
>> p.
>>
>> On 13/11/2014 4:34 PM, Geoff Callender wrote:
>>> Have you had a look at these two:
>>>
>>> http://jumpstart.doublenegative.com.au/jumpstart7/examples/javascript/modal/1
>>> http://jumpstart.doublenegative.com.au/jumpstart7/examples/javascript/reusablemodal/1
>>>
>>> Do they fit your scenario?
>>>
>>> On 13 Nov 2014, at 3:40 pm, Paul Stanton <[hidden email]> wrote:
>>>
>>>> Hi Geoff,
>>>>
>>>> I have found your examples invaluable in learning some of the basics of this (and other) concepts. I can't thank you enough
>>>>
>>>> .. the only thing I can see is missing currently is the example I asked about in the previous mail:
>>>>
>>>> Basically, how do I interact with a js module instance after it is created?
>>>>
>>>> pretend some server-side state changes between afterRender and onSomeEvent, and the client needs to react accordingly.
>>>>
>>>> jss.addScript is deprecated, so I "shouldn't" be telling the client to execute script apparently...
>>>>
>>>> cheers, p.
>>>>
>>>> On 13/11/2014 2:36 PM, Geoff Callender wrote:
>>>>> do these examples cover the situations you are describing?
>>>>
>>>> ---------------------------------------------------------------------
>>>> To unsubscribe, e-mail: [hidden email]
>>>> For additional commands, e-mail: [hidden email]
>>>>
>>>
>>
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: [hidden email]
>> For additional commands, e-mail: [hidden email]
>>
>

Reply | Threaded
Open this post in threaded view
|

Re: [5.4] javascript - simplify the new paradigm please

JumpStart
In reply to this post by Chris Poulsen
I don't think so. I believe the rule of thumb is to use JavaScriptSupport during render, and use an AJAX callback during partial page render.

IIRC, the JavaScriptSupport environmental is not available when you're handling an AJAX component event request.

On 13 Nov 2014, at 6:08 pm, Chris Poulsen <[hidden email]> wrote:

> can't you just use javascriptsupport to require and invoke your js module
> function?
>
> --
> Chris
>
> On Thu, Nov 13, 2014 at 6:34 AM, Geoff Callender <
> [hidden email]> wrote:
>
>> Have you had a look at these two:
>>
>>
>> http://jumpstart.doublenegative.com.au/jumpstart7/examples/javascript/modal/1
>>
>> http://jumpstart.doublenegative.com.au/jumpstart7/examples/javascript/reusablemodal/1
>>
>> Do they fit your scenario?
>>
>> On 13 Nov 2014, at 3:40 pm, Paul Stanton <[hidden email]> wrote:
>>
>>> Hi Geoff,
>>>
>>> I have found your examples invaluable in learning some of the basics of
>> this (and other) concepts. I can't thank you enough
>>>
>>> .. the only thing I can see is missing currently is the example I asked
>> about in the previous mail:
>>>
>>> Basically, how do I interact with a js module instance after it is
>> created?
>>>
>>> pretend some server-side state changes between afterRender and
>> onSomeEvent, and the client needs to react accordingly.
>>>
>>> jss.addScript is deprecated, so I "shouldn't" be telling the client to
>> execute script apparently...
>>>
>>> cheers, p.
>>>
>>> On 13/11/2014 2:36 PM, Geoff Callender wrote:
>>>> do these examples cover the situations you are describing?
>>>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: [hidden email]
>>> For additional commands, e-mail: [hidden email]
>>>
>>
>>


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: [5.4] javascript - simplify the new paradigm please

Paul Stanton
In reply to this post by JumpStart
Thanks Geoff,

Im going to have to play around with this and see what is happening
under the covers.

I'll get back...

cheers, p.

On 14/11/2014 3:06 PM, Geoff Callender wrote:

> I accidentally left out the object's state vars. Added below.
>
> On 14 Nov 2014, at 10:00 am, Geoff Callender <[hidden email]> wrote:
>
>> Yep, that's a valid case, and it's one I have to put into JumpStart.
>>
>> Here's the way I handle it. I'd like to see what others do.
>>
>> Have the module keep an array of objects, identified by a key. The server-side can provide the key when initialising and later whenever invoking a function. The component can use any value for the key as long as it is unique on the page and as long as it is repeatable (eg. the component might need to derive the key from its container or context).
>>
>> Here's an example snippet from a module I called "activate-selectables". More than one component on my page uses this module. A typical case is when I have a list of items on the page, and a button that pops up a modal with another list of items. When an item is selected, the server-side has to set the currentElement on the correct list.
>>
>> define([ "jquery", "t5/core/console" ], function($, console) {
>>
>> var selectablesContainers = [];
>>
>> SelectablesContainer = function() {
> var containerId = "", selectableClass = "", selectedClass = "", currentClass = "";
>
>> init = function(params) {
>> containerId = params.containerId;
>> selectableClass = params.selectableCssClass;
>> selectedClass = params.selectedCssClass;
>> // etc
>> var $container = $('#' + containerId);
>> $container.on('click', '.' + selectableClass, doSelected);
>> };
>>
>> doSelected = function() {
>> var $clicked = $(this);
>> $clicked.addClass(selectedClass);
>> $clicked.trigger('selected');
>> };
>>
>> setCurrentElement = function(selectableName) {
>> // etc.
>> };
>>
>> return {
>> init : init,
>> setCurrentElement : setCurrentElement
>> };
>> };
>>
>> init = function(key, params) {
>> var selectablesContainer = new SelectablesContainer();
>> selectablesContainer.init(params);
>> selectablesContainers[key] = selectablesContainer;
>> };
>>
>> setCurrentElement = function(key, currentElementName) {
>> var selectablesContainer = selectablesContainers[key];
>> selectablesContainer.setCurrentElement(currentElementName);
>> };
>>
>> return {
>> init : init,
>> setCurrentElement : setCurrentElement
>> };
>>
>> });
>>
>> And some corresponding java:
>>
>> void afterRender() {
>> JSONObject params = new JSONObject();
>> params.put("containerId", thingsDiv.getClientId());
>> //etc
>> javaScriptSupport.require("activate-selectables").invoke("init").with(SELECTABLES_KEY, params);
>> }
>>
>> Object onThingSelected(Integer thingId) {
>> this.thingId = thingId;
>> // etc
>> ajaxResponseRenderer.addCallback(makeScriptToSetCurrentElement(selectableName));
>> // etc
>> }
>>
>> private JavaScriptCallback makeScriptToSetCurrentElement(final String selectableName) {
>>
>> return new JavaScriptCallback() {
>>
>> public void run(JavaScriptSupport javaScriptSupport) {
>> javaScriptSupport.require("activate-selectables").invoke("setCurrentElement")
>> .with(SELECTABLES_KEY, selectableName);
>> }
>>
>> };
>>
>> }
>>
>> In this case I get away with SELECTABLES_KEY being a constant but, as I said above, sometimes you have to derive its value from its container or event context.
>>
>> Geoff
>>
>> On 14 Nov 2014, at 9:18 am, Paul Stanton <[hidden email]> wrote:
>>
>>> Oh,
>>>
>>> so calling
>>> require("modal").invoke("activate")
>>>
>>> and then later
>>> require("modal").invoke("deactivate")
>>>
>>> .. both re-construct a seperate "modal" js object and then call one of the two published functions...
>>>
>>> what if you have two different modals? what if they are init-ed differently:
>>>
>>> java:afterRender() {
>>>     require("modal").invoke("init").with("message 1");
>>>     require("modal").invoke("init").with("message 2");
>>> }
>>>
>>> and then later
>>> java:onSomeEvent() {
>>>     require("modal").invoke("activate");
>>> }
>>>
>>> this flow would essentially construct the modal module instance 3 times, and the "activate" wouldn't know about "message 1" or "message 2".
>>>
>>> Therefore, how would I re-aquire a handle to a specific module instance later on? for eg:
>>>
>>> java:onSomeEvent(){
>>>     // activate modal with "message 1"
>>>     require("modal").invoke("activate");
>>> }
>>>
>>> I know this example doesn't make much practical sense, but the concept of communicating with something stateful is pretty key!
>>>
>>> p.
>>>
>>> On 13/11/2014 4:34 PM, Geoff Callender wrote:
>>>> Have you had a look at these two:
>>>>
>>>> http://jumpstart.doublenegative.com.au/jumpstart7/examples/javascript/modal/1
>>>> http://jumpstart.doublenegative.com.au/jumpstart7/examples/javascript/reusablemodal/1
>>>>
>>>> Do they fit your scenario?
>>>>
>>>> On 13 Nov 2014, at 3:40 pm, Paul Stanton <[hidden email]> wrote:
>>>>
>>>>> Hi Geoff,
>>>>>
>>>>> I have found your examples invaluable in learning some of the basics of this (and other) concepts. I can't thank you enough
>>>>>
>>>>> .. the only thing I can see is missing currently is the example I asked about in the previous mail:
>>>>>
>>>>> Basically, how do I interact with a js module instance after it is created?
>>>>>
>>>>> pretend some server-side state changes between afterRender and onSomeEvent, and the client needs to react accordingly.
>>>>>
>>>>> jss.addScript is deprecated, so I "shouldn't" be telling the client to execute script apparently...
>>>>>
>>>>> cheers, p.
>>>>>
>>>>> On 13/11/2014 2:36 PM, Geoff Callender wrote:
>>>>>> do these examples cover the situations you are describing?
>>>>> ---------------------------------------------------------------------
>>>>> To unsubscribe, e-mail: [hidden email]
>>>>> For additional commands, e-mail: [hidden email]
>>>>>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: [hidden email]
>>> For additional commands, e-mail: [hidden email]
>>>
>


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

Reply | Threaded
Open this post in threaded view
|

Re: [5.4] javascript - simplify the new paradigm please

Paul Stanton
In reply to this post by JumpStart
Geoff,

After some testing I can really see the benefits in how you achieve
this... One of my main prior misunderstanding was that the 'define' is
only run once (I thought it would be re-run each 'require'), making
similar to a 'static' object in some ways, in that the state is then
shared by all subsequent 'require' calls... so you are effectively
creating a hash of stateful objects within the context of that 'define'.

thank you for helping me understand this, I feel I have graduated re
this concept and can now get some code written.

would love to see this in action in jumpstart7. as far as i'm concerned
jumpstart is the definitive tapestry documentation, or at least on par
with the official.

howard, thiago etc, maybe putting a few more complex examples in the
'javascript-modules' documentation would be helpful? if you haven't used
requirejs before this concept is hard to grasp at first.

p.

On 14/11/2014 3:06 PM, Geoff Callender wrote:

> I accidentally left out the object's state vars. Added below.
>
> On 14 Nov 2014, at 10:00 am, Geoff Callender <[hidden email]> wrote:
>
>> Yep, that's a valid case, and it's one I have to put into JumpStart.
>>
>> Here's the way I handle it. I'd like to see what others do.
>>
>> Have the module keep an array of objects, identified by a key. The server-side can provide the key when initialising and later whenever invoking a function. The component can use any value for the key as long as it is unique on the page and as long as it is repeatable (eg. the component might need to derive the key from its container or context).
>>
>> Here's an example snippet from a module I called "activate-selectables". More than one component on my page uses this module. A typical case is when I have a list of items on the page, and a button that pops up a modal with another list of items. When an item is selected, the server-side has to set the currentElement on the correct list.
>>
>> define([ "jquery", "t5/core/console" ], function($, console) {
>>
>> var selectablesContainers = [];
>>
>> SelectablesContainer = function() {
> var containerId = "", selectableClass = "", selectedClass = "", currentClass = "";
>
>> init = function(params) {
>> containerId = params.containerId;
>> selectableClass = params.selectableCssClass;
>> selectedClass = params.selectedCssClass;
>> // etc
>> var $container = $('#' + containerId);
>> $container.on('click', '.' + selectableClass, doSelected);
>> };
>>
>> doSelected = function() {
>> var $clicked = $(this);
>> $clicked.addClass(selectedClass);
>> $clicked.trigger('selected');
>> };
>>
>> setCurrentElement = function(selectableName) {
>> // etc.
>> };
>>
>> return {
>> init : init,
>> setCurrentElement : setCurrentElement
>> };
>> };
>>
>> init = function(key, params) {
>> var selectablesContainer = new SelectablesContainer();
>> selectablesContainer.init(params);
>> selectablesContainers[key] = selectablesContainer;
>> };
>>
>> setCurrentElement = function(key, currentElementName) {
>> var selectablesContainer = selectablesContainers[key];
>> selectablesContainer.setCurrentElement(currentElementName);
>> };
>>
>> return {
>> init : init,
>> setCurrentElement : setCurrentElement
>> };
>>
>> });
>>
>> And some corresponding java:
>>
>> void afterRender() {
>> JSONObject params = new JSONObject();
>> params.put("containerId", thingsDiv.getClientId());
>> //etc
>> javaScriptSupport.require("activate-selectables").invoke("init").with(SELECTABLES_KEY, params);
>> }
>>
>> Object onThingSelected(Integer thingId) {
>> this.thingId = thingId;
>> // etc
>> ajaxResponseRenderer.addCallback(makeScriptToSetCurrentElement(selectableName));
>> // etc
>> }
>>
>> private JavaScriptCallback makeScriptToSetCurrentElement(final String selectableName) {
>>
>> return new JavaScriptCallback() {
>>
>> public void run(JavaScriptSupport javaScriptSupport) {
>> javaScriptSupport.require("activate-selectables").invoke("setCurrentElement")
>> .with(SELECTABLES_KEY, selectableName);
>> }
>>
>> };
>>
>> }
>>
>> In this case I get away with SELECTABLES_KEY being a constant but, as I said above, sometimes you have to derive its value from its container or event context.
>>
>> Geoff
>>
>> On 14 Nov 2014, at 9:18 am, Paul Stanton <[hidden email]> wrote:
>>
>>> Oh,
>>>
>>> so calling
>>> require("modal").invoke("activate")
>>>
>>> and then later
>>> require("modal").invoke("deactivate")
>>>
>>> .. both re-construct a seperate "modal" js object and then call one of the two published functions...
>>>
>>> what if you have two different modals? what if they are init-ed differently:
>>>
>>> java:afterRender() {
>>>     require("modal").invoke("init").with("message 1");
>>>     require("modal").invoke("init").with("message 2");
>>> }
>>>
>>> and then later
>>> java:onSomeEvent() {
>>>     require("modal").invoke("activate");
>>> }
>>>
>>> this flow would essentially construct the modal module instance 3 times, and the "activate" wouldn't know about "message 1" or "message 2".
>>>
>>> Therefore, how would I re-aquire a handle to a specific module instance later on? for eg:
>>>
>>> java:onSomeEvent(){
>>>     // activate modal with "message 1"
>>>     require("modal").invoke("activate");
>>> }
>>>
>>> I know this example doesn't make much practical sense, but the concept of communicating with something stateful is pretty key!
>>>
>>> p.
>>>
>>> On 13/11/2014 4:34 PM, Geoff Callender wrote:
>>>> Have you had a look at these two:
>>>>
>>>> http://jumpstart.doublenegative.com.au/jumpstart7/examples/javascript/modal/1
>>>> http://jumpstart.doublenegative.com.au/jumpstart7/examples/javascript/reusablemodal/1
>>>>
>>>> Do they fit your scenario?
>>>>
>>>> On 13 Nov 2014, at 3:40 pm, Paul Stanton <[hidden email]> wrote:
>>>>
>>>>> Hi Geoff,
>>>>>
>>>>> I have found your examples invaluable in learning some of the basics of this (and other) concepts. I can't thank you enough
>>>>>
>>>>> .. the only thing I can see is missing currently is the example I asked about in the previous mail:
>>>>>
>>>>> Basically, how do I interact with a js module instance after it is created?
>>>>>
>>>>> pretend some server-side state changes between afterRender and onSomeEvent, and the client needs to react accordingly.
>>>>>
>>>>> jss.addScript is deprecated, so I "shouldn't" be telling the client to execute script apparently...
>>>>>
>>>>> cheers, p.
>>>>>
>>>>> On 13/11/2014 2:36 PM, Geoff Callender wrote:
>>>>>> do these examples cover the situations you are describing?
>>>>> ---------------------------------------------------------------------
>>>>> To unsubscribe, e-mail: [hidden email]
>>>>> For additional commands, e-mail: [hidden email]
>>>>>
>>>
>>> ---------------------------------------------------------------------
>>> To unsubscribe, e-mail: [hidden email]
>>> For additional commands, e-mail: [hidden email]
>>>
>


---------------------------------------------------------------------
To unsubscribe, e-mail: [hidden email]
For additional commands, e-mail: [hidden email]

12