Bill Keese | 1 Feb 07:17
Favicon
Gravatar

widgets emitting DOM events

I've started working on http://bugs.dojotoolkit.org/ticket/13785 and want to open it up for feedback.

The basic idea is that an app can setup event handlers on a high level node, and get bubbled events from descendant widgets.   So given DOM like

<form id=myForm>
       <input data-dojo-type=dijit/form/NumberTextBox>
       ...
       <button data-dojo-type=dijit/form/Button>click me</button>
       ...
</form>

The app can do:

on(dom.byId("myForm"), "WidgetAttrModified", function(evt){
    console.log("widget " + evt.widget.id + " attribute " + evt.attrName + " set to " + evt.newValue);
});
on(dom.byId("myForm"), "WidgetClick", function(evt){
    console.log("widget " + evt.widget.id + " was clicked ");
});

(BTW, theoretically you could also use on.selector() to only match a subset of the widgets inside of the <form>... especially if we added more attributes to widget DOMNodes such as the widget's declared class.)

Internally, widgets signal events by calling:

    this.emit("Click", [arg1, arg2, arg3], eventObj)

which will:

    a) call legacy onClick() method  (but I think that goes away for 2.0)
    b) execute any callbacks the app registered via _WidgetBase.on(type, callback) with signature callback(arg1, arg2, arg3)
    c) call on.emit(this.domNode, "WidgetClick", eventObj) to propagate the event through the DOM



As a test, I converted StackContainer and TabContainer to use the new API for monitoring changes to panes (like a changed title), and also monitoring clicks on tabs.   The former was fairly straightforward, although for the latter it made me wonder what would be appropriate events from a TabButton to indicate (a) the button was clicked to select that pane or (b) the close button was clicked to delete that pane.   I made them both WidgetClick events (with different attributes), but instead they could be a WidgetSelect event and a WidgetClose event, or something else.   Any opinions on this?    I guess it was a rather complicated example to start with, and it's not clear that the code is any better than before.


Anyway, I think the basic concept is sound, although haven't tested performance etc.   But it does raise some questions:

1) _WidgetBase.on() doesn't catch bubbled events

_WidgetBase.on() doesn't catch bubbled events, which probably makes sense given that on() methods of other classes don't even have a concept of bubbling.   But OTOH it may confuse users who are expecting something like below to catch attribute changes on the descendant widgets:

<form data-dojo-type=dijit/form/Form>
       <script type="dojo/on" data-dojo-event="WidgetAttrModified" data-dojo-args="evt">
               console.log("widget " + evt.widget.id + " attribute " + evt.attrName + " set to " + evt.newValue);
       </script>
       <input data-dojo-type=dijit/form/NumberTextBox>
       ...
       <button data-dojo-type=dijit/form/Button>click me</button>
       ...
</form>

(The code above will never execute.)

To put it another way, requiring users to think about DOMNodes directly is perhaps a little clunky.


2) same or different event names?

Currently I have it using different event names from DOMNodes, for example "WidgetClick" instead of "click", and "WidgetAttrModified" instead of "DOMAttrModified".   That's to avoid infinite loops with (for example) a widget both listening for "click" events and firing them, and also to make it clear when propagated events are from widgets or from DOMNodes.   Note that widgets let most DOM events naturally bubble, with the notable exception of click events.

But it's debatable.

3) which events get bubbled?

Some events like mousemove seem dangerous to bubble because of performance reasons
Other events like onChange() are already covered via WidgetAttrModified (evt.attrName == "value" or for checkboxes "checked")
So, what's a good list of events that widgets should emit?


4) id on focusNode

For accessibility reasons form widgets often set the id attribute on a descendant of this.domNode, rather than on this.domNode itself.   That would confuse users doing a

on(dom.byId("myWidget"), "...", ...);

Perhaps the event should be fired from this.focusNode if defined, or otherwise from this.domNode.


_______________________________________________
dojo-contributors mailing list
dojo-contributors <at> mail.dojotoolkit.org
http://mail.dojotoolkit.org/mailman/listinfo/dojo-contributors
Bill Keese | 1 Feb 08:25
Favicon
Gravatar

nabble

I counted the dojo-interest messages for Jan 31 (Japanese timezone).   12 of the 16 threads matched "nabble" somewhere in the thread.   So apparently, most of the users are using nabble.

Back in December (2011) Torrey said to give him a few weeks to try to find a solution to the problem with nabble corrupting messages and witholding messages that "haven't been approved for the mailing list".   Haven't heard anything since then.   So the question remains whether or not we drop nabble from the website, instead telling users to sign up for the mailing list.
_______________________________________________
dojo-contributors mailing list
dojo-contributors <at> mail.dojotoolkit.org
http://mail.dojotoolkit.org/mailman/listinfo/dojo-contributors
Kitson Kelly | 1 Feb 10:26
Picon
Favicon
Gravatar

Re: nabble

My personal opinion is for the casual user, some sort of "message board" is the best way to interface to the community, although I think very few "hard core" people actually use it directly, focusing more on e-mail.  The problem is that those of us that only use e-mail are often the source of the best stuff.

While I don't have any immediate solution or options, maybe there is a community forum that doubles as a listserv instead of trying to retrofit a listserv into a community forum?  I know it is potentially opening old wounds suggesting we look at alternatives again.

On 1 February 2012 07:25, Bill Keese <bill <at> dojotoolkit.org> wrote:
I counted the dojo-interest messages for Jan 31 (Japanese timezone).   12 of the 16 threads matched "nabble" somewhere in the thread.   So apparently, most of the users are using nabble.

Back in December (2011) Torrey said to give him a few weeks to try to find a solution to the problem with nabble corrupting messages and witholding messages that "haven't been approved for the mailing list".   Haven't heard anything since then.   So the question remains whether or not we drop nabble from the website, instead telling users to sign up for the mailing list.

_______________________________________________
dojo-contributors mailing list
dojo-contributors <at> mail.dojotoolkit.org
http://mail.dojotoolkit.org/mailman/listinfo/dojo-contributors


_______________________________________________
dojo-contributors mailing list
dojo-contributors <at> mail.dojotoolkit.org
http://mail.dojotoolkit.org/mailman/listinfo/dojo-contributors
Christophe Jolif | 1 Feb 11:32
Picon
Gravatar

Re: widgets emitting DOM events

Bill,

Having widget events bubbling might indeed very useful so I'm 100% for
this feature. Now when I read your mail I must admit I fear about
users being a bit confused (like you yourselves mentioned in 1/). If I
well understand we will now have:

1/ standard DOM events
2/ regular Widget events
3/ new Widgets events dispatched as custom DOM events

Isn't there any solution to "merge" 2/ and 3/ to make this a bit
simpler? It sounds for example strange to me to fire the event on the
widget and listen to it on a DOMNode. That seems inconsistent to me a
bit like what you said in 1/. Can't we at least have an optional
parameter to _WidgetBase.on to listen to these events?

--
Christophe

2012/2/1 Bill Keese <bill <at> dojotoolkit.org>:
> I've started working on http://bugs.dojotoolkit.org/ticket/13785 and want to
> open it up for feedback.
>
> The basic idea is that an app can setup event handlers on a high level node,
> and get bubbled events from descendant widgets.   So given DOM like
>
> <form id=myForm>
>        <input data-dojo-type=dijit/form/NumberTextBox>
>        ...
>        <button data-dojo-type=dijit/form/Button>click me</button>
>        ...
> </form>
>
> The app can do:
>
> on(dom.byId("myForm"), "WidgetAttrModified", function(evt){
>     console.log("widget " + evt.widget.id + " attribute " + evt.attrName + "
> set to " + evt.newValue);
> });
> on(dom.byId("myForm"), "WidgetClick", function(evt){
>     console.log("widget " + evt.widget.id + " was clicked ");
> });
>
> (BTW, theoretically you could also use on.selector() to only match a subset
> of the widgets inside of the <form>... especially if we added more
> attributes to widget DOMNodes such as the widget's declared class.)
>
> Internally, widgets signal events by calling:
>
>     this.emit("Click", [arg1, arg2, arg3], eventObj)
>
> which will:
>
>     a) call legacy onClick() method  (but I think that goes away for 2.0)
>     b) execute any callbacks the app registered via _WidgetBase.on(type,
> callback) with signature callback(arg1, arg2, arg3)
>     c) call on.emit(this.domNode, "WidgetClick", eventObj) to propagate the
> event through the DOM
>
>
>
> As a test, I converted StackContainer and TabContainer to use the new API
> for monitoring changes to panes (like a changed title), and also monitoring
> clicks on tabs.   The former was fairly straightforward, although for the
> latter it made me wonder what would be appropriate events from a TabButton
> to indicate (a) the button was clicked to select that pane or (b) the close
> button was clicked to delete that pane.   I made them both WidgetClick
> events (with different attributes), but instead they could be a WidgetSelect
> event and a WidgetClose event, or something else.   Any opinions on this?
>  I guess it was a rather complicated example to start with, and it's not
> clear that the code is any better than before.
>
>
> Anyway, I think the basic concept is sound, although haven't tested
> performance etc.   But it does raise some questions:
>
> 1) _WidgetBase.on() doesn't catch bubbled events
>
> _WidgetBase.on() doesn't catch bubbled events, which probably makes sense
> given that on() methods of other classes don't even have a concept of
> bubbling.   But OTOH it may confuse users who are expecting something like
> below to catch attribute changes on the descendant widgets:
>
> <form data-dojo-type=dijit/form/Form>
>        <script type="dojo/on" data-dojo-event="WidgetAttrModified"
> data-dojo-args="evt">
>                console.log("widget " + evt.widget.id + " attribute " +
> evt.attrName + " set to " + evt.newValue);
>        </script>
>        <input data-dojo-type=dijit/form/NumberTextBox>
>        ...
>        <button data-dojo-type=dijit/form/Button>click me</button>
>        ...
> </form>
>
> (The code above will never execute.)
>
> To put it another way, requiring users to think about DOMNodes directly is
> perhaps a little clunky.
>
>
> 2) same or different event names?
>
> Currently I have it using different event names from DOMNodes, for example
> "WidgetClick" instead of "click", and "WidgetAttrModified" instead of
> "DOMAttrModified".   That's to avoid infinite loops with (for example) a
> widget both listening for "click" events and firing them, and also to make
> it clear when propagated events are from widgets or from DOMNodes.   Note
> that widgets let most DOM events naturally bubble, with the notable
> exception of click events.
>
> But it's debatable.
>
> 3) which events get bubbled?
>
> Some events like mousemove seem dangerous to bubble because of performance
> reasons
> Other events like onChange() are already covered via WidgetAttrModified
> (evt.attrName == "value" or for checkboxes "checked")
> So, what's a good list of events that widgets should emit?
>
>
> 4) id on focusNode
>
> For accessibility reasons form widgets often set the id attribute on a
> descendant of this.domNode, rather than on this.domNode itself.   That would
> confuse users doing a
>
> on(dom.byId("myWidget"), "...", ...);
>
> Perhaps the event should be fired from this.focusNode if defined, or
> otherwise from this.domNode.
>
>
>
> _______________________________________________
> dojo-contributors mailing list
> dojo-contributors <at> mail.dojotoolkit.org
> http://mail.dojotoolkit.org/mailman/listinfo/dojo-contributors
>
Bill Keese | 1 Feb 12:46
Favicon
Gravatar

Re: widgets emitting DOM events

I guess we could have an optional parameter, an API sort-of like this?

myFormWidget.on("click", function(){
     // how do I get the pointer to the descendant widget that was clicked?  is it "this"??
}, true);

On Wed, Feb 1, 2012 at 7:32 PM, Christophe Jolif <cjolif <at> gmail.com> wrote:
Bill,

Having widget events bubbling might indeed very useful so I'm 100% for
this feature. Now when I read your mail I must admit I fear about
users being a bit confused (like you yourselves mentioned in 1/). If I
well understand we will now have:

1/ standard DOM events
2/ regular Widget events
3/ new Widgets events dispatched as custom DOM events

Isn't there any solution to "merge" 2/ and 3/ to make this a bit
simpler? It sounds for example strange to me to fire the event on the
widget and listen to it on a DOMNode. That seems inconsistent to me a
bit like what you said in 1/. Can't we at least have an optional
parameter to _WidgetBase.on to listen to these events?

--
Christophe

2012/2/1 Bill Keese <bill <at> dojotoolkit.org>:
> I've started working on http://bugs.dojotoolkit.org/ticket/13785 and want to
> open it up for feedback.
>
> The basic idea is that an app can setup event handlers on a high level node,
> and get bubbled events from descendant widgets.   So given DOM like
>
> <form id=myForm>
>        <input data-dojo-type=dijit/form/NumberTextBox>
>        ...
>        <button data-dojo-type=dijit/form/Button>click me</button>
>        ...
> </form>
>
> The app can do:
>
> on(dom.byId("myForm"), "WidgetAttrModified", function(evt){
>     console.log("widget " + evt.widget.id + " attribute " + evt.attrName + "
> set to " + evt.newValue);
> });
> on(dom.byId("myForm"), "WidgetClick", function(evt){
>     console.log("widget " + evt.widget.id + " was clicked ");
> });
>
> (BTW, theoretically you could also use on.selector() to only match a subset
> of the widgets inside of the <form>... especially if we added more
> attributes to widget DOMNodes such as the widget's declared class.)
>
> Internally, widgets signal events by calling:
>
>     this.emit("Click", [arg1, arg2, arg3], eventObj)
>
> which will:
>
>     a) call legacy onClick() method  (but I think that goes away for 2.0)
>     b) execute any callbacks the app registered via _WidgetBase.on(type,
> callback) with signature callback(arg1, arg2, arg3)
>     c) call on.emit(this.domNode, "WidgetClick", eventObj) to propagate the
> event through the DOM
>
>
>
> As a test, I converted StackContainer and TabContainer to use the new API
> for monitoring changes to panes (like a changed title), and also monitoring
> clicks on tabs.   The former was fairly straightforward, although for the
> latter it made me wonder what would be appropriate events from a TabButton
> to indicate (a) the button was clicked to select that pane or (b) the close
> button was clicked to delete that pane.   I made them both WidgetClick
> events (with different attributes), but instead they could be a WidgetSelect
> event and a WidgetClose event, or something else.   Any opinions on this?
>  I guess it was a rather complicated example to start with, and it's not
> clear that the code is any better than before.
>
>
> Anyway, I think the basic concept is sound, although haven't tested
> performance etc.   But it does raise some questions:
>
> 1) _WidgetBase.on() doesn't catch bubbled events
>
> _WidgetBase.on() doesn't catch bubbled events, which probably makes sense
> given that on() methods of other classes don't even have a concept of
> bubbling.   But OTOH it may confuse users who are expecting something like
> below to catch attribute changes on the descendant widgets:
>
> <form data-dojo-type=dijit/form/Form>
>        <script type="dojo/on" data-dojo-event="WidgetAttrModified"
> data-dojo-args="evt">
>                console.log("widget " + evt.widget.id + " attribute " +
> evt.attrName + " set to " + evt.newValue);
>        </script>
>        <input data-dojo-type=dijit/form/NumberTextBox>
>        ...
>        <button data-dojo-type=dijit/form/Button>click me</button>
>        ...
> </form>
>
> (The code above will never execute.)
>
> To put it another way, requiring users to think about DOMNodes directly is
> perhaps a little clunky.
>
>
> 2) same or different event names?
>
> Currently I have it using different event names from DOMNodes, for example
> "WidgetClick" instead of "click", and "WidgetAttrModified" instead of
> "DOMAttrModified".   That's to avoid infinite loops with (for example) a
> widget both listening for "click" events and firing them, and also to make
> it clear when propagated events are from widgets or from DOMNodes.   Note
> that widgets let most DOM events naturally bubble, with the notable
> exception of click events.
>
> But it's debatable.
>
> 3) which events get bubbled?
>
> Some events like mousemove seem dangerous to bubble because of performance
> reasons
> Other events like onChange() are already covered via WidgetAttrModified
> (evt.attrName == "value" or for checkboxes "checked")
> So, what's a good list of events that widgets should emit?
>
>
> 4) id on focusNode
>
> For accessibility reasons form widgets often set the id attribute on a
> descendant of this.domNode, rather than on this.domNode itself.   That would
> confuse users doing a
>
> on(dom.byId("myWidget"), "...", ...);
>
> Perhaps the event should be fired from this.focusNode if defined, or
> otherwise from this.domNode.
>
>
>
> _______________________________________________
> dojo-contributors mailing list
> dojo-contributors <at> mail.dojotoolkit.org
> http://mail.dojotoolkit.org/mailman/listinfo/dojo-contributors
>
_______________________________________________
dojo-contributors mailing list
dojo-contributors <at> mail.dojotoolkit.org
http://mail.dojotoolkit.org/mailman/listinfo/dojo-contributors

_______________________________________________
dojo-contributors mailing list
dojo-contributors <at> mail.dojotoolkit.org
http://mail.dojotoolkit.org/mailman/listinfo/dojo-contributors
Bill Keese | 1 Feb 12:55
Favicon
Gravatar

Re: TodoMVC + DojoX MVC - Improvements/Issues

I wish I had time to keep up with the whole MVC discussion.

As far as "something lighter", a long time ago Stephen Chung had made an alternate suggestion of an API to bind any obj1.attr1 to another obj2.attr2.   It was at http://www.mingleplace.com/test/bindingtest.html but unfortunately that page disappeared.

2012/2/1 James Thomas <jthomas.uk <at> gmail.com>
+1 on this, I'd happily play with something lighter and see how it works. 


2012/1/26 Ed Chatelain <ed.chatelain <at> gmail.com>
Ben,
        I am open to the possibility of creating a lightweight model in the dojox.mvc package in addition to the current StatefulModel, if we can come up with a name and an API which would not completely confuse everyone.  I don't want to get rid of the current StatefulModel but I do understand that it is a bit heavy.  Over time we could see which model works best.

Regards,
Ed


2012/1/21 ben hockey <neonstalwart <at> gmail.com>
i've been an enthusiastic early adopter of dojox/mvc and have attempted to make use of it extensively in a "real" project.  if you look through the mvc issues in trac you'll see that i've either reported, patched or heavily commented on many of the tickets.  i feel like i gave it a fair chance during the last ~6 months.

i'm sorry to say that as of this month i gave up on using it in my "real" project.  at first i was so excited to be able to bind values from a model to a widget but i soon ran into limitations.  i'm so glad that james made notes - i think you really covered the main pain points james.  i recently commented on a design doc relating to dojox/mvc and i had trouble recalling details of my struggles but you've covered it well.  also ken, raining on a parade or not, it seems your assessment is reasonably accurate too - particularly the comments relating to declarative markup.

i won't repeat the points again but i would need a majority of the points raised by james and ken to be addressed before i could consider using dojox/mvc again.  i don't want to give up on dojox/mvc completely and so i'll still be watching and participating where possible to try and see improvements made.

in my frustration, i've been looking to alternatives that could meet my need.  knockout [1] seemed somewhat appealing but seems like it would need a little shaping to make it play nicely with dijit.  so far i haven't quite found what i need.  

however, i went back through our mailing list archives to see early discussions surrounding mvc - i remembered that there had been some input about ways to improve dojox/mvc even from the start.  i came across a post from alex [2] mentioning some work on Property Models.  reading some of the papers surrounding this work [3] has got me really excited.  i dug around for a little while longer and found that the work has made its way into the world of javascript as a library called hotdrink [4].  i was even more excited to see that they have a tutorial [5] and a demo [6] that shows how to bind a dijit.form.Slider to a Property Model.  woo hoo!

i've been looking over the code in hotdrink and i'm going to look further into seeing if it can be useful to me somehow.  the part that's most appealing to me is that the binding from the model to the view and the building of the view is general enough that it doesn't matter if the views are dijit or plain DOM elements or anything else.  i'm not even completely sold on the declarative sheets - adam (a syntax for declaring property models) and eve (a syntax for declaring view layouts) but those are interesting too.

for anyone interested in this area, i'd highly recommend taking the time to become familiar with property models even if its just an academic exercise for you.

thanks,

ben...

[3] http://code.google.com/p/hotdrink/downloads/list


On Jan 21, 2012, at 1:56 PM, Kenneth G. Franqueiro wrote:

While I haven't had a chance to look at the TodoMVC example yet, from
what I saw when I was researching the dojox/mvc package a bit, I
somewhat agree with Sasha's sentiment regarding which aspects of Dojo
really deserve the spotlight for promoting separation of concerns
(particularly dojo/store).

The vibe I got from the dojox/mvc package is that it's not so much about
separation of concerns, and a lot more about binding them together.  It
felt rather heavy (with all the Statefuls and watches it hooks up), and
*far* too reliant on declarative markup.  While I realize that
templating is usually a part of these frameworks, I sort of feel that
the most scalable applications built using Dojo lean on declarative
markup as little as possible (other than for widget templates).  The
only piece of dojox/mvc that looked particularly conducive to
programmatic use to me was the Generate module, but that seemed somewhat
limited in usefulness currently, and it still creates declarative markup
to be run through the parser - meaning it's actually even heavier!

Admittedly though, I'm rather uninitiated to DojoX MVC (and relatively,
to MVC frameworks in general), so maybe my concerns don't make a whole
lot of sense.  I do realize that the package lends itself to certain
types of cases and could significantly expedite the process for said
cases.  I guess my premature-optimization OCD just quickly gets the
better of me.  I suppose maybe the project I was potentially looking at
it for didn't seem like the type to significantly reap the benefits from
the full feature set DojoX MVC provides, to justify the weight.

I'm sorry if this sounds like I'm raining on the parade.  It'd be great
if we can improve DojoX MVC's image by addressing some of these concerns
though.

Thanks,
--Ken

On 1/21/2012 1:15 PM, Sasha Firsov wrote:
Hi James,

/Newer toolkits (Backbone, Spine) really promote their MVC support and
I'm not sure many of our users know we can do the same.
/
I would not get too excited on Backbone or Spine. Those are not samples
of good design and clear mind. But agree, they are good in brainwash
playing with MVC words.  I sincerely hope that we would not do same.

DojoX MVC is just separate package which does not reflect the MVC power
of other components. Instead I would point to dojo store(M),
TreeStoreModel(C), dijit.Tree(V) as a good MVC sample.  Unfortunately
the naming convention in dojo does not match popular architectural
terms. Another issue that not all components are fitting to same MVC
delivery chain.
I had in mind to create reusable controller out of TreeStoreModel and
use it for dojo.store to [tab, accordion, form,...] chaining. With a
goal to keep data in hierarchical tree structure keeping in sync.
DojoX MVC is not best candidate just because less coherent with existing
dijits :(

Sasha



_______________________________________________
dojo-contributors mailing list
dojo-contributors <at> mail.dojotoolkit.org
http://mail.dojotoolkit.org/mailman/listinfo/dojo-contributors
_______________________________________________
dojo-contributors mailing list
dojo-contributors <at> mail.dojotoolkit.org
http://mail.dojotoolkit.org/mailman/listinfo/dojo-contributors


_______________________________________________
dojo-contributors mailing list
dojo-contributors <at> mail.dojotoolkit.org
http://mail.dojotoolkit.org/mailman/listinfo/dojo-contributors




--
Ed Chatelain

_______________________________________________
dojo-contributors mailing list
dojo-contributors <at> mail.dojotoolkit.org
http://mail.dojotoolkit.org/mailman/listinfo/dojo-contributors




--
Regards,
James Thomas

_______________________________________________
dojo-contributors mailing list
dojo-contributors <at> mail.dojotoolkit.org
http://mail.dojotoolkit.org/mailman/listinfo/dojo-contributors


_______________________________________________
dojo-contributors mailing list
dojo-contributors <at> mail.dojotoolkit.org
http://mail.dojotoolkit.org/mailman/listinfo/dojo-contributors
Christophe Jolif | 1 Feb 13:02
Picon
Gravatar

Re: widgets emitting DOM events

Bill,

Yes something like this.

I don't think this should be the original target but should be the
widget the listener was registered on.

Wouldn't something like:

registry.byId(event.target.id)

get you to the widget target?

--
Christophe

2012/2/1 Bill Keese <bill <at> dojotoolkit.org>:
> I guess we could have an optional parameter, an API sort-of like this?
>
> myFormWidget.on("click", function(){
>      // how do I get the pointer to the descendant widget that was clicked?
>  is it "this"??
> }, true);
>
> On Wed, Feb 1, 2012 at 7:32 PM, Christophe Jolif <cjolif <at> gmail.com> wrote:
>>
>> Bill,
>>
>> Having widget events bubbling might indeed very useful so I'm 100% for
>> this feature. Now when I read your mail I must admit I fear about
>> users being a bit confused (like you yourselves mentioned in 1/). If I
>> well understand we will now have:
>>
>> 1/ standard DOM events
>> 2/ regular Widget events
>> 3/ new Widgets events dispatched as custom DOM events
>>
>> Isn't there any solution to "merge" 2/ and 3/ to make this a bit
>> simpler? It sounds for example strange to me to fire the event on the
>> widget and listen to it on a DOMNode. That seems inconsistent to me a
>> bit like what you said in 1/. Can't we at least have an optional
>> parameter to _WidgetBase.on to listen to these events?
>>
>> --
>> Christophe
>>
>> 2012/2/1 Bill Keese <bill <at> dojotoolkit.org>:
>> > I've started working on http://bugs.dojotoolkit.org/ticket/13785 and
>> > want to
>> > open it up for feedback.
>> >
>> > The basic idea is that an app can setup event handlers on a high level
>> > node,
>> > and get bubbled events from descendant widgets.   So given DOM like
>> >
>> > <form id=myForm>
>> >        <input data-dojo-type=dijit/form/NumberTextBox>
>> >        ...
>> >        <button data-dojo-type=dijit/form/Button>click me</button>
>> >        ...
>> > </form>
>> >
>> > The app can do:
>> >
>> > on(dom.byId("myForm"), "WidgetAttrModified", function(evt){
>> >     console.log("widget " + evt.widget.id + " attribute " + evt.attrName
>> > + "
>> > set to " + evt.newValue);
>> > });
>> > on(dom.byId("myForm"), "WidgetClick", function(evt){
>> >     console.log("widget " + evt.widget.id + " was clicked ");
>> > });
>> >
>> > (BTW, theoretically you could also use on.selector() to only match a
>> > subset
>> > of the widgets inside of the <form>... especially if we added more
>> > attributes to widget DOMNodes such as the widget's declared class.)
>> >
>> > Internally, widgets signal events by calling:
>> >
>> >     this.emit("Click", [arg1, arg2, arg3], eventObj)
>> >
>> > which will:
>> >
>> >     a) call legacy onClick() method  (but I think that goes away for
>> > 2.0)
>> >     b) execute any callbacks the app registered via _WidgetBase.on(type,
>> > callback) with signature callback(arg1, arg2, arg3)
>> >     c) call on.emit(this.domNode, "WidgetClick", eventObj) to propagate
>> > the
>> > event through the DOM
>> >
>> >
>> >
>> > As a test, I converted StackContainer and TabContainer to use the new
>> > API
>> > for monitoring changes to panes (like a changed title), and also
>> > monitoring
>> > clicks on tabs.   The former was fairly straightforward, although for
>> > the
>> > latter it made me wonder what would be appropriate events from a
>> > TabButton
>> > to indicate (a) the button was clicked to select that pane or (b) the
>> > close
>> > button was clicked to delete that pane.   I made them both WidgetClick
>> > events (with different attributes), but instead they could be a
>> > WidgetSelect
>> > event and a WidgetClose event, or something else.   Any opinions on
>> > this?
>> >  I guess it was a rather complicated example to start with, and it's not
>> > clear that the code is any better than before.
>> >
>> >
>> > Anyway, I think the basic concept is sound, although haven't tested
>> > performance etc.   But it does raise some questions:
>> >
>> > 1) _WidgetBase.on() doesn't catch bubbled events
>> >
>> > _WidgetBase.on() doesn't catch bubbled events, which probably makes
>> > sense
>> > given that on() methods of other classes don't even have a concept of
>> > bubbling.   But OTOH it may confuse users who are expecting something
>> > like
>> > below to catch attribute changes on the descendant widgets:
>> >
>> > <form data-dojo-type=dijit/form/Form>
>> >        <script type="dojo/on" data-dojo-event="WidgetAttrModified"
>> > data-dojo-args="evt">
>> >                console.log("widget " + evt.widget.id + " attribute " +
>> > evt.attrName + " set to " + evt.newValue);
>> >        </script>
>> >        <input data-dojo-type=dijit/form/NumberTextBox>
>> >        ...
>> >        <button data-dojo-type=dijit/form/Button>click me</button>
>> >        ...
>> > </form>
>> >
>> > (The code above will never execute.)
>> >
>> > To put it another way, requiring users to think about DOMNodes directly
>> > is
>> > perhaps a little clunky.
>> >
>> >
>> > 2) same or different event names?
>> >
>> > Currently I have it using different event names from DOMNodes, for
>> > example
>> > "WidgetClick" instead of "click", and "WidgetAttrModified" instead of
>> > "DOMAttrModified".   That's to avoid infinite loops with (for example) a
>> > widget both listening for "click" events and firing them, and also to
>> > make
>> > it clear when propagated events are from widgets or from DOMNodes.
>> > Note
>> > that widgets let most DOM events naturally bubble, with the notable
>> > exception of click events.
>> >
>> > But it's debatable.
>> >
>> > 3) which events get bubbled?
>> >
>> > Some events like mousemove seem dangerous to bubble because of
>> > performance
>> > reasons
>> > Other events like onChange() are already covered via WidgetAttrModified
>> > (evt.attrName == "value" or for checkboxes "checked")
>> > So, what's a good list of events that widgets should emit?
>> >
>> >
>> > 4) id on focusNode
>> >
>> > For accessibility reasons form widgets often set the id attribute on a
>> > descendant of this.domNode, rather than on this.domNode itself.   That
>> > would
>> > confuse users doing a
>> >
>> > on(dom.byId("myWidget"), "...", ...);
>> >
>> > Perhaps the event should be fired from this.focusNode if defined, or
>> > otherwise from this.domNode.
>> >
>> >
>> >
>> > _______________________________________________
>> > dojo-contributors mailing list
>> > dojo-contributors <at> mail.dojotoolkit.org
>> > http://mail.dojotoolkit.org/mailman/listinfo/dojo-contributors
>> >
>> _______________________________________________
>> dojo-contributors mailing list
>> dojo-contributors <at> mail.dojotoolkit.org
>> http://mail.dojotoolkit.org/mailman/listinfo/dojo-contributors
>
>
>
> _______________________________________________
> dojo-contributors mailing list
> dojo-contributors <at> mail.dojotoolkit.org
> http://mail.dojotoolkit.org/mailman/listinfo/dojo-contributors
>
Tom Trenka | 1 Feb 15:50
Picon

Re: widgets emitting DOM events

I don't know if this helps or not, but IIRC both dojox.Grid and dgrid decorate DOM event objects for their handling, so that your handler gets the original DOM event, but with additional information pointing to widget properties.  For instance, in dgrid you can set something up like this:


myGrid.on(".dgrid-cell:click", function(evt){
    var cell = myGrid.cell(e);  // gets you a reference to the cell clicked on in the grid
    if(cell.column.field == "field")....
});

While at first it doesn't seem the most intuitive (especially when you're coming from a pure Dijit background), the approach is actually quite nice in that you get both the DOM and the widget for reading/manipulation.  Perhaps that would be the approach Dijit takes in the future?

-- Tom

On Wed, Feb 1, 2012 at 6:02 AM, Christophe Jolif <cjolif <at> gmail.com> wrote:
Bill,

Yes something like this.

I don't think this should be the original target but should be the
widget the listener was registered on.

Wouldn't something like:

registry.byId(event.target.id)

get you to the widget target?

--
Christophe

2012/2/1 Bill Keese <bill <at> dojotoolkit.org>:
> I guess we could have an optional parameter, an API sort-of like this?
>
> myFormWidget.on("click", function(){
>      // how do I get the pointer to the descendant widget that was clicked?
>  is it "this"??
> }, true);
>
> On Wed, Feb 1, 2012 at 7:32 PM, Christophe Jolif <cjolif <at> gmail.com> wrote:
>>
>> Bill,
>>
>> Having widget events bubbling might indeed very useful so I'm 100% for
>> this feature. Now when I read your mail I must admit I fear about
>> users being a bit confused (like you yourselves mentioned in 1/). If I
>> well understand we will now have:
>>
>> 1/ standard DOM events
>> 2/ regular Widget events
>> 3/ new Widgets events dispatched as custom DOM events
>>
>> Isn't there any solution to "merge" 2/ and 3/ to make this a bit
>> simpler? It sounds for example strange to me to fire the event on the
>> widget and listen to it on a DOMNode. That seems inconsistent to me a
>> bit like what you said in 1/. Can't we at least have an optional
>> parameter to _WidgetBase.on to listen to these events?
>>
>> --
>> Christophe
>>
>> 2012/2/1 Bill Keese <bill <at> dojotoolkit.org>:
>> > I've started working on http://bugs.dojotoolkit.org/ticket/13785 and
>> > want to
>> > open it up for feedback.
>> >
>> > The basic idea is that an app can setup event handlers on a high level
>> > node,
>> > and get bubbled events from descendant widgets.   So given DOM like
>> >
>> > <form id=myForm>
>> >        <input data-dojo-type=dijit/form/NumberTextBox>
>> >        ...
>> >        <button data-dojo-type=dijit/form/Button>click me</button>
>> >        ...
>> > </form>
>> >
>> > The app can do:
>> >
>> > on(dom.byId("myForm"), "WidgetAttrModified", function(evt){
>> >     console.log("widget " + evt.widget.id + " attribute " + evt.attrName
>> > + "
>> > set to " + evt.newValue);
>> > });
>> > on(dom.byId("myForm"), "WidgetClick", function(evt){
>> >     console.log("widget " + evt.widget.id + " was clicked ");
>> > });
>> >
>> > (BTW, theoretically you could also use on.selector() to only match a
>> > subset
>> > of the widgets inside of the <form>... especially if we added more
>> > attributes to widget DOMNodes such as the widget's declared class.)
>> >
>> > Internally, widgets signal events by calling:
>> >
>> >     this.emit("Click", [arg1, arg2, arg3], eventObj)
>> >
>> > which will:
>> >
>> >     a) call legacy onClick() method  (but I think that goes away for
>> > 2.0)
>> >     b) execute any callbacks the app registered via _WidgetBase.on(type,
>> > callback) with signature callback(arg1, arg2, arg3)
>> >     c) call on.emit(this.domNode, "WidgetClick", eventObj) to propagate
>> > the
>> > event through the DOM
>> >
>> >
>> >
>> > As a test, I converted StackContainer and TabContainer to use the new
>> > API
>> > for monitoring changes to panes (like a changed title), and also
>> > monitoring
>> > clicks on tabs.   The former was fairly straightforward, although for
>> > the
>> > latter it made me wonder what would be appropriate events from a
>> > TabButton
>> > to indicate (a) the button was clicked to select that pane or (b) the
>> > close
>> > button was clicked to delete that pane.   I made them both WidgetClick
>> > events (with different attributes), but instead they could be a
>> > WidgetSelect
>> > event and a WidgetClose event, or something else.   Any opinions on
>> > this?
>> >  I guess it was a rather complicated example to start with, and it's not
>> > clear that the code is any better than before.
>> >
>> >
>> > Anyway, I think the basic concept is sound, although haven't tested
>> > performance etc.   But it does raise some questions:
>> >
>> > 1) _WidgetBase.on() doesn't catch bubbled events
>> >
>> > _WidgetBase.on() doesn't catch bubbled events, which probably makes
>> > sense
>> > given that on() methods of other classes don't even have a concept of
>> > bubbling.   But OTOH it may confuse users who are expecting something
>> > like
>> > below to catch attribute changes on the descendant widgets:
>> >
>> > <form data-dojo-type=dijit/form/Form>
>> >        <script type="dojo/on" data-dojo-event="WidgetAttrModified"
>> > data-dojo-args="evt">
>> >                console.log("widget " + evt.widget.id + " attribute " +
>> > evt.attrName + " set to " + evt.newValue);
>> >        </script>
>> >        <input data-dojo-type=dijit/form/NumberTextBox>
>> >        ...
>> >        <button data-dojo-type=dijit/form/Button>click me</button>
>> >        ...
>> > </form>
>> >
>> > (The code above will never execute.)
>> >
>> > To put it another way, requiring users to think about DOMNodes directly
>> > is
>> > perhaps a little clunky.
>> >
>> >
>> > 2) same or different event names?
>> >
>> > Currently I have it using different event names from DOMNodes, for
>> > example
>> > "WidgetClick" instead of "click", and "WidgetAttrModified" instead of
>> > "DOMAttrModified".   That's to avoid infinite loops with (for example) a
>> > widget both listening for "click" events and firing them, and also to
>> > make
>> > it clear when propagated events are from widgets or from DOMNodes.
>> > Note
>> > that widgets let most DOM events naturally bubble, with the notable
>> > exception of click events.
>> >
>> > But it's debatable.
>> >
>> > 3) which events get bubbled?
>> >
>> > Some events like mousemove seem dangerous to bubble because of
>> > performance
>> > reasons
>> > Other events like onChange() are already covered via WidgetAttrModified
>> > (evt.attrName == "value" or for checkboxes "checked")
>> > So, what's a good list of events that widgets should emit?
>> >
>> >
>> > 4) id on focusNode
>> >
>> > For accessibility reasons form widgets often set the id attribute on a
>> > descendant of this.domNode, rather than on this.domNode itself.   That
>> > would
>> > confuse users doing a
>> >
>> > on(dom.byId("myWidget"), "...", ...);
>> >
>> > Perhaps the event should be fired from this.focusNode if defined, or
>> > otherwise from this.domNode.
>> >
>> >
>> >
>> > _______________________________________________
>> > dojo-contributors mailing list
>> > dojo-contributors <at> mail.dojotoolkit.org
>> > http://mail.dojotoolkit.org/mailman/listinfo/dojo-contributors
>> >
>> _______________________________________________
>> dojo-contributors mailing list
>> dojo-contributors <at> mail.dojotoolkit.org
>> http://mail.dojotoolkit.org/mailman/listinfo/dojo-contributors
>
>
>
> _______________________________________________
> dojo-contributors mailing list
> dojo-contributors <at> mail.dojotoolkit.org
> http://mail.dojotoolkit.org/mailman/listinfo/dojo-contributors
>
_______________________________________________
dojo-contributors mailing list
dojo-contributors <at> mail.dojotoolkit.org
http://mail.dojotoolkit.org/mailman/listinfo/dojo-contributors

_______________________________________________
dojo-contributors mailing list
dojo-contributors <at> mail.dojotoolkit.org
http://mail.dojotoolkit.org/mailman/listinfo/dojo-contributors
Tom Trenka | 1 Feb 15:57
Picon

Re: widgets emitting DOM events

Sorry, the (e) argument in the myGrid.cell should have been "evt"...anyways, to expound on the idea, you could have something like this:


myDijitForm.on(".dijit-Textbox:change", function(evt){
    var textbox = myDijitForm.getWidget(evt);
    if(textbox.get("value") == "foo")...
});

It would take advantage of event bubbling without the need to write a separate bubbling system by using selectors to set up the event listening.  Could be worth pursuing...

Tom

On Wed, Feb 1, 2012 at 8:50 AM, Tom Trenka <ttrenka <at> gmail.com> wrote:
I don't know if this helps or not, but IIRC both dojox.Grid and dgrid decorate DOM event objects for their handling, so that your handler gets the original DOM event, but with additional information pointing to widget properties.  For instance, in dgrid you can set something up like this:

myGrid.on(".dgrid-cell:click", function(evt){
    var cell = myGrid.cell(e);  // gets you a reference to the cell clicked on in the grid
    if(cell.column.field == "field")....
});

While at first it doesn't seem the most intuitive (especially when you're coming from a pure Dijit background), the approach is actually quite nice in that you get both the DOM and the widget for reading/manipulation.  Perhaps that would be the approach Dijit takes in the future?

-- Tom


On Wed, Feb 1, 2012 at 6:02 AM, Christophe Jolif <cjolif <at> gmail.com> wrote:
Bill,

Yes something like this.

I don't think this should be the original target but should be the
widget the listener was registered on.

Wouldn't something like:

registry.byId(event.target.id)

get you to the widget target?

--
Christophe

2012/2/1 Bill Keese <bill <at> dojotoolkit.org>:
> I guess we could have an optional parameter, an API sort-of like this?
>
> myFormWidget.on("click", function(){
>      // how do I get the pointer to the descendant widget that was clicked?
>  is it "this"??
> }, true);
>
> On Wed, Feb 1, 2012 at 7:32 PM, Christophe Jolif <cjolif <at> gmail.com> wrote:
>>
>> Bill,
>>
>> Having widget events bubbling might indeed very useful so I'm 100% for
>> this feature. Now when I read your mail I must admit I fear about
>> users being a bit confused (like you yourselves mentioned in 1/). If I
>> well understand we will now have:
>>
>> 1/ standard DOM events
>> 2/ regular Widget events
>> 3/ new Widgets events dispatched as custom DOM events
>>
>> Isn't there any solution to "merge" 2/ and 3/ to make this a bit
>> simpler? It sounds for example strange to me to fire the event on the
>> widget and listen to it on a DOMNode. That seems inconsistent to me a
>> bit like what you said in 1/. Can't we at least have an optional
>> parameter to _WidgetBase.on to listen to these events?
>>
>> --
>> Christophe
>>
>> 2012/2/1 Bill Keese <bill <at> dojotoolkit.org>:
>> > I've started working on http://bugs.dojotoolkit.org/ticket/13785 and
>> > want to
>> > open it up for feedback.
>> >
>> > The basic idea is that an app can setup event handlers on a high level
>> > node,
>> > and get bubbled events from descendant widgets.   So given DOM like
>> >
>> > <form id=myForm>
>> >        <input data-dojo-type=dijit/form/NumberTextBox>
>> >        ...
>> >        <button data-dojo-type=dijit/form/Button>click me</button>
>> >        ...
>> > </form>
>> >
>> > The app can do:
>> >
>> > on(dom.byId("myForm"), "WidgetAttrModified", function(evt){
>> >     console.log("widget " + evt.widget.id + " attribute " + evt.attrName
>> > + "
>> > set to " + evt.newValue);
>> > });
>> > on(dom.byId("myForm"), "WidgetClick", function(evt){
>> >     console.log("widget " + evt.widget.id + " was clicked ");
>> > });
>> >
>> > (BTW, theoretically you could also use on.selector() to only match a
>> > subset
>> > of the widgets inside of the <form>... especially if we added more
>> > attributes to widget DOMNodes such as the widget's declared class.)
>> >
>> > Internally, widgets signal events by calling:
>> >
>> >     this.emit("Click", [arg1, arg2, arg3], eventObj)
>> >
>> > which will:
>> >
>> >     a) call legacy onClick() method  (but I think that goes away for
>> > 2.0)
>> >     b) execute any callbacks the app registered via _WidgetBase.on(type,
>> > callback) with signature callback(arg1, arg2, arg3)
>> >     c) call on.emit(this.domNode, "WidgetClick", eventObj) to propagate
>> > the
>> > event through the DOM
>> >
>> >
>> >
>> > As a test, I converted StackContainer and TabContainer to use the new
>> > API
>> > for monitoring changes to panes (like a changed title), and also
>> > monitoring
>> > clicks on tabs.   The former was fairly straightforward, although for
>> > the
>> > latter it made me wonder what would be appropriate events from a
>> > TabButton
>> > to indicate (a) the button was clicked to select that pane or (b) the
>> > close
>> > button was clicked to delete that pane.   I made them both WidgetClick
>> > events (with different attributes), but instead they could be a
>> > WidgetSelect
>> > event and a WidgetClose event, or something else.   Any opinions on
>> > this?
>> >  I guess it was a rather complicated example to start with, and it's not
>> > clear that the code is any better than before.
>> >
>> >
>> > Anyway, I think the basic concept is sound, although haven't tested
>> > performance etc.   But it does raise some questions:
>> >
>> > 1) _WidgetBase.on() doesn't catch bubbled events
>> >
>> > _WidgetBase.on() doesn't catch bubbled events, which probably makes
>> > sense
>> > given that on() methods of other classes don't even have a concept of
>> > bubbling.   But OTOH it may confuse users who are expecting something
>> > like
>> > below to catch attribute changes on the descendant widgets:
>> >
>> > <form data-dojo-type=dijit/form/Form>
>> >        <script type="dojo/on" data-dojo-event="WidgetAttrModified"
>> > data-dojo-args="evt">
>> >                console.log("widget " + evt.widget.id + " attribute " +
>> > evt.attrName + " set to " + evt.newValue);
>> >        </script>
>> >        <input data-dojo-type=dijit/form/NumberTextBox>
>> >        ...
>> >        <button data-dojo-type=dijit/form/Button>click me</button>
>> >        ...
>> > </form>
>> >
>> > (The code above will never execute.)
>> >
>> > To put it another way, requiring users to think about DOMNodes directly
>> > is
>> > perhaps a little clunky.
>> >
>> >
>> > 2) same or different event names?
>> >
>> > Currently I have it using different event names from DOMNodes, for
>> > example
>> > "WidgetClick" instead of "click", and "WidgetAttrModified" instead of
>> > "DOMAttrModified".   That's to avoid infinite loops with (for example) a
>> > widget both listening for "click" events and firing them, and also to
>> > make
>> > it clear when propagated events are from widgets or from DOMNodes.
>> > Note
>> > that widgets let most DOM events naturally bubble, with the notable
>> > exception of click events.
>> >
>> > But it's debatable.
>> >
>> > 3) which events get bubbled?
>> >
>> > Some events like mousemove seem dangerous to bubble because of
>> > performance
>> > reasons
>> > Other events like onChange() are already covered via WidgetAttrModified
>> > (evt.attrName == "value" or for checkboxes "checked")
>> > So, what's a good list of events that widgets should emit?
>> >
>> >
>> > 4) id on focusNode
>> >
>> > For accessibility reasons form widgets often set the id attribute on a
>> > descendant of this.domNode, rather than on this.domNode itself.   That
>> > would
>> > confuse users doing a
>> >
>> > on(dom.byId("myWidget"), "...", ...);
>> >
>> > Perhaps the event should be fired from this.focusNode if defined, or
>> > otherwise from this.domNode.
>> >
>> >
>> >
>> > _______________________________________________
>> > dojo-contributors mailing list
>> > dojo-contributors <at> mail.dojotoolkit.org
>> > http://mail.dojotoolkit.org/mailman/listinfo/dojo-contributors
>> >
>> _______________________________________________
>> dojo-contributors mailing list
>> dojo-contributors <at> mail.dojotoolkit.org
>> http://mail.dojotoolkit.org/mailman/listinfo/dojo-contributors
>
>
>
> _______________________________________________
> dojo-contributors mailing list
> dojo-contributors <at> mail.dojotoolkit.org
> http://mail.dojotoolkit.org/mailman/listinfo/dojo-contributors
>
_______________________________________________
dojo-contributors mailing list
dojo-contributors <at> mail.dojotoolkit.org
http://mail.dojotoolkit.org/mailman/listinfo/dojo-contributors


_______________________________________________
dojo-contributors mailing list
dojo-contributors <at> mail.dojotoolkit.org
http://mail.dojotoolkit.org/mailman/listinfo/dojo-contributors
Kitson Kelly | 1 Feb 16:57
Picon
Favicon
Gravatar

Parser Auto-Require

All:

I have been working on (under the guidance of Bill and Ben) a patch to the dojo/parser that would allow the auto-requirement of modules by the parser by specifying their MID in the data-dojo-type.  It is covered by ticket #14591.

We had previously had committed a patch (ticket #13778) that allowed the specification of a MID, but the module would have already need to be loaded prior to invocation to the scope.  This patch though requires a rather significant overhaul of the dojo/parser in order to be able to support the asynchronous nature of module loading under AMD.  On the other hand, my opinion is that this actually puts us in a better position for 2.0 for further enhancing the parser and can hopefully support some planned features a little bit easier.

While on the surface, the parser is fully API backwards compatible, there are some interesting changes to note:
  • Constructors are resolved separately from the scanning of the DOM
  • The ".stopParser" feature of items like ContentPanes and the inheritance of special attributes like "lang" "dir" and "data-dojo-textdir" are broken out from the scan of the DOM.
  • Several internal methods are created that may or may not be handy for other users (mapCtorProto, propagateChildren, _getCtor, scan and _instantiate)
  • The internal representation of parsed objects has heavily changed.
  • parser.parse() and parser.instantiate() return a Deferred when there are modules loaded asynchronously (there is a limitation in that if the code runs synchronously, the instantiated objects only are returned, therefore end users should use a Deferred.when(parser.parse(), function() {}) instead of a parser.parser().then(function() {}); when dealing with potentially deferred returns.
This patch does seem to change the performance of the dojo/parser, but strangely in some browsers it improves performance in certain situations and in others it decreases performance.  We have tried to optimise everything we can in order to ensure that we are giving everything as much benefit as possible and hope that generally speaking, real world examples will either be improved performance or on par with previous parser performance.

I have been committing incrementally to my own fork on github and Bill and Ben have been actively commenting on my changes over the past couple of days.  I have posted a full patch into the ticket against the current TRUNK.  I would encourage anyone interested to assess the patch, comment or ask any questions.

Regards,
Kit
_______________________________________________
dojo-contributors mailing list
dojo-contributors <at> mail.dojotoolkit.org
http://mail.dojotoolkit.org/mailman/listinfo/dojo-contributors

Gmane