FAQ
Partly sparked by Alex's last blog post [1] (I've been thinking about
this subject anyway though), I wanted to go little further in looking
ahead at how I believe we can develop Dojo, RequireJS, and has.js to
create truly optimal applications across different browsers/devices.
First, a few foundational principles. The last decade of JavaScript
development has clearly taught the reliability of using feature
detection. To be clear, UA-sniffing does belong in our source code. This
is clearly the right way to create future-proof source code and to avoid
this in our source code for the sake of performance would be premature
optimization. However, Alex has also clearly pointed out that feature
detection must be optimized out eventually. While our source code may
use feature detection, it is unacceptable for all the feature tests to
optimizations are available. This is where the build comes in. For the
most part, a built application should be based on UA, and use feature
detection as little as possible. Arguing about whether feature detection
or UA-sniffing naive. Briefly, the right time for feature detection and
UA-sniffing is:
* Feature detection at source code level
* UA based determination of features at the build level to eliminate
run-time feature tests

With this approach our source code is future-proof and we can readily
create builds based on the latest UA feature sets without source code
modifications.

Fortunately our move to the standardized convention of has() makes this
type of optimization well within reach. RequireJS has already proven the
ease at which has() branches can eliminate unused feature branches/code.
However, currently we are not offering any help with the actual creation
of UA-specific build layers and the branching to those layers. RequireJS
simply delegates this to the developer to deal with. This is a
non-trivial problem though, and I think significant benefit can be
gained by providing tooling/help in this area.

I threw together a little package to demonstrate a solution we could
provide for UA-sniffing based optimization for feature detection (this
is not functional code right now, just demonstrates the idea):
https://github.com/kriszyp/ua-optimized
The basic premise here is that we have a AMD plugin "ua-optimized" that
can do UA-sniffing to branch to different build layers that were

require(["ua-optimized!my-app"]);

At dev time ua-optimized! would basically be a no-op and would just load
the "my-app" module. During the build, ua-optimized would generate
various (perhaps a dozen or even dozens) build/layers of my-app based
optimized for different UA's and their known feature sets and then most
or all of feature tests and used branches would eliminated. It would
also generate a "default" layer that would corresponded to unknown UAs
and would include all the features and branches. When ua-optimized is
run on built modules, it would then use the UA string to load the
correct UA-specific version of my-app (or the default if the UA is not
known).

Again, the advantage here is that one could build applications and
properly make use of feature detection for safe, reliable code. The
built applications can leverage known UAs to short-cut out of
unnecessary feature tests, while still falling back to feature tests for
unknown user agents. UA-feature set information can be updated in the
future to improve builds without any modification to source code.

There are a couple minor pieces needed to put this puzzle together:

* We need an API for AMD plugins to trigger recursive builds. I assume
this is a pretty simple addition to the build systems.
* We need a database of UAs and their feature sets (based on has.js
tests). Is Pete or any has.js folks already collecting this information?

From bogus@does.not.exist.com Tue Jan 18 18:42:17 2011
From: bogus@does.not.exist.com ()
Date: Tue, 18 Jan 2011 23:42:17 -0000
Subject: No subject
Message-ID: <mailman.1.1296498952.13280.dojo-contributors@mail.dojotoolkit.org>

is getting stored somewhere.

[1] http://infrequently.org/2011/01/cutting-the-interrogation-short/

Thanks,
Kris
<https://github.com/kriszyp/ua-optimized>

--------------040204080907020508010208
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

<html>

<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<body bgcolor="#FFFFFF" text="#000000">
Partly sparked by Alex's last blog post [1] (I've been thinking
looking ahead at how I believe we can develop Dojo, RequireJS, and
has.js to create truly optimal applications across different
browsers/devices. First, a few foundational principles. The last
decade of JavaScript development has clearly taught the reliability
of using feature detection. To be clear, UA-sniffing does belong in
our source code. This is clearly the right way to create
future-proof source code and to avoid this in our source code for
the sake of performance would be premature optimization. However,
Alex has also clearly pointed out that feature detection must be
optimized out eventually. While our source code may use feature
detection, it is unacceptable for all the feature tests to be
optimizations are available. This is where the build comes in. For
the most part, a built application should be based on UA, and use
feature detection as little as possible. Arguing about whether
feature detection or UA-sniffing naive. Briefly, the right time for
feature detection and UA-sniffing is:<br>
* Feature detection at source code level<br>
* UA based determination of features at the build level to eliminate
run-time feature tests<br>
<br>
With this approach our source code is future-proof and we can
readily create builds based on the latest UA feature sets without
source code modifications.<br>
<br>
Fortunately our move to the standardized convention of has() makes
this type of optimization well within reach. RequireJS has already
proven the ease at which has() branches can eliminate unused feature
branches/code. However, currently we are not offering any help with
the actual creation of UA-specific build layers and the branching to
those layers. RequireJS simply delegates this to the developer to
deal with. This is a non-trivial problem though, and I think
significant benefit can be gained by providing tooling/help in this
area.<br>
<br>
I threw together a little package to demonstrate a solution we could
provide for UA-sniffing based optimization for feature detection
(this is not functional code right now, just demonstrates the idea):<br>
<a href="https://github.com/kriszyp/ua-optimized">https://github.com/kriszyp/ua-optimized</a><br>
The basic premise here is that we have a AMD plugin "ua-optimized"
that can do UA-sniffing to branch to different build layers that
like:<br>
<br>
require(["ua-optimized!my-app"]);<br>
<br>
At dev time ua-optimized! would basically be a no-op and would just
load the "my-app" module. During the build, ua-optimized would
generate various (perhaps a dozen or even dozens) build/layers of
my-app based optimized for different UA's and their known feature
sets and then most or all of feature tests and used branches would
eliminated. It would also generate a "default" layer that would
corresponded to unknown UAs and would include all the features and
branches. When ua-optimized is run on built modules, it would then
use the UA string to load the correct UA-specific version of my-app
(or the default if the UA is not known). <br>
<br>
Again, the advantage here is that one could build applications and
properly make use of feature detection for safe, reliable code. The
built applications can leverage known UAs to short-cut out of
unnecessary feature tests, while still falling back to feature tests
for unknown user agents. UA-feature set information can be updated
in the future to improve builds without any modification to source
code.<br>
<br>
There are a couple minor pieces needed to put this puzzle together:<br>
<br>
* We need an API for AMD plugins to trigger recursive builds. I
assume this is a pretty simple addition to the build systems.<br>
* We need a database of UAs and their feature sets (based on has.js
tests). Is Pete or any has.js folks already collecting this
information? From
<a class="moz-txt-link-freetext" href="http://dante.dojotoolkit.org/hasjs/tests/runTests.html">http://dante.dojotoolkit.org/hasjs/tests/runTests.html</a>, it looks it
is getting stored somewhere.<br>
<br>
[1] <a
href="http://infrequently.org/2011/01/cutting-the-interrogation-short/">http://infrequently.org/2011/01/cutting-the-interrogation-short/</a><br>
<br>
Thanks,<br>
Kris<br>
<a href="https://github.com/kriszyp/ua-optimized"></a>
</body>
</html>

--------------040204080907020508010208--

## Search Discussions

•  at Jan 31, 2011 at 5:25 pm ⇧

On 1/31/2011 11:35 AM, Kris Zyp wrote:
Partly sparked by Alex's last blog post [1] (I've been thinking about
this subject anyway though), I wanted to go little further in looking
ahead at how I believe we can develop Dojo, RequireJS, and has.js to
create truly optimal applications across different browsers/devices.
First, a few foundational principles. The last decade of JavaScript
development has clearly taught the reliability of using feature
detection. To be clear, UA-sniffing does belong in our source code.
Correction: UA-sniffing does *not* belong in our source code.

Sorry for the typo.
Kris
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.dojotoolkit.org/pipermail/dojo-contributors/attachments/20110131/0599ac2c/attachment.htm
•  at Jan 31, 2011 at 6:20 pm ⇧

2011/1/31 Kris Zyp <kzyp at dojotoolkit.org>:
* We need an API for AMD plugins to trigger recursive builds. I assume this
is a pretty simple addition to the build systems.
This is just my first thoughts, so subject to change/good arguments:

The multi-build work should be done outside of the loader plugin, and
even outside the main builder used for JS modules. This is a job for a
more generic build tool like make or ant.

I believe the build tool for a JavaScript dependency system should
focus more strictly on combining sets of modules together, since that
is the hard part that cannot be replicated in other build systems
optimized resources).

Furthermore, I would expect Dojo to never ship with all of those
builds done as part of a Dojo distribution -- that is an optimization
step reserved for the optimization of an app, not of a library that
may be used as an app. Or if it is distributed, it is not the main
distribution -- something that has 5-10 builds of the toolkit inside
it for each type of UA profile would freak people out just on the
download size alone, never mind the set of server rules they need to
put in place to serve them correctly.

While it is worthwhile to work out a system for UA+version specific
builds, not everyone will want them. The file size management
complexity cost and serverside URL routing setup to get it to work
will be seen as too much complication for many sites, and I expect
that once a display ad service is put on the site, any gain by this
sort of optimization will likely go unnoticed, particularly if only
the has tests used by the code are included vs. the full set.

To be clear: I am not arguing it is not worthwhile, but that it is
just one piece of an optimization story, and there is a complexity
cost to implementing it, and not everyone should be forced to take the
hit of that complexity cost. It needs to be taken when the site is

So I see the work as identifying how more generic build tools could
use a database of the has profiles in a build step. I could see this
as generally useful knowledge that is tracked as part of the has.js
project, since it is likely useful even outside any JS module-specific
build tool.

James

From bogus@does.not.exist.com Tue Jan 18 18:42:17 2011
From: bogus@does.not.exist.com ()
Date: Tue, 18 Jan 2011 23:42:17 -0000
Subject: No subject
Message-ID: <mailman.5.1297912278.13280.dojo-contributors@mail.dojotoolkit.org>

- 2/21 - 1.6 RC
- 2/28 - 1.6 release
- IE9 will be supported in a point release, presumably 1.6.1

--002354435d081a7887049c71bee5
Content-Type: text/html; charset=ISO-8859-1

From bogus@does.not.exist.com Tue Jan 18 18:42:17 2011
From: bogus@does.not.exist.com ()
Date: Tue, 18 Jan 2011 23:42:17 -0000
Subject: No subject
Message-ID: <mailman.6.1297912279.13280.dojo-contributors@mail.dojotoolkit.org>

--002354435d081a7887049c71bee5--

From bogus@does.not.exist.com Tue Jan 18 18:42:17 2011
From: bogus@does.not.exist.com ()
Date: Tue, 18 Jan 2011 23:42:17 -0000
Subject: No subject
Message-ID: <mailman.8.1299377370.13280.dojo-contributors@mail.dojotoolkit.org>

worst case, every node with a "ref" setting will trace up to <body> looking
for a parent ref. That still sounds CPU intensive but maybe not the end of
the world.

Note: you probably should be calling dojo.getObject() rather than
dojo.eval(), will you ever pass eval() more than a dot separated identifier?

--------
I'm still confused by ref vs. binding. In one of your test files you
have:

dijit.byId("view").set("binding", binding);

Yet, there's no "binding" attribute declared in _DataBindingMixin.js.

In one of your test files you have:

<input id="taxes" dojoType="dijit.form.NumberTextBox" ref="
loanModel.Taxes"/>

In that example ref is both the StatefulModel object and the attribute
inside of it. (loanModel.Taxes is a number, right?)

------
Have you thought that users might try to specify ref (or is it binding?) as
an object rather than as a string? Something like:

new dijit.form.TextBox({ref: myStatefulModel.employeeName})

That's not quite right because it will end up as though I had done this:

new dijit.form.TextBox({ref: "John Smith"})

but anyway it seems like the app should be able to specify the Stateful
object being bound as an object rather than as a string name of a global
variable.

Note that we have this pattern in other widget parameters, for example
DateTextBox.value is a Date object, but when you construct a DateTextBox or
call set("value", ...) you can pass in a string for the value and it gets
converted. In your case it seems like ref (or is it binding?) should be an
Object, but you allow a string as a parameter to the constructor or argument
to set("ref", ...) .

----------

Here's a test case for you to add, it seems like this should work, but it

myWidget = new myWidget({ref: "foo.bar"}) <--- can't eval ref yet
since no parent
myWidget.placeAt(dojo.body());
myWidget.startup() <--- should set widget's value according to model
myWiget.set("ref", "baz.bam") <-- should reset widget's value according
to new model

On Sun, Mar 6, 2011 at 5:17 AM, Rahul Akolkar wrote:

Hi Bill,

Inline.
On Fri, Mar 4, 2011 at 10:33 PM, Bill Keese wrote:
Glad you are getting good feedback from Ben.
<snip/>

Yup, good to have more pairs of eagle eyes on this. I am in the middle
of some minor refactorings based on all the comments so far. I expect
to have a refreshed patch by the end of the weekend.

Here's a reply to some of the stuff from my original note.
<snap/>

Thanks, I was hoping it'd come in before my refreshed patch became ready
:-)

2. DataBindingMixin

a) file structure
The root of the patch is _DataBindingMixin.js, which gets mixed into
_WidgetBase. Current code for that is split across two files as:

dojo.declare("dijit._DataBindingMixin", null, { ... });

dojo.extend(dijit._WidgetBase, new dijit._DataBindingMixin());

It would be simpler like this:

dojo.extend(dijit._WidgetBase, {...});

You can still pull _DataBindingMixin.js into StatefulModel.js if you
don't
want apps to need to explicitly dojo.require(DataBindingMixin).
<snap/>

Correct, thats indeed the objective. The data binding mixin is not
something we'd want apps to explicitly dojo.require(). By "pull into",
I'm thinking you mean inline the source into the other file? Thats an
option.

Sorry, I meant that you could list _DataBindingMixin in the list of requires
for StatefulModel, in the first line define() call.
<snip/>

Oh, got it.

But I agree with Ben's comment, it seems wrong to make a dijit dependency on
StatefulModel just so apps can avoid an extra dojo.require() call
Would StatefulModel ever be useful outside of widgets? A recursive
dojo.Stateful sounds useful in general, not sure about the other stuff in
there.
<snap/>

Right, the dijit.StatefulModel class is already geared to deal with
specifics of a view layer (all the valid, readOnly, relevant etc.
meta-data lends well to view layer bindings). In theory, one could
capture the essence of the recursive model for reuse elsewhere. But
while it may be possible to craft a base class that is purely a
recursive dojo.Stateful model and then subclass it to provide what is
effectively dijit.StatefulModel functionality now, I can't say I have
many usecases at hand. Ofcourse, such refactoring can also happen down

e) _initControl()

This is run from postCreate(), yet it assumes that the widget is
anchored to
the document. You shouldn't assume that until startup() is called;
in
particular it's not true for programatically created widgets ex: new
dijit.form.TextBox().placeAt(...)
<snip/>

OK, I'll look into (d) and (e) above.
About having every widget trace up the tree to find a parent with a binding
specified, or if there's no such parent then tracing all the way to
<body>... we faced that same problem with the bidi group and their
lobbying for every widget to support a dir parameter (possibly) being
inherited from an ancestor . We didn't want to have every single widget
calling getParent() repeatedly to inspect it's ancestors as that seemed like
the parser to pass down the dir inherited from the ancestor. I wonder if
that makes sense here.
<snip/>

It may make sense, but let me step back a bit. Some thoughts, in no
particular order:

I assume by getParent() you mean dijit.getEnclosingWidget() which is
what is used here. The number of these calls is a function of: (a)
Number of data-bound widgets, (b) Topology of binds i.e. amount of
relative refs implied by nesting and (c) Average DOM separation (along
parent axis) between nested data-bound dijits.

The observed rule of thumb is that at page load you'd expect roughly
2x the number of dijit.getEnclosingWidget() calls as the number of
data-bound widgets. This is somewhat less pervasive than bidi as it
only applies to data-bound dijits (clearly, a view may have data-bound
dijits and others that aren't data-bound).

There are two scenarios where bindings are calculated (or recalculated):
* Programmatic binding update (example: when user chooses to list
details for a particular search result in the master-detail demos in
the patch, causing the bindings in the detail portion of the view to
be updated)

_setupBinding(), which effectively removes the need for any DOM
operations or parent widget lookups in the second case.

For the initial page load, the roughly 2x dijit.getEnclosingWidget()
calls may be avoided if we can get the parent binding to be
"inherited" through the parser. OTOH, these calls aren't terribly
expensive either (operations therein include .parentNode references,
getting the widgetId attribute values and a lookups into the widget
registry), so some of this could be done as incremental improvements.

In your response to Ben you gave this example:
model:
{ foo : { bar : { baz : { freddy : { frog : "prince" } } } } }

markup:
<div dojoType="dijit.mvc.Group" ref="model.foo">
<div dojoType="dijit.mvc.Group" ref="bar">
<div dojoType="dijit.mvc.Group" ref="baz">
<div dojoType="dijit.mvc.Group" ref="freddy">
<div dojoType="dijit.form.TextBox" ref="frog">

Hopefully that doesn't execute in O(n^2), where every widget needs to trace
to the top of the tree, does it?
<snap/>

In the above example:
* There are exactly 5 getEnclosingWidget() calls
* The total number of node.parentNode references looked up (including
those within these 5 calls) is exactly equal to the DOM depth of the
textbox on the page

Let me try to understand why you say O(n^2), since every widget isn't
trying to reach every other widget on the page. Worst case performance
is linear to the total number of data-bound widgets (n) where the
constant in the linear equation is the average DOM separation across
all data-bound widgets (k). I guess you are assuming n tends to k on a
given page? (not usually the case). Also, if total number of dijits on
page is N, n < N is common, if not outrightly n << N.

I don't really understand the code that
executes for the TextBox figures out that it's connected to
model.foo.bar.baz.freddy.frog. (What info is cached inside of the
innermost Group?)
<snip/>

There is no caching per se, direct references to nodes within the
StatefulModel are stored as "binding" property on appropriate dijits.
Here is how things work in above scenario:
1. Outermost group finds no data-bound parent, evals "model.foo" to
obtain its ref StatefulModel node
2. The next three groups locate their data-bound parent immediately
i.e. on first parent lookup (as its also the DOM parent), and each
resolves their ref expression as relative to parent. So, in the
absolute sense, 2nd group refs model.foo.bar, 3rd refs
model.foo.bar.baz and so on.
3. The textbox similarly (relatively) obtains its "binding" as a ref
to the model.foo.bar.baz.freddy.frog node (parent:
model.foo.bar.baz.freddy, relative ref: frog). At which point, the
data (i.e. "value") and meta-data associations are set up between that
model node and the textbox, thereby the textbox displays the value
from the model i.e. "prince".

Anyway, the parser has an "inherited" parameter that could be used to pass
down the ref from the parent. I'm not sure if using it makes sense or not.
<snap/>

See above.

4. NumberTextBox, ValidationTextBox

These methods are now assuming a super-class isValid() method, but
that
method only exists when _DataBindingMixin is included. I guess we
need
to
define an empty isValid() method in _WidgetBase? I don't know what
happens
when you call this.inherited(arguments) and there's no such
super-class
function, but even if it works, it seems fragile.
<snap/>

Nothing happens, see line 190 (linking to a few lines before that for
context):
http://bugs.dojotoolkit.org/browser/dojo/trunk/_base/declare.js?rev#778#L186
That aside, yes, this was slightly tricky because there was no
corresponding isValid() in _WidgetBase whereas I think there should
be. Also, not all dijits check base class validity (where applicable)
before deciding their isValid() status and once its added to
_WidgetBase, they should (and thereby, the model validity will be
accounted for in cases where the data binding mixin is applied).
OK, adding it to _WidgetBase is something to consider. But again, there
would be the "problem" where your mixin is simply overwriting the
isValid()method in _WidgetBase.js, like it's overwriting postCreate() now.
The isValid() problem is harder to solve since dojo.connect() doesn't work
since you need to return a value, I guess you should be doing something
like:
var oldIsValid = dijit._WidgetBase.isValid;
dijit._WidgetBase.isValid = function(){ return this.oldIsValid() &&
your-code-here; }
<snip/>

OK, that would cover all bases. OTOH, isValid() would simply return
true in _WidgetBase, can't imagine much else going on there.

5. dijit.mvc._Container

This has >100 lines of cut-pasted code from _Templated and doesn't
support
the new data-dojo-attach-point etc. syntax. Can you do better? See
dijit.Declaration, maybe you can have similar code.
<snip/>

Yes, its listed as a TODO in code -- it'd be good to remove that
duplication. The issue as I remember was that I wasn't able to reuse
_Templated directly as the way it deals with templates and template
caches is different from, say repeat, where the template is inline
(body). I'll take another look at dijit.Declaration, but ISTR some
other differences there.

This inheritance from _Container to both Group and Repeater confuses me.
While Group is just a plain wrapper widget, similar to dijit.form.Form or
dijit.layout.ContentPane, Repeater is a different beast that generates from
a template.
<snap/>

It sure would be confusing if that were the case :-) Group does not
inherit from _Container, it inherits from _WidgetBase. Its the
simplest data-bound widget that is very useful in setting up
hierarchical data bindings (ref'ing to intermediate model nodes).

I guess my question is, why does mvc._Container have any code
<snip/>

In hindsight, somewhat unnecessary. I've refactored that out of
_Container (please see next patch in a day or two).

b) the declaredClass references here and in other parts of the code
aren't
future-proof. declaredClass will likely go away in 2.0.
<snap/>

OK, any future-proof equivalent? I'll investigate or use a bit more of
the duck typing sauce if needed.
Yes, if there isn't an obvious way to ducktype (ex: testing if a certain
method like then() is available), then in dijit for example we have
isContainer and isLayoutContainer flags on widgets that indicate they have a
certain functionality.
<snap/>

Thanks, there is, toPlainObject() is used as the duck typing signature.

-Rahul
--000e0cd5c8720ff651049dc6defa
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<font size="2">OK, so part of what I was asking was whether parent.get(&quot;ref&quot;) just returned parent.ref, or if it computed the return value by tracing up the tree.   From your response it&#39;s clear that it just returns parent.ref.  So</font> in the worst case, every node with a &quot;ref&quot; setting will trace up to &lt;body&gt; looking for a parent ref.   That still sounds CPU intensive but maybe not the end of the world.
<div><font size="2"><br></font></div><div><font size="2">Note: you probably should be calling dojo.getObject() rather than dojo.eval(), will you ever pass eval() more than a dot separated identifier?</font></div><div><font size="2"><br>

</font></div><div><font size="2">--------</font></div><div><font size="2"><div>I&#39;m still confused by ref vs. binding.    In one of your test files you have:</div><div><br></div><div><p style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px">

dijit.byId(&quot;view&quot;).set(&quot;binding&quot;, binding);</p><p style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px"><br></p><p style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px">

Yet, there&#39;s no &quot;binding&quot; attribute declared in _DataBindingMixin.js.</p><p style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px"><br></p><p style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px">
In one of your test files you have:</p><p style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px"><br></p><p style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px"><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="Content-Style-Type" content="text/css">
<title></title>
<meta name="Generator" content="Cocoa HTML Writer">
<meta name="CocoaVersion" content="1038.35">
<style type="text/css">
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 11.0px Monaco; color: #1738f5}
span.s1 {color: #b52422}
span.s2 {color: #000000}
span.s3 {color: #ff201a}
</style>

</p><p class="p1">&lt;<span class="s1">input</span><span class="s2"> </span><span class="s3">id</span><span class="s2">=&quot;</span>taxes<span class="s2">&quot; </span><span class="s3">dojoType</span><span class="s2">=&quot;</span>dijit.form.NumberTextBox<span class="s2">&quot; </span><span class="s3">ref</span><span class="s2">=&quot;</span>loanModel.Taxes<span class="s2">&quot;</span>/&gt;</p>
<p class="p1"><br></p><p class="p1"><font class="Apple-style-span" color="#000000" face="arial, helvetica, sans-serif" size="2">In that example ref is both the StatefulModel object and the attribute inside of it.   (loanModel.Taxes is a number, right?)</font></p>
<p></p><p style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px">
<br></p><p style="margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px">------</p></div></font></div><div><font size="2">Have you thought that users might try to specify ref (or is it binding?) as an object rather than as a string?   Something like:</font></div>
<div><font size="2"><br></font></div><div><font size="2">      new dijit.form.TextBox({ref: myStatefulModel.employeeName})</font></div>
<div><font size="2"><br></font></div><div><meta charset="utf-8"><div><font size="2">That&#39;s not quite right because it will end up as though I had done this:</font></div><div><font size="2"><br></font></div><div><font size="2"><div>
<font size="2">      new dijit.form.TextBox({ref: &quot;John Smith&quot;})</font></div><div><font size="2"><br></font></div></font></div><div>but anyway it seems like the app should be able to specify the Stateful object being bound as an object rather than as a string name of a global variable.</div>
</div><div><br></div><div><br></div><div><font size="2">Note that we have this pattern in other widget parameters, for example DateTextBox.value is a Date object, but when you construct a DateTextBox or call set(&quot;value&quot;, ...) you can pass in a string for the value and it gets converted.   In your case it seems like ref (or is it binding?) should be an Object, but you allow a string as a parameter to the constructor or argument to set(&quot;ref&quot;, ...) .</font></div>

<div><br></div><div>----------</div><div><br></div><div><font size="2">Here&#39;s a test case for you to add, it seems like this should work, but it won&#39;t work w/your current code:</font></div><div><font size="2"><br>
</font></div><div><font size="2">    myWidget = new myWidget({ref: &quot;foo.bar&quot;})    &lt;--- can&#39;t eval ref yet since no parent</font></div>
<div><font size="2">    myWidget.placeAt(dojo.body());</font></div><div><font size="2">    myWidget.startup()  &lt;--- should set widget&#39;s value according to model</font></div><div><font size="2">    myWiget.set(&quot;ref&quot;, &quot;baz.bam&quot;) &lt;-- should reset widget&#39;s value according to new model</font></div>

<div><font size="2"><br></font><br></div><div><br></div><div><div class="gmail_quote">On Sun, Mar 6, 2011 at 5:17 AM, Rahul Akolkar <span dir="ltr">&lt;<a href="mailto:rahul.akolkar at gmail.com" target="_blank">rahul.akolkar at gmail.com</a>&gt;</span> wrote:<br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi Bill,<br>
<br>
Inline.<br>
<div><br>
On Fri, Mar 4, 2011 at 10:33 PM, Bill Keese &lt;<a href="mailto:bill at dojotoolkit.org" target="_blank">bill at dojotoolkit.org</a>&gt; wrote:<br>
&gt; Glad you are getting good feedback from Ben.<br>
</div>&lt;snip/&gt;<br>
<br>
Yup, good to have more pairs of eagle eyes on this. I am in the middle<br>
of some minor refactorings based on all the comments so far. I expect<br>
to have a refreshed patch by the end of the weekend.<br>
<div><br>
<br>
&gt; Here&#39;s a reply to some of the stuff from my original note.<br>
&gt;<br>
</div>&lt;snap/&gt;<br>
<br>
Thanks, I was hoping it&#39;d come in before my refreshed patch became ready :-)<br>
<div><br>
<br>
&gt;&gt;<br>
&gt;&gt; &gt; 2. DataBindingMixin<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; a) file structure<br>
&gt;&gt; &gt; The root of the patch is _DataBindingMixin.js, which gets mixed into<br>
&gt;&gt; &gt; _WidgetBase.   Current code for that is split across two files as:<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; dojo.declare(&quot;dijit._DataBindingMixin&quot;, null, { ... });<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; dojo.extend(dijit._WidgetBase, new dijit._DataBindingMixin());<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; It would be simpler like this:<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; dojo.extend(dijit._WidgetBase, {...});<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; You can still pull _DataBindingMixin.js into StatefulModel.js if you<br>
&gt;&gt; &gt; don&#39;t<br>
&gt;&gt; &gt; want apps to need to explicitly dojo.require(DataBindingMixin).<br>
&gt;&gt; &gt;<br>
&gt;&gt; &lt;snap/&gt;<br>
&gt;&gt;<br>
&gt;&gt; Correct, thats indeed the objective. The data binding mixin is not<br>
&gt;&gt; something we&#39;d want apps to explicitly dojo.require(). By &quot;pull into&quot;,<br>
&gt;&gt; I&#39;m thinking you mean inline the source into the other file? Thats an<br>
&gt;&gt; option.<br>
&gt;<br>
&gt;<br>
&gt; Sorry, I meant that you could list _DataBindingMixin in the list of requires<br>
&gt; for StatefulModel, in the first line define() call.<br>
</div>&lt;snip/&gt;<br>
<br>
Oh, got it.<br>
<div><br>
<br>
&gt; But I agree with Ben&#39;s comment, it seems wrong to make a dijit dependency on<br>
&gt; StatefulModel just so apps can avoid an extra dojo.require() call<br>
&gt; Would StatefulModel ever be useful outside of widgets?    A recursive<br>
&gt; dojo.Stateful sounds useful in general, not sure about the other stuff in<br>
&gt; there.<br>
&gt;<br>
</div>&lt;snap/&gt;<br>
<br>
Right, the dijit.StatefulModel class is already geared to deal with<br>
specifics of a view layer (all the valid, readOnly, relevant etc.<br>
meta-data lends well to view layer bindings). In theory, one could<br>
capture the essence of the recursive model for reuse elsewhere. But<br>
while it may be possible to craft a base class that is purely a<br>
recursive dojo.Stateful model and then subclass it to provide what is<br>
effectively dijit.StatefulModel functionality now, I can&#39;t say I have<br>
many usecases at hand. Ofcourse, such refactoring can also happen down<br>
<div><br>
<br>
&gt;&gt; &gt; e) _initControl()<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; This is run from postCreate(), yet it assumes that the widget is<br>
&gt;&gt; &gt; anchored to<br>
&gt;&gt; &gt; the document.   You shouldn&#39;t assume that until startup() is called; in<br>
&gt;&gt; &gt; particular it&#39;s not true for programatically created widgets ex:  new<br>
&gt;&gt; &gt; dijit.form.TextBox().placeAt(...)<br>
&gt;&gt; &gt;<br>
&gt;&gt; &lt;snip/&gt;<br>
&gt;&gt;<br>
&gt;&gt; OK, I&#39;ll look into (d) and (e) above.<br>
&gt;&gt;<br>
&gt;<br>
&gt; About having every widget trace up the tree to find a parent with a binding<br>
&gt; specified, or if there&#39;s no such parent then tracing all the way to<br>
&gt; &lt;body&gt;...    we faced that same problem with the bidi group and their<br>
&gt; lobbying for every widget to support a dir parameter (possibly) being<br>
&gt; inherited from an ancestor .  We didn&#39;t want to have every single widget<br>
&gt; calling getParent() repeatedly to inspect it&#39;s ancestors as that seemed like<br>
&gt; the parser to pass down the dir inherited from the ancestor.   I wonder if<br>
&gt; that makes sense here.<br>
</div>&lt;snip/&gt;<br>
<br>
It may make sense, but let me step back a bit. Some thoughts, in no<br>
particular order:<br>
<br>
I assume by getParent() you mean dijit.getEnclosingWidget() which is<br>
what is used here. The number of these calls is a function of: (a)<br>
Number of data-bound widgets, (b) Topology of binds i.e. amount of<br>
relative refs implied by nesting and (c) Average DOM separation (along<br>
parent axis) between nested data-bound dijits.<br>
<br>
The observed rule of thumb is that at page load you&#39;d expect roughly<br>
2x the number of dijit.getEnclosingWidget() calls as the number of<br>
data-bound widgets. This is somewhat less pervasive than bidi as it<br>
only applies to data-bound dijits (clearly, a view may have data-bound<br>
dijits and others that aren&#39;t data-bound).<br>
<br>
There are two scenarios where bindings are calculated (or recalculated):<br>
* Programmatic binding update (example: when user chooses to list<br>
details for a particular search result in the master-detail demos in<br>
the patch, causing the bindings in the detail portion of the view to<br>
be updated)<br>
<br>
_setupBinding(), which effectively removes the need for any DOM<br>
operations or parent widget lookups in the second case.<br>
<br>
For the initial page load, the roughly 2x dijit.getEnclosingWidget()<br>
calls may be avoided if we can get the parent binding to be<br>
&quot;inherited&quot; through the parser. OTOH, these calls aren&#39;t terribly<br>
expensive either (operations therein include .parentNode references,<br>
getting the widgetId attribute values and a lookups into the widget<br>
registry), so some of this could be done as incremental improvements.<br>
<div><br>
<br>
&gt; In your response to Ben you gave this example:<br>
&gt; model:<br>
&gt;  { foo : { bar : { baz : { freddy : { frog : &quot;prince&quot; } } } } }<br>
&gt;<br>
&gt;<br>
&gt; markup:<br>
&gt;  &lt;div dojoType=&quot;dijit.mvc.Group&quot; ref=&quot;model.foo&quot;&gt;<br>
&gt;  &lt;div dojoType=&quot;dijit.mvc.Group&quot; ref=&quot;bar&quot;&gt;<br>
&gt;   &lt;div dojoType=&quot;dijit.mvc.Group&quot; ref=&quot;baz&quot;&gt;<br>
&gt;    &lt;div dojoType=&quot;dijit.mvc.Group&quot; ref=&quot;freddy&quot;&gt;<br>
&gt;     &lt;div dojoType=&quot;dijit.form.TextBox&quot; ref=&quot;frog&quot;&gt;<br>
&gt;<br>
&gt;<br>
&gt; Hopefully that doesn&#39;t execute in O(n^2), where every widget needs to trace<br>
&gt; to the top of the tree, does it?<br>
</div>&lt;snap/&gt;<br>
<br>
In the above example:<br>
* There are exactly 5 getEnclosingWidget() calls<br>
* The total number of node.parentNode references looked up (including<br>
those within these 5 calls) is exactly equal to the DOM depth of the<br>
textbox on the page<br>
<br>
Let me try to understand why you say O(n^2), since every widget isn&#39;t<br>
trying to reach every other widget on the page. Worst case performance<br>
is linear to the total number of data-bound widgets (n) where the<br>
constant in the linear equation is the average DOM separation across<br>
all data-bound widgets (k). I guess you are assuming n tends to k on a<br>
given page? (not usually the case). Also, if total number of dijits on<br>
page is N, n &lt; N is common, if not outrightly n &lt;&lt; N.<br>
<div><br>
<br>
&gt; I don&#39;t really understand the code that<br>
&gt; executes for the TextBox figures out that it&#39;s connected to<br>
&gt; model.foo.bar.baz.freddy.frog.   (What info is cached inside of the<br>
&gt; innermost Group?)<br>
</div>&lt;snip/&gt;<br>
<br>
There is no caching per se, direct references to nodes within the<br>
StatefulModel are stored as &quot;binding&quot; property on appropriate dijits.<br>
Here is how things work in above scenario:<br>
1. Outermost group finds no data-bound parent, evals &quot;model.foo&quot; to<br>
obtain its ref StatefulModel node<br>
2. The next three groups locate their data-bound parent immediately<br>
i.e. on first parent lookup (as its also the DOM parent), and each<br>
resolves their ref expression as relative to parent. So, in the<br>
absolute sense, 2nd group refs model.foo.bar, 3rd refs<br>
model.foo.bar.baz and so on.<br>
3. The textbox similarly (relatively) obtains its &quot;binding&quot; as a ref<br>
to the model.foo.bar.baz.freddy.frog node (parent:<br>
model.foo.bar.baz.freddy, relative ref: frog). At which point, the<br>
data (i.e. &quot;value&quot;) and meta-data associations are set up between that<br>
model node and the textbox, thereby the textbox displays the value<br>
from the model i.e. &quot;prince&quot;.<br>
<div><br>
<br>
&gt; Anyway, the parser has an &quot;inherited&quot; parameter that could be used to pass<br>
&gt; down the ref from the parent.  I&#39;m not sure if using it makes sense or not.<br>
&gt;<br>
</div>&lt;snap/&gt;<br>
<br>
See above.<br>
<div><div></div><div><br>
<br>
&gt;&gt;<br>
&gt;&gt; &gt; 4. NumberTextBox, ValidationTextBox<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; These methods are now assuming a super-class isValid() method, but that<br>
&gt;&gt; &gt; method only exists when _DataBindingMixin is included.   I guess we need<br>
&gt;&gt; &gt; to<br>
&gt;&gt; &gt; define an empty isValid() method in _WidgetBase?   I don&#39;t know what<br>
&gt;&gt; &gt; happens<br>
&gt;&gt; &gt; when you call this.inherited(arguments) and there&#39;s no such super-class<br>
&gt;&gt; &gt; function, but even if it works, it seems fragile.<br>
&gt;&gt; &lt;snap/&gt;<br>
&gt;&gt;<br>
&gt;&gt; Nothing happens, see line 190 (linking to a few lines before that for<br>
&gt;&gt; context):<br>
&gt;&gt; <a href="http://bugs.dojotoolkit.org/browser/dojo/trunk/_base/declare.js?rev=23778#L186" target="_blank">http://bugs.dojotoolkit.org/browser/dojo/trunk/_base/declare.js?rev=23778#L186</a><br>
&gt;&gt;<br>
&gt;&gt; That aside, yes, this was slightly tricky because there was no<br>
&gt;&gt; corresponding isValid() in _WidgetBase whereas I think there should<br>
&gt;&gt; be. Also, not all dijits check base class validity (where applicable)<br>
&gt;&gt; before deciding their isValid() status and once its added to<br>
&gt;&gt; _WidgetBase, they should (and thereby, the model validity will be<br>
&gt;&gt; accounted for in cases where the data binding mixin is applied).<br>
&gt;&gt;<br>
&gt;<br>
&gt; OK, adding it to _WidgetBase is something to consider.    But again, there<br>
&gt; would be the &quot;problem&quot; where your mixin is simply overwriting the<br>
&gt; isValid()method in _WidgetBase.js, like it&#39;s overwriting postCreate() now.<br>
&gt;  The isValid() problem is harder to solve since dojo.connect() doesn&#39;t work<br>
&gt; since you need to return a value, I guess you should be doing something<br>
&gt; like:<br>
&gt; var oldIsValid = dijit._WidgetBase.isValid;<br>
&gt; dijit._WidgetBase.isValid = function(){ return this.oldIsValid() &amp;&amp;<br>
&gt; your-code-here; }<br>
&gt;<br>
</div></div>&lt;snip/&gt;<br>
<br>
OK, that would cover all bases. OTOH, isValid() would simply return<br>
true in _WidgetBase, can&#39;t imagine much else going on there.<br>
<div><br>
<br>
&gt;&gt;<br>
&gt;&gt; &gt; 5. dijit.mvc._Container<br>
&gt;&gt; &gt;<br>
&gt;&gt; &gt; This has &gt;100 lines of cut-pasted code from _Templated and doesn&#39;t<br>
&gt;&gt; &gt; support<br>
&gt;&gt; &gt; the new data-dojo-attach-point etc. syntax.   Can you do better?   See<br>
&gt;&gt; &gt; dijit.Declaration, maybe you can have similar code.<br>
&gt;&gt; &lt;snip/&gt;<br>
&gt;&gt;<br>
&gt;&gt; Yes, its listed as a TODO in code -- it&#39;d be good to remove that<br>
&gt;&gt; duplication. The issue as I remember was that I wasn&#39;t able to reuse<br>
&gt;&gt; _Templated directly as the way it deals with templates and template<br>
&gt;&gt; caches is different from, say repeat, where the template is inline<br>
&gt;&gt; (body). I&#39;ll take another look at dijit.Declaration, but ISTR some<br>
&gt;&gt; other differences there.<br>
&gt;<br>
&gt;<br>
&gt; This inheritance from _Container to both Group and Repeater confuses me.<br>
&gt;  While Group is just a plain wrapper widget, similar to dijit.form.Form or<br>
&gt; dijit.layout.ContentPane, Repeater is a different beast that generates from<br>
&gt; a template.<br>
</div>&lt;snap/&gt;<br>
<br>
It sure would be confusing if that were the case :-) Group does not<br>
inherit from _Container, it inherits from _WidgetBase. Its the<br>
simplest data-bound widget that is very useful in setting up<br>
hierarchical data bindings (ref&#39;ing to intermediate model nodes).<br>
<div><br>
<br>
&gt;   I guess my question is, why does mvc._Container have any code<br>
&gt;<br>
</div>&lt;snip/&gt;<br>
<br>
In hindsight, somewhat unnecessary. I&#39;ve refactored that out of<br>
_Container (please see next patch in a day or two).<br>
<div><br>
<br>
&gt;&gt;<br>
&gt;&gt; &gt; b) the declaredClass references here and in other parts of the code<br>
&gt;&gt; &gt; aren&#39;t<br>
&gt;&gt; &gt; future-proof.   declaredClass will likely go away in 2.0.<br>
&gt;&gt; &lt;snap/&gt;<br>
&gt;&gt;<br>
&gt;&gt; OK, any future-proof equivalent? I&#39;ll investigate or use a bit more of<br>
&gt;&gt; the duck typing sauce if needed.<br>
&gt;<br>
&gt; Yes, if there isn&#39;t an obvious way to ducktype (ex: testing if a certain<br>
&gt; method like then() is available), then in dijit for example we have<br>
&gt; isContainer and isLayoutContainer flags on widgets that indicate they have a<br>
&gt; certain functionality.<br>
&gt;<br>
</div>&lt;snap/&gt;<br>
<br>
Thanks, there is, toPlainObject() is used as the duck typing signature.<br>
<font color="#888888"><br>
-Rahul<br>
</font></blockquote></div><br></div>

--000e0cd5c8720ff651049dc6defa--

From bogus@does.not.exist.com Tue Jan 18 18:42:17 2011
From: bogus@does.not.exist.com ()
Date: Tue, 18 Jan 2011 23:42:17 -0000
Subject: No subject
Message-ID: <mailman.10.1299861896.13280.dojo-contributors@mail.dojotoolkit.org>

say an IBM product includes some sort of distribution, it is a lot
easier to prove IP et al if the actual source of something is clear.
In other words, if the main distribution was assembled from a repo
owned and maintained by the Dojo Foundation, it is a lot easier for
IBM's lawyers to approve the distribution--as opposed to having to
trace the code history through a bunch of individual GitHub accounts.
It also ensures that things like CLAs and such have actually been
checked against *before* getting a distribution.

Does that make sense? It's kind of wordy and the coffee hasn't
entirely kicked in yet =)

-- Tom

From bogus@does.not.exist.com Tue Jan 18 18:42:17 2011
From: bogus@does.not.exist.com ()
Date: Tue, 18 Jan 2011 23:42:17 -0000
Subject: No subject
Message-ID: <mailman.17.1301565859.13280.dojo-contributors@mail.dojotoolkit.org>

one of these). Ideally we could have also tablets vs phones detection for
each of these platforms. Even if that is not much leveraged now compare to
the other flags I suspect more and more people might need to adapt to mobile
vs tablets.

What other thinks? Should we all continue to have our own detection or
should we put that in a central place and where?

Thanks,
--
Christophe

Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

Hi everyone,<br><br>Sorry if that has already been raised but I&#39;m starting to see more and more code that is detecting mobile devices vs desktop devices.<br><br>There is some in touch event patch:<br><br><span style="white-space: pre-wrap;"><a href="http://bugs.dojotoolkit.org/attachment/ticket/12176/touch0.2.patch" target="_blank">http://bugs.dojotoolkit.org/attachment/ticket/12176/touch0.2.patch</a><br>
<br>That is detecting iOS/Android/Mobile<br><br>There is some in dojox.mobile:<br><br><a href="http://svn.dojotoolkit.org/src/dojox/trunk/mobile/app/_event.js">http://svn.dojotoolkit.org/src/dojox/trunk/mobile/app/_event.js</a><br>
<br>That is detecting iPhone/Android/WebOS<br><br>And finally there is some in demos (and probably users code) that is doing something similar.<br><br>Shouldn&#39;t we consolidate that so that not everyone has to write his own detection and also that everyone get consistent results (for example dojox.mobile isIPhone does not take iPad into account while touch events patch is)?<br>
<br clear="all"></span>From what I see we need at least iOS/Android &amp; WebOS detection (mobile being one of these). Ideally we could have also tablets vs phones detection for each of these platforms. Even if that is not much leveraged now compare to the other flags I suspect more and more people might need to adapt to mobile vs tablets.<br>
<br>What other thinks? Should we all continue to have our own detection or should we put that in a central place and where?<br><br>Thanks,<br>-- <br>Christophe<br>

From bogus@does.not.exist.com Tue Jan 18 18:42:17 2011
From: bogus@does.not.exist.com ()
Date: Tue, 18 Jan 2011 23:42:17 -0000
Subject: No subject
Message-ID: <mailman.18.1301586576.13280.dojo-contributors@mail.dojotoolkit.org>

Dojo codebase could be handled by this simple query engine. The more
exotic queries are rarely if ever used internally, and most apps could
probably be built with the simple engine.

* dojo/query is a new module, and effectively using this instead of base
(and thus dojo/_base/query) is the opt-in to simpler, more native-based
querying.

* Backwards compatible, base will load "dojo/query!slick" or
"dojo/query!dojo/acme" or something. We can also allow for configuration
to opt-in to conditionally load the full selector engine (use native

* dojo/query provides the NodeList wrapping of the arrays returned from
the selector engine. This makes it easier to plug in selector engines
without the selector engine actually having to do the NodeList wrapping.
A selector engine only needs to return arrays. Therefore we can use
Sizzle or Slick with little or no modification (rather than having to
keep a fork in the dojo codebase).

* First class support for CSS matching testing. The default
implementation uses the vendorMatchesSelector() if available, otherwise
the internal matching code, which means we can do efficient event
delegation (from what I can tell, the current implementation in dojox is
painfully inefficient since it relies on full queries to check for CSS
matching).

* Uses has() branching. The full module is about 3.3 KB (compressed, not
gzipped). With a modern browser build (with qSA) it is less than 2KB
(just the plugin code, NodeList wrapping and root correction with fast
paths when qSA is not the fastest approach).

* At the intersection of the new event handling and this proposed query
selection mechanism, I added event delegation support to
NodeList.prototype.on in my branch to consider, so you can do:
query("#list").on("li:click") to listen for clicks on <li> children of
the #list.
This leverages the efficient match method provided by the selector
engine (which by default comes from native impl if available).

* The default implementation should be very fast for simple common
queries since it fast-paths to native specific methods when possible.

Let me know if you think this is worth pursuing.
Thanks,
Kris
On 3/25/2011 7:56 PM, Stephen Chung wrote:
My suggestions in order to help out programmers out here:

Option #1: Split dojo.query into two parts, say dojo.query and
dojo.simpleQuery. dojo.simpleQuery to handle only subset of selectors
that all popular QSA implementations can handle (i.e. the LCD set).
dojo.query continue to handle all, including advanced, queries.
dojo.simpleQuery delegates to QSA where possible. dojo.query is
always JS implementation.

Option #2: Always delegate dojo.query to QSA where available, which
means that the same dojo.query call may fail in some browsers ??? the
programmer just has to test. Make dojo.queryAdvanced ==> always JS ???
anybody who wants it ???just to work??? everywhere without extensive

You can see that the goal of my suggestion is to make sure that the
dev and built versions behave the same in all browsers. That???s
because if builds work differently from dev version, it is usually a
royal pain to debug...

- Stephen

*From:* Kris Zyp <mailto:kzyp at dojotoolkit.org>
*Sent:* Saturday, 26 March, 2011 12:36 AM
*To:* dojo dev. <mailto:dojo-contributors at mail.dojotoolkit.org>
*Cc:* Stephen Chung <mailto:Stephen.Chung at intexact.com>
*Subject:* Re: [dojo-contributors] Query Selector Engines
On 3/25/2011 10:18 AM, Stephen Chung wrote:
My $0.02's worth of experience: Originally wrote dojo.query("> input, > select, > textarea", node) to iterate through all the input elements under a frame node. No prob here. Then build with webkitMobile set. Suddenly didn't work on the iPad (non-built version worked ok). Strangely, the same code continued to work in desktop WebKit browser. This illustrates a fundamental problem with build-pragmas and why we are switching to has(). Dev runtime and build-time should behave the same. When you have different branches for builds then dev runtime you inevitably run into problems. We shouldn't need warning messages, we need consistent execution paths. The webkitMobile branch in dojo.query is buggy because it doesn't get exercised. Took most of one day with "console.log" statements (seems to only way to debug strange errors on the iPad) to figure out why: with webkitMobile set, dojo.query redirects to QSA. However, when the second argument is set, it tagged "#"+node in front of the query text, making it "#frame > input, > select, > textarea" which skipped all the select/textarea tags. I eventually had to remove the call to dojo.query and manually looped through the children. So, currently dojo.query and QSA are not 100% compatible anyway (considering the flaky interpretation of the ">" children queries and the "," group queries in QSA), so I am pretty sure many people out there are going through the same thing, finding out the first time they tested their new build to know that it failed to work on some browsers with QSA. Just FYI, if you run our unit tests on the native QSA there are number of other tests that fail. I believe there are some complicated :not tests that no browsers handle like we do at the moment, and then IE8 fails on a lot of the pseudo selectors (assuming some of that is fixed in IE9). Not that these queries are really used that much. Looking at the Dojo code base, almost all dojo.query() calls are easily handled by any native QSA (at least if we fixed the > and , combination bug, which I noticed when I looked at that code as well). I saw one test that used a :nth-child that IE wouldn't have been able to handle, and dojox.mobile uses similar pseudos (but obviously it isn't targeted at IE). I think Dojo base clearly needs to default to our full CSS capabilities. Having an opt-in for less guarantees (FF and WebKit's QSA at least still reliably provide more selectors than any mere mortal should ever need) so native QSA can be used more frequently would be beneficial. Thanks, Kris ------------------------------------------------------------------------ No virus found in this incoming message. Checked by AVG - www.avg.com Version: 9.0.894 / Virus Database: 271.1.1/3529 - Release Date: 03/26/11 00:54:00 --------------080800090002030206030804 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: 8bit <html> <head> <meta content="text/html; charset=UTF-8" http-equiv="Content-Type"> </head> <body bgcolor="#FFFFFF" text="#000000"> Based on these suggestions (for different levels of querying), and the move to better modularization and feature detect branching, I put together an attempt at a new query entry module:<br> <a href="https://github.com/kriszyp/dojo/blob/has-modularize/query.js">https://github.com/kriszyp/dojo/blob/has-modularize/query.js</a><br> Key parts of this approach:<br> * This module provides a default very simple lightweight selector implementation and leans heavily on native querySelectorAll when available. You can then choose to load a full selector engine if you want with injection via AMD plugin syntax or the setEngine method:<br> For example, to use the Sizzle engine, we could do:<br> define("dojo/query!sizzle", function(query){<br> ...<br> or to only use Sizzle if a good native qSA is not available:<br> define("dojo/query!sizzle?", function(query){<br> or to use jQuery:<br> query.setEngine($)<br>
When you only need basic queries, you can do:<br>
define("dojo/query", function(query){<br>
query("#id div");<br>
When you require something like "dojo/query!slick?" it allows you to
only load a full engine if there isn't a native qSA, so mobile
builds can still be very light.<br>
define("dojo/query!slick?", function(query){<br>
query("#id div:nth-child(odd)");<br>
From my survey of Dojo, it looks like virtually every query used in
the Dojo codebase could be handled by this simple query engine. The
more exotic queries are rarely if ever used internally, and most
apps could probably be built with the simple engine.<br>
<br>
* dojo/query is a new module, and effectively using this instead of
base (and thus dojo/_base/query) is the opt-in to simpler, more
native-based querying.<br>
<br>
* Backwards compatible, base will load "dojo/query!slick" or
"dojo/query!dojo/acme" or something. We can also allow for
configuration to opt-in to conditionally load the full selector
it.<br>
<br>
* dojo/query provides the NodeList wrapping of the arrays returned
from the selector engine. This makes it easier to plug in selector
engines without the selector engine actually having to do the
NodeList wrapping. A selector engine only needs to return arrays.
Therefore we can use Sizzle or Slick with little or no modification
(rather than having to keep a fork in the dojo codebase).<br>
<br>
* First class support for CSS matching testing. The default
implementation uses the vendorMatchesSelector() if available,
otherwise the internal matching code, which means we can do
efficient event delegation (from what I can tell, the current
implementation in dojox is painfully inefficient since it relies on
full queries to check for CSS matching).<br>
<br>
* Uses has() branching. The full module is about 3.3 KB (compressed,
not gzipped). With a modern browser build (with qSA) it is less than
2KB (just the plugin code, NodeList wrapping and root correction
with fast paths when qSA is not the fastest approach).<br>
<br>
* At the intersection of the new event handling and this proposed
query selection mechanism, I added event delegation support to
NodeList.prototype.on in my branch to consider, so you can do:<br>
query("#list").on("li:click") to listen for clicks on &lt;li&gt;
children of the #list.<br>
This leverages the efficient match method provided by the selector
engine (which by default comes from native impl if available).<br>
<br>
* The default implementation should be very fast for simple common
queries since it fast-paths to native specific methods when
possible.<br>
<br>
Let me know if you think this is worth pursuing.<br>
Thanks,<br>
Kris<br>
<br>
On 3/25/2011 7:56 PM, Stephen Chung wrote:
<blockquote cite="mid:74D363A654CE41B8815C0338D2F91BE5 at StephenChung"
type="cite">
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
<div dir="ltr">
<div style="FONT-FAMILY: 'Droid Sans'; COLOR: #080000;
FONT-SIZE: 14pt">
<div><font size="4">My suggestions in order to help out
programmers out here:</font></div>
<div>??</div>
<div><font size="4">Option #1: Split dojo.query into two
parts, say dojo.query and dojo.simpleQuery.??
dojo.simpleQuery to handle only subset of selectors that
all popular QSA implementations can handle (i.e. the LCD
set).?? dojo.query continue to handle all, including
advanced, queries.?? dojo.simpleQuery delegates to QSA
where possible.?? dojo.query is always JS implementation.</font></div>
<div>??</div>
<div><font size="4">Option #2: Always delegate dojo.query to
QSA where available, which means that the same dojo.query
call may fail in some browsers ??? the programmer just has
to test.?? Make dojo.queryAdvanced ==&gt; always JS ???
anybody who wants it ???just to work??? everywhere without
extensive testing can use this instead.</font></div>
<div>??</div>
<div><font size="4">You can see that the goal of my suggestion
is to make sure that the dev and built versions behave the
same in all browsers.?? That???s because if builds work
differently from dev version, it is usually a royal pain
to debug...</font></div>
<div>??</div>
<div><font size="4">- Stephen</font></div>
<div>??</div>
<div style="FONT-STYLE: normal; DISPLAY: inline; FONT-FAMILY:
'Calibri'; COLOR: #000000; FONT-SIZE: small; FONT-WEIGHT:
normal; TEXT-DECORATION: none">
<div style="FONT: 10pt tahoma">
<div>??</div>
<div style="BACKGROUND: #f5f5f5">
<div style="font-color: black"><b>From:</b> <a
moz-do-not-send="true" title="kzyp at dojotoolkit.org"
href="mailto:kzyp at dojotoolkit.org">Kris Zyp</a> </div>
<div><b>Sent:</b> Saturday, 26 March, 2011 12:36 AM</div>
<div><b>To:</b> <a moz-do-not-send="true"
title="dojo-contributors at mail.dojotoolkit.org"
href="mailto:dojo-contributors at mail.dojotoolkit.org">dojo
dev.</a> </div>
<div><b>Cc:</b> <a moz-do-not-send="true"
title="Stephen.Chung at intexact.com"
href="mailto:Stephen.Chung at intexact.com">Stephen
Chung</a> </div>
<div><b>Subject:</b> Re: [dojo-contributors] Query
Selector Engines</div>
</div>
</div>
<div>??</div>
</div>
<div style="FONT-STYLE: normal; DISPLAY: inline; FONT-FAMILY:
'Calibri'; COLOR: #000000; FONT-SIZE: small; FONT-WEIGHT:
normal; TEXT-DECORATION: none">On 3/25/2011 10:18 AM,
Stephen Chung wrote: <br>
<span style="WHITE-SPACE: pre">&gt; My \$0.02's worth of
experience: <br>
&gt; <br>
&gt; Originally wrote dojo.query("&gt; input, &gt; select,
&gt; textarea", node) to <br>
&gt; iterate through all the input elements under a frame
node. No prob here. <br>
&gt; <br>
&gt; Then build with webkitMobile set. Suddenly didn't
&gt; (non-built version worked ok). Strangely, the same
code continued to work <br>
&gt; in desktop WebKit browser. <br>
</span><br>
This illustrates a fundamental problem with build-pragmas
and why we are switching to has(). Dev runtime and
build-time should behave the same. When you have different
branches for builds then dev runtime you inevitably run into
problems. We shouldn't need warning messages, we need
consistent execution paths. The webkitMobile branch in
dojo.query is buggy because it doesn't get exercised.<br>
<span style="WHITE-SPACE: pre"><br>
&gt; Took most of one day with "console.log" statements
(seems to only way to <br>
&gt; debug strange errors on the iPad) to figure out why:
with webkitMobile set, <br>
&gt; dojo.query redirects to QSA. However, when the second
argument is set, it <br>
&gt; tagged "#"+node in front of the query text, making it
"#frame &gt; input, &gt; <br>
&gt; select, &gt; textarea" which skipped all the
select/textarea tags. <br>
&gt; <br>
&gt; I eventually had to remove the call to dojo.query and
manually looped <br>
&gt; through the children. <br>
&gt; <br>
&gt; So, currently dojo.query and QSA are not 100%
compatible anyway (considering <br>
&gt; the flaky interpretation of the "&gt;" children
queries and the "," group <br>
&gt; queries in QSA), so I am pretty sure many people out
there are going through <br>
&gt; the same thing, finding out the first time they
tested their new build to <br>
&gt; know that it failed to work on some browsers with
QSA. <br>
</span><br>
Just FYI, if you run our unit tests on the native QSA there
are number of other tests that fail. I believe there are
some complicated :not tests that no browsers handle like we
do at the moment, and then IE8 fails on a lot of the pseudo
selectors (assuming some of that is fixed in IE9). Not that
these queries are really used that much. Looking at the Dojo
code base, almost all dojo.query() calls are easily handled
by any native QSA (at least if we fixed the &gt; and ,
combination bug, which I noticed when I looked at that code
as well). I saw one test that used a :nth-child that IE
wouldn't have been able to handle, and dojox.mobile uses
similar pseudos (but obviously it isn't targeted at IE).<br>
<br>
I think Dojo base clearly needs to default to our full CSS
capabilities. Having an opt-in for less guarantees (FF and
WebKit's QSA at least still reliably provide more selectors
than any mere mortal should ever need) so native QSA can be
used more frequently would be beneficial.<br>
Thanks,<br>
Kris<br>
<p>
</p>
<hr>
<br>
No virus found in this incoming message.<br>
Checked by AVG - <a class="moz-txt-link-abbreviated" href="http://www.avg.com">www.avg.com</a> <br>
Version: 9.0.894 / Virus Database: 271.1.1/3529 - Release
Date: 03/26/11 00:54:00<br>
</div>
</div>
</div>
</blockquote>
<br>
</body>
</html>

--------------080800090002030206030804--

From bogus@does.not.exist.com Tue Jan 18 18:42:17 2011
From: bogus@does.not.exist.com ()
Date: Tue, 18 Jan 2011 23:42:17 -0000
Subject: No subject
Message-ID: <mailman.19.1301744374.13280.dojo-contributors@mail.dojotoolkit.org>

* Two-way / bi-directional binds between application data models and
widgets (supported via ref)
* One-way binds between model items for client-side "calculates"
(supported via bindProperties)

Here as well, I am not against adding more "modes" to a generic
substrate (the stateless bits I mention above) if others think its
worthwhile.

- Bindings -- should be able to markup multiple bindings to multiple
properties of the widget, hopefully in both directions! That way, for
example, you can bind the value of a ValidationTextBox to one property on
the model, then bind the validation function to another property, and bind
the display formatting mask to yet another property etc.
<snip/>

Sure, this can be done programmatically. Some of the things you
mention above don't usually change on the widget side so binds in both
directions may not be necessary, though there isn't any reason why
they can't be set up in both directions if needed.

Or by markup, did you mean doing this declaratively? That may require
illustrations in this space.

- I suggest that, instead of creating a dijit.mvc.Group container class,
just put the hierarchical binding context mechanism into WidgetBase. Then
any widget can act as a holder of a binding context for all its children.
In other words, binding to data context should be completely orthogonal to
the widgets system. You may still eventually still need a dijit.Group just
for grouping things though (it is generic enough to not need the MVC
annotation).
<snap/>

Agreed, particularly since this is how things work :-) If there is a
data-bound parent already, it sets up the hierarchical data binding
context. If there is no "natural" parent, and grouping some subset of
the view makes sense given application view semantics, a group
container may be used which is a simple shell whose primarily purpose
is to provide common data binding context to its descendents. The
machinery to do all this is provided in the DataBindingMixin.

- Not sure whether this is in dijit.StatefulModel (have to scan through the
patch), but it should also abstract out an array of items, automatically
keeping track of the "current" one. Programs can next/back/jump through the
array, changing the current item, which automatically updates bound widgets
to display new data. Currently, the programmer has to set the "ref"
property in order to change binding to the new array index property -- we
should be able to save this little program step as well, since this occurs
in almost every master-detail type form.
<snip/>

Right, there is value to adding current index tracking for arrays.
Ofcourse, till its available, this can be tracked easily by the
application model.

All-in-all, a summary of my suggestions (so far):

1. Abstract binding mechanism into requiring at least one dojo.Stateful and
one object; ability to bind to any property, with type/format converters
support
2. dojo.StatefulModel and dijit.StatefulModel on top of raw-metal binding,
with added features (e.g. dojo.StatefulModel can connect to dojo.store's,
and dijit.StatefulModel handles widgets)
3. Different binding modes -- one-way in both directions, two-way, once
only, and perhaps others as well
4. Declaratively specify multiple bindings on one widget to different
properties
5. Extend binding contexts with the ability to keep track of the "current
object" if the object acting as binding context is an array, with
programmatic control -- which means that, if specified, this context will
pass the current object to its children as binding context instead of the
array (which requires its children to manually bind to an index)
<snap/>

Good feedback, I've responded to these items above. I see now that you
mean declaratively for item 4 -- this is something on the incremental

Best,
-Rahul

Will give more comments after looking through patch code. Thanks!

- Stephen
From bogus@does.not.exist.com Tue Jan 18 18:42:17 2011
From: bogus@does.not.exist.com ()
Date: Tue, 18 Jan 2011 23:42:17 -0000
Subject: No subject
Message-ID: <mailman.20.1302129533.13280.dojo-contributors@mail.dojotoolkit.org>

the 1.6.1 fixes (particularly IE9 and FF4 support) in by next week's
meeting, so we can release 1.6.1. Thanks!

--20cf3054a4b50b926504a047a88c
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

<font size="2">From the meeting today (in case you weren&#39;t there), the plan is to get all the 1.6.1 fixes (particularly IE9 and FF4 support) in by next week&#39;s meeting, so we can release 1.6.1.    Thanks!</font>

--20cf3054a4b50b926504a047a88c--

From bogus@does.not.exist.com Tue Jan 18 18:42:17 2011
From: bogus@does.not.exist.com ()
Date: Tue, 18 Jan 2011 23:42:17 -0000
Subject: No subject
Message-ID: <mailman.25.1303996751.13280.dojo-contributors@mail.dojotoolkit.org>

that has been connected to used to have a _listeners property. The chart
event handling is checking for this property to avoid superfluous work.
Since this commit the property is not here anymore and no work is done
anymore ;)

Is there something similar with the new event handling that charting code
can use instead to check for listeners presence on a method?

Thanks,
--
Christophe
On Tue, Apr 26, 2011 at 5:34 AM, Kris Zyp wrote:

I just made a substantial checkin (r24471) of the new event handling
system and query delegation modules. By checking this in, I don't mean
to indicate that this is an unreversable change to Dojo, but it seems
clear that we need to get these proposed changes easily available to
test and keeping a branch is difficult to maintain. Bill has provided me
a ton of assistance in testing this out on Dijit (Thank you Bill!), so
hopefully it is in relatively good shape as far as stability (I guess we
will see though). Changes include:

* Addition of dojo/listen, a lighter weight event handling module that
loses some of the cruft that dojo.connect has built up, and provides
some cool new features including event delegation, extension events,
touch event normalization, method/event separation, and event dispatching.
* Addition of dojo/aspect, a very small module to add aspects to
methods. This is included since dojo/listen relies on this module for
listening to non-DOM objects. This suppors before, after, and around
advice based largely on Eugene's suggestions/specifications.
* dojo/_base/connect.js and .../event.js built on dojo/listen now, with
some back-compat shims to keep it's behavior the same.
* dojo.NodeList includes an on() method that delegates to dojo/listen
for nodes in the NodeList (with full event delegation support of course).
* Addition of dojo/mouse.js to provide the mouse.enter and mouse.leave
extension events that correspond to dojo.connect's "mouseenter" and
"mouseleave" emulated events.
* Added some feature detect tests to dojo/has.js for tests that are used
by multiple modules.
* Added JSON validation dojo/json.js for secure/strict validation of
JSON in browsers without native support.
* Addition of dojo/query.js as entry module to performing DOM/selector
queries. This delegates to Acme by default, but can be configured for
alternate engines (tested with Slick, Sizzle, and the new lite engine).
* Cleaner separation of selector engine so we can use Slick and Sizzle
without (or with minimal module wrapping) modification.
* Move Acme (dojo/_base/query.js) to dojo/selector/acme.js for better
clarity
* Addition of dojo/selector/lite.js as a very simple lightweight engine
that can be used as alternative to Acme for applications that don't need
everything Acme has.
* New unit tests to test this new stuff
* Some other minor updates to modules to better leverage improved AMD
support in Dojo.
* loader-catchApi config setting to false by default. It is terribly
difficult to debug without this.

I recognize there are still some wrinkles to be ironed out. I have some
experiments with managing memory for IE leakage. The class DOM-JS object
cycle problem is well understood and solvable, however the way we are
currently solving the problem actually causes memory leaks in IE8 and
newer, and I really would like to avoid causing additional leakage. I
have tried some alternative approaches, but IE8 also some weird iframe
related memory leakage that are very difficult to pin down (it is not
the same as the normal DOM cycle leakage), so I still hope to make some
improvements in this area.

Let me know what issues you find.
Thanks,
Kris
_______________________________________________
dojo-contributors mailing list
dojo-contributors at mail.dojotoolkit.org
http://mail.dojotoolkit.org/mailman/listinfo/dojo-contributors
--0016e6509fb2d9378b04a1fa66af
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

Hi Krys,<br><br>Following your commit, if you play with the charting test case below and try to get tooltips on chart markers you&#39;ll see that charting event handling is broken because no tooltip appear:<br><br><a href="http://archive.dojotoolkit.org/nightly/dojotoolkit/dojox/charting/tests/test_event2d.html">http://archive.dojotoolkit.org/nightly/dojotoolkit/dojox/charting/tests/test_event2d.html</a><br>
<br>From what I can see charting event handling relies on the fact that a method that has been connected to used to have a _listeners property. The chart event handling is checking for this property to avoid superfluous work. Since this commit the property is not here anymore and no work is done anymore ;)<br>
<br>Is there something similar with the new event handling that charting code can use instead to check for listeners presence on a method? <br><br>Thanks,<br>--<br>Christophe<br><br><div class="gmail_quote">On Tue, Apr 26, 2011 at 5:34 AM, Kris Zyp <span dir="ltr">&lt;<a href="mailto:kzyp at dojotoolkit.org">kzyp at dojotoolkit.org</a>&gt;</span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">I just made a substantial checkin (r24471) of the new event handling<br>
system and query delegation modules. By checking this in, I don&#39;t mean<br>
to indicate that this is an unreversable change to Dojo, but it seems<br>
clear that we need to get these proposed changes easily available to<br>
test and keeping a branch is difficult to maintain. Bill has provided me<br>
a ton of assistance in testing this out on Dijit (Thank you Bill!), so<br>
hopefully it is in relatively good shape as far as stability (I guess we<br>
will see though). Changes include:<br>
<br>
* Addition of dojo/listen, a lighter weight event handling module that<br>
loses some of the cruft that dojo.connect has built up, and provides<br>
some cool new features including event delegation, extension events,<br>
touch event normalization, method/event separation, and event dispatching.<br>
* Addition of dojo/aspect, a very small module to add aspects to<br>
methods. This is included since dojo/listen relies on this module for<br>
listening to non-DOM objects. This suppors before, after, and around<br>
advice based largely on Eugene&#39;s suggestions/specifications.<br>
* dojo/_base/connect.js and .../event.js built on dojo/listen now, with<br>
some back-compat shims to keep it&#39;s behavior the same.<br>
* dojo.NodeList includes an on() method that delegates to dojo/listen<br>
for nodes in the NodeList (with full event delegation support of course).<br>
* Addition of dojo/mouse.js to provide the mouse.enter and mouse.leave<br>
extension events that correspond to dojo.connect&#39;s &quot;mouseenter&quot; and<br>
&quot;mouseleave&quot; emulated events.<br>
* Added some feature detect tests to dojo/has.js for tests that are used<br>
by multiple modules.<br>
* Added JSON validation dojo/json.js for secure/strict validation of<br>
JSON in browsers without native support.<br>
* Addition of dojo/query.js as entry module to performing DOM/selector<br>
queries. This delegates to Acme by default, but can be configured for<br>
alternate engines (tested with Slick, Sizzle, and the new lite engine).<br>
* Cleaner separation of selector engine so we can use Slick and Sizzle<br>
without (or with minimal module wrapping) modification.<br>
* Move Acme (dojo/_base/query.js) to dojo/selector/acme.js for better<br>
clarity<br>
* Addition of dojo/selector/lite.js as a very simple lightweight engine<br>
that can be used as alternative to Acme for applications that don&#39;t need<br>
everything Acme has.<br>
* New unit tests to test this new stuff<br>
* Some other minor updates to modules to better leverage improved AMD<br>
support in Dojo.<br>
* loader-catchApi config setting to false by default. It is terribly<br>
difficult to debug without this.<br>
<br>
I recognize there are still some wrinkles to be ironed out. I have some<br>
experiments with managing memory for IE leakage. The class DOM-JS object<br>
cycle problem is well understood and solvable, however the way we are<br>
currently solving the problem actually causes memory leaks in IE8 and<br>
newer, and I really would like to avoid causing additional leakage. I<br>
have tried some alternative approaches, but IE8 also some weird iframe<br>
related memory leakage that are very difficult to pin down (it is not<br>
the same as the normal DOM cycle leakage), so I still hope to make some<br>
improvements in this area.<br>
<br>
Let me know what issues you find.<br>
Thanks,<br>
Kris<br>
_______________________________________________<br>
dojo-contributors mailing list<br>
<a href="mailto:dojo-contributors at mail.dojotoolkit.org">dojo-contributors@mail.dojotoolkit.org</a><br>
<a href="http://mail.dojotoolkit.org/mailman/listinfo/dojo-contributors" target="_blank">http://mail.dojotoolkit.org/mailman/listinfo/dojo-contributors</a><br>
</blockquote></div><br><br>

--0016e6509fb2d9378b04a1fa66af--

From bogus@does.not.exist.com Tue Jan 18 18:42:17 2011
From: bogus@does.not.exist.com ()
Date: Tue, 18 Jan 2011 23:42:17 -0000
Subject: No subject
Message-ID: <mailman.29.1306254018.13280.dojo-contributors@mail.dojotoolkit.org>

If it can help reduce memory usage and uses less cpu for mobile dijit, big
+1

Some ideas for improving the dojo.connect() / not sure if there's a need for
a whole new api:
Instead of passing around 'event objects', the default behavior could be to
generate "event identifiers' / integer

eventId = dojo.connect(...);

All events would be registered somewhere (no more 'magic cookies'?)

// then you can consistently get an 'event object' through some other api
dojo.event(eventId).cancel();

Maybe dojo.on() could be a wrapper for:

dojo.on = {
var eventId = dojo.connect(...);
return dojo.event(eventId);
}

From bogus@does.not.exist.com Tue Jan 18 18:42:17 2011
From: bogus@does.not.exist.com ()
Date: Tue, 18 Jan 2011 23:42:17 -0000
Subject: No subject
Message-ID: <mailman.30.1306323288.13280.dojo-contributors@mail.dojotoolkit.org>

variable initialization to null. (was there previously in 1.6).

thx
--
Patrick

From bogus@does.not.exist.com Tue Jan 18 18:42:17 2011
From: bogus@does.not.exist.com ()
Date: Tue, 18 Jan 2011 23:42:17 -0000
Subject: No subject
Message-ID: <mailman.31.1306765932.13280.dojo-contributors@mail.dojotoolkit.org>

truly private I would probably suggest that they simply copy the
original code, make their alterations, and use the altered code in
place of the original. Sometimes this can be very difficult
(especially in the case where the alteration needs to be made in the
middle of a largish inheritance chain), at which point the
_byConvention works out ok.

I will reiterate what Kris said though; I think many people who come
to rely on using _functions directly are either shooting themselves in
the foot eventually, or it is a good indicator that the original
_function should have probably been part of the public contract in the
first place--so it might not be a bad idea to try to get a sense of
which _methods are being used by consumers of the library on a regular
basis, and perhaps move some of those towards being public (i.e.
without the "_") as we shift towards 2.0.

Cheers--
Tom
On Sun, May 29, 2011 at 4:02 PM, Kris Zyp wrote:
To voice the other side, I believe that true private functions are
indeed very valuable. The reason we have private functions is to because
the function forms part of the inner workings of an implementation. We
need to be free to change and improve upon our implementations of APIs
in order to continue to evolve and improve Dojo. Private functions also
can have performance advantages in many situations and better
compressibility characteristics. Our _private-by-convention indeed has a
place (there are other situations where these methods perform better),
but frequently has led to a blurry, shoddy state of extensibility. Users
end up using (or extending) _private functions and then either we are
stuck supporting it or their code breaks in a future upgrade. With true
public and private functions the lines are clearly drawn: Use/extend the
public methods if you want a hassle free upgrade, these are the only
ones you can use without changing the source code. If you really need to
deal with implementations internals, than you must modify Dojo source
code. The upgrade process then clearly and explicitly involves merging,
rather than lurking hidden potholes of possible internal-yet-exposed API
changes. If you want a highly extensible class, provide a lot public
methods. If you want internals that you are still working out and
optimizing, private them. IMHO, _private-by-convention is often
indicative of trying to import class-centic model from other languages
rather than groking the scope-centric JS model... But still, there is
still certainly a time and place for each of the techniques. Good
programmers know when to use each. Anyway, just my 2c on this.
Thanks,
Kris
On 5/29/2011 2:07 PM, Mike Wilcox wrote:
On May 29, 2011, at 2:50 PM, Eugene Lazutkin wrote:

Are we okay to use techniques that prevent users from monkey-patching
our code dynamically?
I've voiced this opinion a few times before. Not allowing monkey patching may hamper advanced users of the library for no good reason.

I have monkey patches in DojoX FX - Timeline, Complex and Reverse all monkey patch dojo.animation - and this was enormously difficult due to the large amount of private methods and variables. So this kind of protection would prohibit library extensions as well.

Mike

_______________________________________________
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
From bogus@does.not.exist.com Tue Jan 18 18:42:17 2011
From: bogus@does.not.exist.com ()
Date: Tue, 18 Jan 2011 23:42:17 -0000
Subject: No subject
Message-ID: <mailman.32.1307142520.13280.dojo-contributors@mail.dojotoolkit.org>

pull in the top level js to get started as in the following (or the
dojo.require equivalent thereof):

require(['dojox/mvc', ...], ...)

This would effectively load things like the bind substrate, the model
and its factory function, the data binding mixin and related
_WidgetBase monkey patches to give us ref semantics on dijits etc.
Many of the mvc tests and examples then depend on the dojox global.
This is quite a simple for users, they don't worry about most bits
mentioned in this paragraph.

If we removed the top level js file, did the _base -> main renaming
(AMD question - would that change the require to dojox/mvc/main? got a
pointer to related docs?), removed dojox global references etc., it
might be better given thats where we're heading. I don't know if we
have the time before tag and whether all supporting bits (doc parser
etc.) are firmly in place.

-Rahul

On Thu, Jun 2, 2011 at 4:44 PM, Rahul Akolkar wrote:

Lets use dojox.mvc as the exemplar, I suggest this because of my
interest it in, but also because the following make it a good
candidate:

* This will be the first dojox.mvc release, there are no
compatibility constraints
* Its a small codebase (relative to some others in dojox)
* It has the right representative code patterns (global dojox
assumption, top level js file, monkey patches into dijit)

The way some of the dojox.mvc structure was added (such as top level
js) was by looking at other dojox siblings. If exemplary is desired in
AMD or any other perspective, then exemplars are needed :-)

I encourage anyone interested to just dig in and improve dojox.mvc.
After all, its now in SVN [1].

-Rahul

[1] http://svn.dojotoolkit.org/src/dojox/trunk/mvc/
(and: http://svn.dojotoolkit.org/src/dojox/trunk/mvc.js)
•  at Feb 1, 2011 at 12:22 am ⇧

On 1/31/2011 4:20 PM, James Burke wrote:
2011/1/31 Kris Zyp <kzyp at dojotoolkit.org>:
* We need an API for AMD plugins to trigger recursive builds. I assume this
is a pretty simple addition to the build systems.
This is just my first thoughts, so subject to change/good arguments:

The multi-build work should be done outside of the loader plugin, and
even outside the main builder used for JS modules. This is a job for a
more generic build tool like make or ant.
That is a reasonable way to approach the problem as well, and could
possibly be better. However, there is a necessary coupling and
interaction between the runtime UA-sniffing/branching module that loads
the UA-specific layer and the build scripting process that creates those
layers. The intent with using a plugin is to encapsulate and automate
this synchronization all in a compact package that can be installed like
any other JS package. It would be nice to save developers from hassles
of installation and integration of build scripts, incorporate the UA
branching module into built code, and ensuring that layers are
synchronized with that branching. Maybe that can be done with higher
level build tool...

Even if my suggested solution isn't for everyone, hopefully the
underlying principle is solid: we can and should be using feature
detection in our source modules, and we can and should encourage the
removal of feature detection as build-time optimization through UA
branching tools.
I believe the build tool for a JavaScript dependency system should
focus more strictly on combining sets of modules together, since that
is the hard part that cannot be replicated in other build systems
optimized resources).

Furthermore, I would expect Dojo to never ship with all of those
builds done as part of a Dojo distribution -- that is an optimization
step reserved for the optimization of an app, not of a library that
may be used as an app. Or if it is distributed, it is not the main
distribution -- something that has 5-10 builds of the toolkit inside
it for each type of UA profile would freak people out just on the
download size alone, never mind the set of server rules they need to
put in place to serve them correctly.
Definitely agree, this is only for apps.
While it is worthwhile to work out a system for UA+version specific
builds, not everyone will want them. The file size management
complexity cost and serverside URL routing setup to get it to work
will be seen as too much complication for many sites, and I expect
that once a display ad service is put on the site, any gain by this
sort of optimization will likely go unnoticed, particularly if only
the has tests used by the code are included vs. the full set.
It is indeed less compelling if only tests get excluded. If major blocks
of code are removed (because it is not needed for a particular feature
set), it becomes much more compelling. If you are developing an
application with a focus on using HTML5 features like new form elements,
CSS3 animations, and standard DOM interaction, and omitting larger
components for mobile targets, I think it could be very reasonable to
have applications that are many times bigger in an IE build than latest
the mobile webkit builds. These types of applications is where this type
of system becomes tremendously beneficial. And this type of web
application development is becoming increasingly prevalent now and in
the future.
To be clear: I am not arguing it is not worthwhile, but that it is
just one piece of an optimization story, and there is a complexity
cost to implementing it, and not everyone should be forced to take the
hit of that complexity cost. It needs to be taken when the site is
There isn't anything about such a plugin that would introduce a
(complexity) cost to those that aren't using it is there?
So I see the work as identifying how more generic build tools could
use a database of the has profiles in a build step. I could see this
as generally useful knowledge that is tracked as part of the has.js
project, since it is likely useful even outside any JS module-specific
build tool.
Yes, regardless of the solution, a database of has profiles is important
(and the corresponding UA-driven branching code). Pete, do you have
that? Where is our has() test results going when we do the online test?
Thanks,
Kris
•  at Feb 1, 2011 at 12:35 am ⇧
Both Alex and Kris are right --- the whole optimization story should be
thought out properly, and while doing it, we have to tame complexity as
well.

I am a supporter of feature testing, yet we should be reasonable,
without fanaticism. How many tests are enough? Dozens? Hundreds?
Thousands? What should we test for? Existing bugs only? Present bugs only?

Remember our problems with DOM geometry --- how almost impossible to get
it right? Recently I've been working with MathJax (www.mathjax.org),
which lays out math formulas using absolutely crazy combinations of CSS
and DOM structures. It is open source. So I looked inside at some point
- --- its code based on flags: "if this bug", "if that bug", "if quirks",
and so on --- more than a dozen of such flags corresponding to different
bugs. My understanding is that majority of them are not feature-tested
directly in the code, but calculated using other means, including
UA-sniffing.

Q: how to test layout bugs? The are limits to feature testing.

Still with all complex machinery they have in place --- e.g., it is far
more complex than what we have in our DOM geometry --- I was still
getting visual glitches. It turned out that they never expected (and
never tested) layout inside <div contentEditable=true>. And I don't
blame them. If they start to test all possible yet exotic
configurations, number of feature tests will grow in geometric progression.

Q: where to stop?

Some time ago I was working on a project, and found a bug/feature, which
was common for 2-3 browsers. Immediately I devised a test for it, and
fluffy kittens and unicorns rejoiced. Now, going over my old code, I am
deleting branches marked "Safari 3", "Firefox 2", "Opera 9.5", "IE6",
and so on --- I don't support those browsers anymore. But for the love
of multiple rainbows I cannot remember how relevant my old feature tests
were. Did they become irrelevant with "Firefox 2", or are they still
present? To answer this question I have to go over supported browsers
(two dozens?) and see if they are there or not.

Even if it is not present at the moment, should I keep them in the
off-chance that they will surface again?

Q: how to maintain, and retire tests?

Why don't I keep old tests? I like beautiful well-readable code. All
those pesky tests obscure the real intent. In short I want to remove as
much branches/tests as possible to streamline logic, and maybe gain some
performance. But in reality it was far from trivial, unlike UA-sniffing.

Q: how to evolve/upgrade applications with feature-tests over time?

I guess my point is that feature tests are not a cure-all, it is not
something programmers should take on faith without usual due diligence.
While they can be a right tool for certain things, they are not the only
proper tool in town. And the whole arsenal should be thought out carefully.

Cheers,

Eugene
On 1/31/11 1:35 PM, Kris Zyp wrote:
Partly sparked by Alex's last blog post [1] (I've been thinking about
this subject anyway though), I wanted to go little further in looking
ahead at how I believe we can develop Dojo, RequireJS, and has.js to
create truly optimal applications across different browsers/devices.
First, a few foundational principles. The last decade of JavaScript
development has clearly taught the reliability of using feature
detection. To be clear, UA-sniffing does belong in our source code. This
is clearly the right way to create future-proof source code and to avoid
this in our source code for the sake of performance would be premature
optimization. However, Alex has also clearly pointed out that feature
detection must be optimized out eventually. While our source code may
use feature detection, it is unacceptable for all the feature tests to
optimizations are available. This is where the build comes in. For the
most part, a built application should be based on UA, and use feature
detection as little as possible. Arguing about whether feature detection
or UA-sniffing naive. Briefly, the right time for feature detection and
UA-sniffing is:
* Feature detection at source code level
* UA based determination of features at the build level to eliminate
run-time feature tests

With this approach our source code is future-proof and we can readily
create builds based on the latest UA feature sets without source code
modifications.

Fortunately our move to the standardized convention of has() makes this
type of optimization well within reach. RequireJS has already proven the
ease at which has() branches can eliminate unused feature branches/code.
However, currently we are not offering any help with the actual creation
of UA-specific build layers and the branching to those layers. RequireJS
simply delegates this to the developer to deal with. This is a
non-trivial problem though, and I think significant benefit can be
gained by providing tooling/help in this area.

I threw together a little package to demonstrate a solution we could
provide for UA-sniffing based optimization for feature detection (this
is not functional code right now, just demonstrates the idea):
https://github.com/kriszyp/ua-optimized
The basic premise here is that we have a AMD plugin "ua-optimized" that
can do UA-sniffing to branch to different build layers that were

require(["ua-optimized!my-app"]);

At dev time ua-optimized! would basically be a no-op and would just load
the "my-app" module. During the build, ua-optimized would generate
various (perhaps a dozen or even dozens) build/layers of my-app based
optimized for different UA's and their known feature sets and then most
or all of feature tests and used branches would eliminated. It would
also generate a "default" layer that would corresponded to unknown UAs
and would include all the features and branches. When ua-optimized is
run on built modules, it would then use the UA string to load the
correct UA-specific version of my-app (or the default if the UA is not
known).

Again, the advantage here is that one could build applications and
properly make use of feature detection for safe, reliable code. The
built applications can leverage known UAs to short-cut out of
unnecessary feature tests, while still falling back to feature tests for
unknown user agents. UA-feature set information can be updated in the
future to improve builds without any modification to source code.

There are a couple minor pieces needed to put this puzzle together:

* We need an API for AMD plugins to trigger recursive builds. I assume
this is a pretty simple addition to the build systems.
* We need a database of UAs and their feature sets (based on has.js
tests). Is Pete or any has.js folks already collecting this information?
From http://dante.dojotoolkit.org/hasjs/tests/runTests.html, it looks it
is getting stored somewhere.

[1] http://infrequently.org/2011/01/cutting-the-interrogation-short/

Thanks,
Kris
<https://github.com/kriszyp/ua-optimized>

_______________________________________________
dojo-contributors mailing list
dojo-contributors at mail.dojotoolkit.org
http://mail.dojotoolkit.org/mailman/listinfo/dojo-contributors
•  at Feb 1, 2011 at 3:30 am ⇧
Eugene, well said.

My instinct is that we should "feature test" for bugs still present in the
short-circuit the tests for bugs that have already been fixed. For
example, this would save 25 lines of code:

addtest("dom-dynamic-base", function (g, d, el){ return !(dojo.isFF <
4 || dojo.isIE < 8); });

The upside is size and performance for non-platform-specific builds. The
downside is problems with browser spoofing and possibility that this bug
will resurface some time in the future, or that the bug currently exists on
some browser we don't know about.

Also, before deciding anything, we should wait to see how many
tests/branches we actually need, and how many are just relevant for IE6-8,
etc. etc. has.js is currently 7K compressed and minified, and runs at
about 150ms on iPhone. We won't need all the tests in there, but OTOH we
will need lots of tests that aren't there yet. (For example, if we
actually converted dijit.Editor to feature testing, if that's even possible,
the size/performance would become a bigger issue.)

On Tue, Feb 1, 2011 at 2:35 PM, Eugene Lazutkin wrote:

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Both Alex and Kris are right --- the whole optimization story should be
thought out properly, and while doing it, we have to tame complexity as
well.

I am a supporter of feature testing, yet we should be reasonable,
without fanaticism. How many tests are enough? Dozens? Hundreds?
Thousands? What should we test for? Existing bugs only? Present bugs only?

Remember our problems with DOM geometry --- how almost impossible to get
it right? Recently I've been working with MathJax (www.mathjax.org),
which lays out math formulas using absolutely crazy combinations of CSS
and DOM structures. It is open source. So I looked inside at some point
- --- its code based on flags: "if this bug", "if that bug", "if quirks",
and so on --- more than a dozen of such flags corresponding to different
bugs. My understanding is that majority of them are not feature-tested
directly in the code, but calculated using other means, including
UA-sniffing.

Q: how to test layout bugs? The are limits to feature testing.

Still with all complex machinery they have in place --- e.g., it is far
more complex than what we have in our DOM geometry --- I was still
getting visual glitches. It turned out that they never expected (and
never tested) layout inside <div contentEditable=true>. And I don't
blame them. If they start to test all possible yet exotic
configurations, number of feature tests will grow in geometric progression.

Q: where to stop?

Some time ago I was working on a project, and found a bug/feature, which
was common for 2-3 browsers. Immediately I devised a test for it, and
fluffy kittens and unicorns rejoiced. Now, going over my old code, I am
deleting branches marked "Safari 3", "Firefox 2", "Opera 9.5", "IE6",
and so on --- I don't support those browsers anymore. But for the love
of multiple rainbows I cannot remember how relevant my old feature tests
were. Did they become irrelevant with "Firefox 2", or are they still
present? To answer this question I have to go over supported browsers
(two dozens?) and see if they are there or not.

Even if it is not present at the moment, should I keep them in the
off-chance that they will surface again?

Q: how to maintain, and retire tests?

Why don't I keep old tests? I like beautiful well-readable code. All
those pesky tests obscure the real intent. In short I want to remove as
much branches/tests as possible to streamline logic, and maybe gain some
performance. But in reality it was far from trivial, unlike UA-sniffing.

Q: how to evolve/upgrade applications with feature-tests over time?

I guess my point is that feature tests are not a cure-all, it is not
something programmers should take on faith without usual due diligence.
While they can be a right tool for certain things, they are not the only
proper tool in town. And the whole arsenal should be thought out carefully.

Cheers,

Eugene
On 1/31/11 1:35 PM, Kris Zyp wrote:
Partly sparked by Alex's last blog post [1] (I've been thinking about
this subject anyway though), I wanted to go little further in looking
ahead at how I believe we can develop Dojo, RequireJS, and has.js to
create truly optimal applications across different browsers/devices.
First, a few foundational principles. The last decade of JavaScript
development has clearly taught the reliability of using feature
detection. To be clear, UA-sniffing does belong in our source code. This
is clearly the right way to create future-proof source code and to avoid
this in our source code for the sake of performance would be premature
optimization. However, Alex has also clearly pointed out that feature
detection must be optimized out eventually. While our source code may
use feature detection, it is unacceptable for all the feature tests to
optimizations are available. This is where the build comes in. For the
most part, a built application should be based on UA, and use feature
detection as little as possible. Arguing about whether feature detection
or UA-sniffing naive. Briefly, the right time for feature detection and
UA-sniffing is:
* Feature detection at source code level
* UA based determination of features at the build level to eliminate
run-time feature tests

With this approach our source code is future-proof and we can readily
create builds based on the latest UA feature sets without source code
modifications.

Fortunately our move to the standardized convention of has() makes this
type of optimization well within reach. RequireJS has already proven the
ease at which has() branches can eliminate unused feature branches/code.
However, currently we are not offering any help with the actual creation
of UA-specific build layers and the branching to those layers. RequireJS
simply delegates this to the developer to deal with. This is a
non-trivial problem though, and I think significant benefit can be
gained by providing tooling/help in this area.

I threw together a little package to demonstrate a solution we could
provide for UA-sniffing based optimization for feature detection (this
is not functional code right now, just demonstrates the idea):
https://github.com/kriszyp/ua-optimized
The basic premise here is that we have a AMD plugin "ua-optimized" that
can do UA-sniffing to branch to different build layers that were

require(["ua-optimized!my-app"]);

At dev time ua-optimized! would basically be a no-op and would just load
the "my-app" module. During the build, ua-optimized would generate
various (perhaps a dozen or even dozens) build/layers of my-app based
optimized for different UA's and their known feature sets and then most
or all of feature tests and used branches would eliminated. It would
also generate a "default" layer that would corresponded to unknown UAs
and would include all the features and branches. When ua-optimized is
run on built modules, it would then use the UA string to load the
correct UA-specific version of my-app (or the default if the UA is not
known).

Again, the advantage here is that one could build applications and
properly make use of feature detection for safe, reliable code. The
built applications can leverage known UAs to short-cut out of
unnecessary feature tests, while still falling back to feature tests for
unknown user agents. UA-feature set information can be updated in the
future to improve builds without any modification to source code.

There are a couple minor pieces needed to put this puzzle together:

* We need an API for AMD plugins to trigger recursive builds. I assume
this is a pretty simple addition to the build systems.
* We need a database of UAs and their feature sets (based on has.js
tests). Is Pete or any has.js folks already collecting this information?
From http://dante.dojotoolkit.org/hasjs/tests/runTests.html, it looks it
is getting stored somewhere.

[1] http://infrequently.org/2011/01/cutting-the-interrogation-short/

Thanks,
Kris
<https://github.com/kriszyp/ua-optimized>

_______________________________________________
dojo-contributors mailing list
dojo-contributors at mail.dojotoolkit.org
http://mail.dojotoolkit.org/mailman/listinfo/dojo-contributors
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (Darwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk1Hm4sACgkQY214tZwSfCukMQCeLqLuRKpcPA3cCmcgRRVahvbn
7rsAnit0v7acy2e2Olt13dB/cvryoDNe
=Huv+
-----END PGP SIGNATURE-----
_______________________________________________
dojo-contributors mailing list
dojo-contributors at mail.dojotoolkit.org
http://mail.dojotoolkit.org/mailman/listinfo/dojo-contributors
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.dojotoolkit.org/pipermail/dojo-contributors/attachments/20110201/92505bd5/attachment-0001.htm

## Related Discussions

Discussion Overview
 group dojo-contributors categories dojo posted Jan 31, '11 at 1:35p active Feb 1, '11 at 3:30a posts 6 users 4 website dojotoolkit.org

### 4 users in discussion

Content

People

Support

Translate

site design / logo © 2015 Grokbase