Sencha Touch--Support 2 browsers in just 228K!

G

Garrett Smith

On 2010-07-17 06:25 PM, David Mark wrote: [...]
/**
* Forces the browser to repaint this element

The name "repaint" has the outward indication of a mystical incantation.
We know that there is no way to force a repaint, and so when I see a
name like that, I know that the method won't directly cause the browser
to repaint and that it will, at best, perform an unrelated action that
was associated with addressing a perceived problem.

I'm not sure where you coming from with this.

Was there anything not right about that?
There certainly are observable ways to trigger both — reflow and
repaint; at least in WebKit (as that's the layout engine being discussed
here).

In Chrome you can use Speed Tracer
(<http://code.google.com/webtoolkit/speedtracer/>, developed by Google
themselves, IIRC) to take a peek into when browser reflows the document
and when it repaints the screen.

So there are things that have been associated with reflow an repaint.
Try something like this, to see both — reflow and repaing hapenning at
~3085ms:

[...]

A repaint occurring there wouldn't be surprising at all. The browser is
in a place where it it has new layout information and will need to queue
up a repaint. After the stack of execution contexts has completed would
be a good opportunity to do that recalc.

The recalc is not guaranteed there. What the code does to trigger a
recalc is probably pretty far from whatever it was that they perceived
as a need for a recalc.
Or am I missing something?
I don't know. What's wrong with the criticism I provided?

Garrett
 
G

Garrett Smith

[...]
That error will happen in IE but since IE is not supported they don't
care. That exception won't happen in webkit so they get away with it there.

Yes, this is yet another case of script developers hiding (current or
potential) problems from *themselves*. I cringe every time I hear "I
don't care about browser XYZ" or "Nobody uses browser XYZ" as an

Improving quality reduces costs in the long run.

Testing more browsers improves quality. Given an an unknown browser X
the likelihood of the application failing in browser X inversely
correlated to the number of browsers that it the app is tested working in.

Testing in older shows how the app degrades or fails (degrading is
preferred, failure and errors should be avoided).

The marginal cost of testing in a desktop browser is low.

The cost of fixing the bugs can be high initially, and for the
inexperienced, this can seem not worth it, but as this is repeated, it
becomes easier because the type of constructs that are known to trigger
problems can be avoided.

Limiting the set of tested browsers may initially reduce costs (because
there is less work done), but at the cost of quality, which leads to
increases in costs.

[...]
Sencha, or Ext for TouchScreen devices, supports only a couple devices,
and at a nearly 500k, what does it do?

So as not to cause confusion, I prefer to compare minified sizes (and
I can't see penalizing scripts for using long variable names). It's
bad enough that marketers report sizes after compression. I assume
you are referring to the size with white space and without comments.
Of course, it is 228K minified, but the CSS and graphics easily push
the payload over 500K. Add the application script, markup and assets
ext-touch-debug.js..............458k
ext-touch-debug-w-comments.js...928k

[...]

[...]
The first problem is that it creates invalid selectors out of any
perfectly valid selector that contains a comma. For example, Sencha will
convert the selector '[title="Hey, Joe"]' to '[title="Hey,' and ' Joe"],
both of which are invalid. Sencha then passes each item to
document.querySelectorAll which throws an uncaught error on the invalid
'[title="Hey,' selector.[/QUOTE]

Oh for Christ's sake; that's right. They didn't even bother to wrap
the QSA call in a try-catch. Probably too elitist for them. Such
incompetence makes me bitter (and jealous). :)
[/QUOTE]

Throwing an error for invalid syntax is fine. Throwing an error for
'[title="Hey, Joe"]' is introducing an error that is not present in the
browsers.

[...]
Probably?!

I can assume that the intention of the program was not realized in the
code. The documentation does not match the code and the code does not do
anything sensible. It is hard to make assertions of what the author was
thinking when the code looks mostly unintentional.

The code explains what it does well enough. Extra effort was required to
split on "," and create a loop and for what possible benefit? I really
can't say.
All for no reason, unless they were literally *trying* to fall flat on
their face.

The function could have instead called `root.querySelectorAll`
unfettered by the splitting and looping, and would have avoided all of
those problems.

Of course, it should be first checked that `root` is not null, as calls
to `document.getElementById` can return null.
Hard to tell whether that is a misconception or a copy/paste mistake.

I suspect it may be a holdover from previous jQuery-inspired efforts.
Remember that older versions of jQuery supported XPath.

[...]
 
D

David Mark

On 2010-07-17 06:25 PM, David Mark wrote: [...]
/**
* Forces the browser to repaint this element
The name "repaint" has the outward indication of a mystical incantation.
We know that there is no way to force a repaint, and so when I see a
name like that, I know that the method won't directly cause the browser
to repaint and that it will, at best, perform an unrelated action that
was associated with addressing a perceived problem.
I'm not sure where you coming from with this.

Was there anything not right about that?
There certainly are observable ways to trigger both — reflow and
repaint; at least in WebKit (as that's the layout engine being discussed
here).
In Chrome you can use Speed Tracer
(<http://code.google.com/webtoolkit/speedtracer/>, developed by Google
themselves, IIRC) to take a peek into when browser reflows the document
and when it repaints the screen.

So there are things that have been associated with reflow an repaint.
Try something like this, to see both — reflow and repaing hapenning at
~3085ms:

[...]

A repaint occurring there wouldn't be surprising at all. The browser is
in a place where it it has new layout information and will need to queue
up a repaint. After the stack of execution contexts has completed would
be a good opportunity to do that recalc.

They typically address this on exiting execution contexts, not at the
end of the stack.
 
D

David Mark

[...]
ext-touch-debug.js..............458k

Not sure what sort of "debugging" they had in mind. All it does is
hide mistakes, rather than throwing exceptions for unexpected usage
patterns.

But that measurement includes white space and penalizes long variable
names. That's why I prefer the equalizer of a minification when
making comparisons. jQuery (which does virtually nothing but queries)
is 70K+; Sencha (which supports only two WebKit variations) is 225K+
and the full build of My Library (which does more than the two
*combined* and works in virtually every browser known to man) is 140K
+. And unlike the other two, mine is not hopelessly tangled up in
interdependencies, which makes it easy to create much smaller custom
builds.

The marketers take the opposite tack of touting the sizes after
compression, which just confuses the uninitiated. For example, the
iPhone's cache limit is not based on the compressed size. For
another, if your HTML is 50K and CSS 30K, will the addition of the
"80K" Sencha Touch increase the payload by a factor of two or four?
Of course, the answer is four; but if you are going by the advertised
size, you would have to manually GZIP the HTML and CSS to find this
out. The marketers know that many developers will simply assume that
80K of HTML/CSS is equivalent to "80K" of Sencha.

[...]
I suspect it may be a holdover from previous jQuery-inspired efforts.
Remember that older versions of jQuery supported XPath.

How old? I only remember seeing XPath in Prototype. And AFAIK, they
are still trying to "support" it (despite the fact that it varies
wildly from their other forks).
 
D

David Mark

On 7/18/10 2:18 AM, Garrett Smith wrote:
On 2010-07-17 06:25 PM, David Mark wrote:
[...]
/**
* Forces the browser to repaint this element
The name "repaint" has the outward indication of a mystical incantation.
We know that there is no way to force a repaint, and so when I see a
name like that, I know that the method won't directly cause the browser
to repaint and that it will, at best, perform an unrelated action that
was associated with addressing a perceived problem.
I'm not sure where you coming from with this.
There certainly are observable ways to trigger both — reflow and
repaint; at least in WebKit (as that's the layout engine being discussed
here). [...]
Or am I missing something?
Yes; the code in question seems to assert that it can make the browser
reflow/repaint at a specific point in the execution.  And it doesn't
change the style rules, but does the styling equivalent of a no-op.

I see what you mean. And yes, I see they're adding a class, then
removing it in about 1 ms. I wonder what's the point of setting _both_
class and background; wouldn't class (with proper declarations) suffice?

There's an easy explanation. They added code until it seemed to
"work". It's a classic mystical incantation.
I also wonder about the need for a function like this in the first
place.

There's good reason to wonder. Clearly they were having some sort of
problem and rather than trying to determine the root of it, resorted
to a magic spell (which may or may not hold up in future WebKit
versions).
Reflows/repaints are usually being avoided as much as possible;

Absolutely. It's critical for performance in many areas (e.g.
animations, widgets). And if you don't understand how/when they
happen, you will end up with twitches (i.e. early flashes of content).
What could be the use for such function? Perhaps some layout/positioning
bug on mobile WebKit?

Something they ran into in their zeal to make a monolithic do-
everything library. Clearly they couldn't design around it as they
needed to solve every problem for every context. Some things never
change.
 
G

Garrett Smith

[...]
ext-touch-debug.js..............458k

Not sure what sort of "debugging" they had in mind. All it does is
hide mistakes, rather than throwing exceptions for unexpected usage
patterns.

But that measurement includes white space and penalizes long variable
names. That's why I prefer the equalizer of a minification when
making comparisons. jQuery (which does virtually nothing but queries)
is 70K+; Sencha (which supports only two WebKit variations) is 225K+
and the full build of My Library (which does more than the two
*combined* and works in virtually every browser known to man) is 140K
+. And unlike the other two, mine is not hopelessly tangled up in
interdependencies, which makes it easy to create much smaller custom
builds.

The marketers take the opposite tack of touting the sizes after
compression, which just confuses the uninitiated. For example, the
iPhone's cache limit is not based on the compressed size. For
another, if your HTML is 50K and CSS 30K, will the addition of the
"80K" Sencha Touch increase the payload by a factor of two or four?
Of course, the answer is four; but if you are going by the advertised
size, you would have to manually GZIP the HTML and CSS to find this
out. The marketers know that many developers will simply assume that
80K of HTML/CSS is equivalent to "80K" of Sencha.

[...]
I suspect it may be a holdover from previous jQuery-inspired efforts.
Remember that older versions of jQuery supported XPath.

How old? I only remember seeing XPath in Prototype. And AFAIK, they
are still trying to "support" it (despite the fact that it varies
wildly from their other forks).

jQuery 1.1.4 had XPath support. Other libraries seem to have been
inspired by that and the detritus from those libraries seems to remain
in Ext even in Sencha.

Ext provides additional syntax extensions to match style values (CSS
Value Selectors. The documentation for Sencha states that those are
supported, but they're not.

Ext-JS's (full/big version) more recent design borrows from the jQuery
NFD approach. The timeline is clear that jQuery did that first and the
Ext copied it. Regardless, NFD is a design mistake, no matter how
popular it becomes and no matter many libraries copy it. The reason I
mention this is it seems that Ext-JS has been following what jQuery
does, copying the mistakes and adding its own mistakes to that.

Ext-JS actually makes jQUery look good.

The Sencha documentation I mentioned earlier:
<http://www.sencha.com/deploy/dev/docs/?class=Ext.DomQuery>

The documnetation is quoted in full below. The reason I have done this
is that the documentation may change and when it does, the comments I've
made about it will not apply. By posting that inline, the comments will
be relevant to what is posted here, even if the document at that URI
changes.

The documentation does not reflect what the code does.

| Provides high performance selector/xpath processing by compiling
| queries into reusable functions. New pseudo classes and matchers can
| be plugged. It works on HTML and XML documents (if a content node is
| passed in).
|
| DomQuery supports most of the CSS3 selectors spec, along with some
| custom selectors and basic XPath.
|
| All selectors, attribute filters and pseudos below can be combined
| infinitely in any order. For example "div.foo:nth-child(odd)
| [@foo=bar].bar:first" would be a perfectly valid selector. Node
| filters are processed in the order in which they appear,
| which allows you to optimize your queries for your document structure.
| Element Selectors:
|

That is an example claimed of XPath support. An error will be thrown if
this is followed.

Sencha does not support XPath selectors, except those that also match
exactly the production for CSS Selectors, as [foo=bar], which is valid
XPath and also a valid CSS Selector.

| * * any element

That operator is supported in Sencha, though not properly supported in
Ext-JS, depending on the browser, its version, document mode, etc. The
fundamental problem with the NFD approach that they borrowed from jQuery.

| * E an element with the tag E
| * E F All descendent elements of E that have the tag F
| * E > F or E/F all direct children elements of E that have the tag F
| * E + F all elements with the tag F that are immediately preceded by
| an element with the tag E
| * E ~ F all elements with the tag F that are preceded by a sibling
| element with the tag E
|
| Attribute Selectors:
|
| The use of @ and quotes are optional. For example, div[@foo='bar'] is
| also a valid attribute selector.
|

No, that's not how CSS Selectors work and an error will be thrown if
this is followed.

| * E[foo] has an attribute "foo"
| * E[foo=bar] has an attribute "foo" that equals "bar"
| * E[foo^=bar] has an attribute "foo" that starts with "bar"
| * E[foo$=bar] has an attribute "foo" that ends with "bar"
| * E[foo*=bar] has an attribute "foo" that contains the substring "bar"
| * E[foo%=2] has an attribute "foo" that is evenly divisible by 2
| * E[foo!=bar] has an attribute "foo" that does not equal "bar"
|
| Pseudo Classes:
|
| * E:first-child E is the first child of its parent
| * E:last-child E is the last child of its parent
| * E:nth-child(n) E is the nth child of its parent (1 based as per the
| spec)
| * E:nth-child(odd) E is an odd child of its parent
| * E:nth-child(even) E is an even child of its parent
| * E:eek:nly-child E is the only child of its parent
| * E:checked E is an element that is has a checked attribute that is
| true
| (e.g. a radio or checkbox)
| * E:first the first E in the resultset
| * E:last the last E in the resultset
| * E:nth(n) the nth E in the resultset (1 based)
| * E:eek:dd shortcut for :nth-child(odd)
| * E:even shortcut for :nth-child(even)
| * E:contains(foo) E's innerHTML contains the substring "foo"
| * E:nodeValue(foo) E contains a textNode with a nodeValue that equals
| "foo"

The syntax extensions there, including :nodeValue, will throw an error.

| * E:not(S) an E element that does not match simple selector S
| * E:has(S) an E element that has a descendent that matches simple
| selector S
| * E:next(S) an E element whose next sibling matches simple selector S
| * E:prev(S) an E element whose previous sibling matches simple
| selector S
| * E:any(S1|S2|S2) an E element which matches any of the simple
| selectors
| S1, S2 or S3//\\
|
| CSS Value Selectors:
|

These will all throw errors in Sencha and they do not work in Ext,
either, as you've reviewed the section of code the reads styles, and
that returns different results, when trying to read:

{visibility=visible}

- the result returned depends on the browser and how styles are calculated.

For example, if the default value for visibility is used, the element's
visibility is calcualted as "inherit" (which is correct) and in that
case, the result won't include that element. Except where it does, and
that depends on the browser.

But that is about Ext-JS (big version), not Sencha. In Sencha, all of
this stuff throws errors.

(I've got a some errands to do, so I'm going to post the rest of this
here wihout editing)

| * E{display=none} css value "display" that equals "none"
| * E{display^=none} css value "display" that starts with "none"
| * E{display$=none} css value "display" that ends with "none"
| * E{display*=none} css value "display" that contains the substring
| "none"
| * E{display%=2} css value "display" that is evenly divisible by 2
| * E{display!=none} css value "display" that does not equal "none"
|
|
|
| This class is a singleton and cannot be created directly.
| Public Properties
| Property Defined By
| matchers : Object
| Collection of matching regular expressions and code snippets. Each
| capture group within () will be replace the {} in ...
| Collection of matching regular expressions and code snippets. Each
| capture group within () will be replace the {} in the select statement
| as specified by their index.
| DomQuery
| pseudos : Object
| Object hash of "pseudo class" filter functions which are used when
| filtering selections. Each function is passed two ...
|
| Object hash of "pseudo class" filter functions which are used when
| filtering selections. Each function is passed two parameters:
|
| * c : Array
| An Array of DOM elements to filter.
| * v : String
| The argument (if any) supplied in the selector.
|
| A filter function returns an Array of DOM elements which conform to
| the pseudo class.
|
| In addition to the provided pseudo classes listed above such as
| first-child and nth-child, developers may add additional, custom psuedo
| class filters to select elements according to application-specific
| requirements.
|
| For example, to filter <a> elements to only return links to external
| resources:
|
| Ext.DomQuery.pseudos.external = function(c, v){
| var r = [], ri = -1;
| for(var i = 0, ci; ci = c; i++){
| // Include in result set only if it's a link to an external resource
| if(ci.hostname != location.hostname){
| r[++ri] = ci;
| }
| }
| return r;
| };
|
| Then external links could be gathered with the following statement:
|
| var externalLinks = Ext.select("a:external");
|
| DomQuery
| Public Methods
| Method Defined By
| compile( String selector, [String type] ) : Function
| Compiles a selector/xpath query into a reusable function. The returned
| function takes one parameter "root" (optional)...
| Compiles a selector/xpath query into a reusable function. The returned
| function takes one parameter "root" (optional), which is the context
| node from where the query should start.
| Parameters:
|
| * selector : String
| The selector/xpath query
| * type : String
| (optional) Either "select" (the default) or "simple" for a simple
| selector match
|
| Returns:
|
| * Function
|
| DomQuery
| filter( Array el, String selector, Boolean nonMatches ) : Array
| Filters an array of elements to only include matches of a simple
| selector (e.g. div.some-class or span:first-child)
| Filters an array of elements to only include matches of a simple
| selector (e.g. div.some-class or span:first-child)
| Parameters:
|
| * el : Array
| An array of elements to filter
| * selector : String
| The simple selector to test
| * nonMatches : Boolean
| If true, it returns the elements that DON'T match the selector instead
| of the ones that match
|
| Returns:
|
| * Array
| An Array of DOM elements which match the selector. If there are no
| matches, and empty Array is returned.
|
| DomQuery
| is( String/HTMLElement/Array el, String selector ) : Boolean
| Returns true if the passed element(s) match the passed simple selector
| (e.g. div.some-class or span:first-child)
| Returns true if the passed element(s) match the passed simple selector
| (e.g. div.some-class or span:first-child)
| Parameters:
|
| * el : String/HTMLElement/Array
| An element id, element or array of elements
| * selector : String
| The simple selector to test
|
| Returns:
|
| * Boolean
|
| DomQuery
| jsSelect( String selector, [Node/String root] ) : Array
| Selects a group of elements.
| Selects a group of elements.
| Parameters:
|
| * selector : String
| The selector/xpath query (can be a comma separated list of selectors)
| * root : Node/String
| (optional) The start of the query (defaults to document).
|
| Returns:
|
| * Array
| An Array of DOM elements which match the selector. If there are no
| matches, and empty Array is returned.
|
| DomQuery
| operators() : void
| Collection of operator comparison functions. The default operators are
| =, !=, ^=, $=, *=, %=, |= and ~=. New operator...
| Collection of operator comparison functions. The default operators are
| =, !=, ^=, $=, *=, %=, |= and ~=. New operators can be added as long
| as the match the format c= where c is any character other than space,
| > <.
| Parameters:
|
| * None.
|
| Returns:
|
| * void
|

At least half of these operators are syntax extensions.

| DomQuery
| selectNode( String selector, [Node root] ) : Element
| Selects a single element.
| Selects a single element.
| Parameters:
|
| * selector : String
| The selector/xpath query
| * root : Node
| (optional) The start of the query (defaults to document).
|
| Returns:
|
| * Element
| The DOM element which matched the selector.
|
| DomQuery
| selectNumber( String selector, [Node root], Number defaultValue ) :
| Number
| Selects the value of a node, parsing integers and floats. Returns the
| defaultValue, or 0 if none is specified.
| Selects the value of a node, parsing integers and floats. Returns the
| defaultValue, or 0 if none is specified.
| Parameters:
|
| * selector : String
| The selector/xpath query
| * root : Node
| (optional) The start of the query (defaults to document).
| * defaultValue : Number
|
| Returns:
|
| * Number
|
| DomQuery
| selectValue( String selector, [Node root], String defaultValue ) :
| String
| Selects the value of a node, optionally replacing null with the
| defaultValue.
| Selects the value of a node, optionally replacing null with the
| defaultValue.
| Parameters:
|
| * selector : String
| The selector/xpath query
| * root : Node
| (optional) The start of the query (defaults to document).
| * defaultValue : String
|
| Returns: String
|
| DomQuery

The `selectValue` and `selectNumber` methods are missing altogether from
Sencha.

typeof Ext.DomQuery.selectValue

"undefined"
 
D

David Mark

[...]
ext-touch-debug.js..............458k

Not sure what sort of "debugging" they had in mind.  All it does is
hide mistakes, rather than throwing exceptions for unexpected usage
patterns.
But that measurement includes white space and penalizes long variable
names.  That's why I prefer the equalizer of a minification when
making comparisons.  jQuery (which does virtually nothing but queries)
is 70K+; Sencha (which supports only two WebKit variations) is 225K+
and the full build of My Library (which does more than the two
*combined* and works in virtually every browser known to man) is 140K
+.  And unlike the other two, mine is not hopelessly tangled up in
interdependencies, which makes it easy to create much smaller custom
builds.
The marketers take the opposite tack of touting the sizes after
compression, which just confuses the uninitiated.  For example, the
iPhone's cache limit is not based on the compressed size.  For
another, if your HTML is 50K and CSS 30K, will the addition of the
"80K" Sencha Touch increase the payload by a factor of two or four?
Of course, the answer is four; but if you are going by the advertised
size, you would have to manually GZIP the HTML and CSS to find this
out.  The marketers know that many developers will simply assume that
80K of HTML/CSS is equivalent to "80K" of Sencha.
I suspect it may be a holdover from previous jQuery-inspired efforts.
Remember that older versions of jQuery supported XPath.
How old?  I only remember seeing XPath in Prototype.  And AFAIK, they
are still trying to "support" it (despite the fact that it varies
wildly from their other forks).

jQuery 1.1.4 had XPath support. Other libraries seem to have been
inspired by that and the detritus from those libraries seems to remain
in Ext even in Sencha.

Yes, Ext has it. And, like Prototype, there's not a chance in hell it
matches their other forks. For example, they are all afflicted by the
same misconceptions about attributes. It you look at documents as
database tables, elements as rows and attributes as fields, the
monumental futility of CSS selector query engines (as implemented in
all of the "major" libraries) is clear. Who would use such a
database? The only defense I've heard from those who lean on these
things is that they don't care because they somehow manage to avoid
the problems (which vary wildly from one browser to the next) at least
in the browsers they "care" about. Of course that would require an
inhuman amount of memorization to make work and there would always be
the chance that the ever-shifting libraries could invalidate their map
at any time. And then there are the browsers they've never heard of
(most notably the ones that have yet to be published).
Ext provides additional syntax extensions to match style values (CSS
Value Selectors. The documentation for Sencha states that those are
supported, but they're not.

Of course not. We've seen how Ext/Sencha deal with styles. They are
just as clumsy with those as they are with attributes. Thus large
portions of their documentation are pure fantasy.
Ext-JS's (full/big version) more recent design borrows from the jQuery
NFD approach. The timeline is clear that jQuery did that first and the
Ext copied it.

Yes, Sizzle was a fraud perpetrated on jQuery users, dressed up as a
performance increase. Here's John Resig lamenting what should have
been the end of his old query code:-

http://ejohn.org/blog/thoughts-on-queryselectorall/#postcomment

....then he went ahead and piled QSA on top of it. His fellow
"luminaries" predictably followed suit.

And speaking of the other efforts; you mentioned that ExtJS was the
worst of the worst with respect to queries. But I don't know how you
could get much more inept than Dojo's, which relies on their "attr"
function, which has always been complete gibberish. It's only a
couple of dozen lines of code and I once tried to explain its illogic
to them, but they just kept chirping: "show me where it fails". I was
reluctant to do that as it would predictably lead to patches without
understanding (or fixing) the general problem. But even after
producing a couple of failure cases, they were still hesitant to
change anything, lest they break compatibility. Of course,
"compatibility" that produces one result in IE8 standards mode and
another in its compatibility view is not something to preserve.
Furthermore, their "vaunted" widgets and parser rely heavily on this
function, so the mistakes manifest themselves in virtually everything
they do. Their forums, mailing lists, etc. are full of confused
questions (and even more confused answers) related to these issues.
Regardless, NFD is a design mistake, no matter how
popular it becomes and no matter many libraries copy it.

Of course it is. A child could see that.
The reason I
mention this is it seems that Ext-JS has been following what jQuery
does, copying the mistakes and adding its own mistakes to that.

It appears that way. And they have the gall to charge people to use
recycled garbage.
Ext-JS actually makes jQUery look good.

It's apples and oranges, but if you just compare the Ext core to
jQuery, then I'd have to agree. Pity. And people wonder why I don't
like *any* of these things.
The Sencha documentation I mentioned earlier:
<http://www.sencha.com/deploy/dev/docs/?class=Ext.DomQuery>

The documnetation is quoted in full below. The reason I have done this
is that the documentation may change and when it does, the comments I've
made about it will not apply. By posting that inline, the comments will
be relevant to what is posted here, even if the document at that URI
changes.

The documentation does not reflect what the code does.

| Provides high performance selector/xpath processing by compiling
| queries into reusable functions. New pseudo classes and matchers can
| be plugged. It works on HTML and XML documents (if a content node is
| passed in).

That sounds like an optimistic appraisal of ExtJS, but Sencha Touch
does nothing of the sort. It "compiles" nothing and certainly won't
work with XML documents.
|
| DomQuery supports most of the CSS3 selectors spec, along with some
| custom selectors and basic XPath.
|
| All selectors, attribute filters and pseudos below can be combined
| infinitely in any order.

Infinitely. :) Of course, even one selector may get the wrong
result, depending on browser, rendering mode, phase of the moon, etc.
Why do developers insist on buying in to this stuff? The whole idea
was doomed from the start, has failed miserably and yet is more
popular than ever. The popularity is often used as an excuse to use
queries, while the myriad technical issues are brushed off as
irrelevant. Go figure.
For example "div.foo:nth-child(odd)
| [@foo=bar].bar:first" would be a perfectly valid selector. Node
| filters are processed in the order in which they appear,
| which allows you to optimize your queries for your document structure.
| Element Selectors:
|

That is an example claimed of XPath support. An error will be thrown if
this is followed.

Sencha does not support XPath selectors, except those that also match
exactly the production for CSS Selectors, as [foo=bar], which is valid
XPath and also a valid CSS Selector.

Yes, occasionally works by coincidence.
| * * any element

That operator is supported in Sencha, though not properly supported in
Ext-JS, depending on the browser, its version, document mode, etc. The
fundamental problem with the NFD approach that they borrowed from jQuery.

Yes, the native implementations are incompatible with the scripted
query engines, which are often incompatible with themselves (e.g.
changing from one version of jQuery to the next).
| * E an element with the tag E
| * E F All descendent elements of E that have the tag F
| * E > F or E/F all direct children elements of E that have the tag F
| * E + F all elements with the tag F that are immediately preceded by
| an element with the tag E
| * E ~ F all elements with the tag F that are preceded by a sibling
| element with the tag E
|
| Attribute Selectors:
|
| The use of @ and quotes are optional. For example, div[@foo='bar'] is
| also a valid attribute selector.
|

No, that's not how CSS Selectors work and an error will be thrown if
this is followed.

When it comes to attributes, they've got so many problems that
developers should just forget about using such queries. Of course,
many jQuery tutorials demonstrate querying by attribute values.
| * E[foo] has an attribute "foo"
| * E[foo=bar] has an attribute "foo" that equals "bar"
| * E[foo^=bar] has an attribute "foo" that starts with "bar"
| * E[foo$=bar] has an attribute "foo" that ends with "bar"
| * E[foo*=bar] has an attribute "foo" that contains the substring "bar"
| * E[foo%=2] has an attribute "foo" that is evenly divisible by 2
| * E[foo!=bar] has an attribute "foo" that does not equal "bar"
|
| Pseudo Classes:
|
| * E:first-child E is the first child of its parent
| * E:last-child E is the last child of its parent
| * E:nth-child(n) E is the nth child of its parent (1 based as per the
| spec)
| * E:nth-child(odd) E is an odd child of its parent
| * E:nth-child(even) E is an even child of its parent
| * E:eek:nly-child E is the only child of its parent
| * E:checked E is an element that is has a checked attribute that is
| true
| (e.g. a radio or checkbox)

That's not right. For one, a checked attribute cannot be
"true" (except in an invalid document) and the :checked pseudo queries
the *property* so as to take user input into account. Fortunately, I
think that's what they all do anyway; but unfortunately, they do the
same thing when querying the CHECKED attribute. In my experience,
most of the participants in these projects don't know the difference.
| * E:first the first E in the resultset
| * E:last the last E in the resultset
| * E:nth(n) the nth E in the resultset (1 based)
| * E:eek:dd shortcut for :nth-child(odd)
| * E:even shortcut for :nth-child(even)
| * E:contains(foo) E's innerHTML contains the substring "foo"
| * E:nodeValue(foo) E contains a textNode with a nodeValue that equals
| "foo"

The syntax extensions there, including :nodeValue, will throw an error.

Yes. The :contains pseudo was in at least one of the Selectors drafts,
but was eventually dropped, so QSA implementations can't parse it.
| * E:not(S) an E element that does not match simple selector S
| * E:has(S) an E element that has a descendent that matches simple
| selector S
| * E:next(S) an E element whose next sibling matches simple selector S
| * E:prev(S) an E element whose previous sibling matches simple
| selector S
| * E:any(S1|S2|S2) an E element which matches any of the simple
| selectors
| S1, S2 or S3//\\
|
| CSS Value Selectors:
|

These will all throw errors in Sencha and they do not work in Ext,
either, as you've reviewed the section of code the reads styles, and
that returns different results, when trying to read:

{visibility=visible}

- the result returned depends on the browser and how styles are calculated.

Yes, using these things to query by style values is even less
predictable than querying by attribute values.
For example, if the default value for visibility is used, the element's
visibility is calcualted as "inherit" (which is correct) and in that
case, the result won't include that element. Except where it does, and
that depends on the browser.

No, "inherit" would be incorrect for getComputedStyle. For elements
without a visibility rule, "visible" is the expected result. Now,
IE's "cascaded styles" will indeed return "inherit" as IE doesn't
compute styles at all, simply returning whatever is specified in
applicable rules (or the default value, which is "inherit" in this
case).

Regardless, I'm sure that ExtJS fails to account for this (among many
other things). Just like jQuery! :)
But that is about Ext-JS (big version), not Sencha. In Sencha, all of
this stuff throws errors.

Of course as it has no query engine; it simply hands off all queries
to QSA.
(I've got a some errands to do, so I'm going to post the rest of this
here wihout editing)

| * E{display=none} css value "display" that equals "none"
| * E{display^=none} css value "display" that starts with "none"
| * E{display$=none} css value "display" that ends with "none"
| * E{display*=none} css value "display" that contains the substring
| "none"

There's not a chance in hell they got any of those right cross-
browser.
| * E{display%=2} css value "display" that is evenly divisible by 2

LOL. What on earth would that mean?
| * E{display!=none} css value "display" that does not equal "none"
|
|
|
| This class is a singleton and cannot be created directly.

It's neither a class nor a singleton.
| Public Properties

All JS properties are public.
| Property Defined By
| matchers : Object
| Collection of matching regular expressions and code snippets. Each
| capture group within () will be replace the {} in ...
| Collection of matching regular expressions and code snippets. Each
| capture group within () will be replace the {} in the select statement
| as specified by their index.
| DomQuery
| pseudos : Object
| Object hash of "pseudo class" filter functions which are used when
| filtering selections. Each function is passed two ...

Oh God. As usual, these types of projects get ten steps ahead of
themselves. I mean, it's 2010 and their basic queries are still
broken. What's the point of piling all of this other nonsense on top?

[snip more delusions]
|
| DomQuery
| selectNumber( String selector, [Node root], Number defaultValue ) :
| Number
| Selects the value of a node, parsing integers and floats. Returns the
| defaultValue, or 0 if none is specified.
| Selects the value of a node, parsing integers and floats. Returns the
| defaultValue, or 0 if none is specified.
| Parameters:
|
| * selector : String
| The selector/xpath query
| * root : Node
| (optional) The start of the query (defaults to document).
| * defaultValue : Number
|
| Returns:
|
| * Number
|
| DomQuery
| selectValue( String selector, [Node root], String defaultValue ) :
| String
| Selects the value of a node, optionally replacing null with the
| defaultValue.
| Selects the value of a node, optionally replacing null with the
| defaultValue.
| Parameters:
|
| * selector : String
| The selector/xpath query
| * root : Node
| (optional) The start of the query (defaults to document).
| * defaultValue : String
|
| Returns:  String
|
| DomQuery

The `selectValue` and `selectNumber` methods are missing altogether from
Sencha.

There's a lot of that going on. They were clearly pressed for time.
typeof Ext.DomQuery.selectValue

"undefined"

Here's a good acid test for a Web application:-

typeof Ext == 'undefined'

,,,with true being the desired result. ;)
 
R

Ry Nohryb

The name "repaint" has the outward indication of a mystical incantation.
We know that there is no way to force a repaint, and so when I see a
name like that, I know that the method won't directly cause the browser
to repaint and that it will, at best, perform an unrelated action that
was associated with addressing a perceived problem.

You're mistaken, again, Garrett.
Yes, there are ways to force both reflows and repaints.
For example, this (google groups) page can be forced to repaint with:

document.body.style.opacity= 0;
setTimeout(function(){document.body.style.opacity= 1},0);

Or with:
document.body.style.visibility= "hidden";
setTimeout(function(){document.body.style.visibility= ""},0);

And to reflow (+ repaint):
document.body.style.maxWidth= "50px";
setTimeout(function(){document.body.style.maxWidth= ""},0);

HTH,
 
D

David Mark

You're mistaken, again, Garrett.
Yes, there are ways to force both reflows and repaints.
For example, this (google groups) page can be forced to repaint with:

document.body.style.opacity= 0;
setTimeout(function(){document.body.style.opacity= 1},0);

Or with:
document.body.style.visibility= "hidden";
setTimeout(function(){document.body.style.visibility= ""},0);

And to reflow (+ repaint):
document.body.style.maxWidth= "50px";
setTimeout(function(){document.body.style.maxWidth= ""},0);

HTH,

It doesn't. This oversimplification of the issue was covered earlier
in the thread (just a few hours ago). Of course you can cause the
document to reflow/repaint if you change its style and exit an
execution context (though it may not happen immediately). The
question is why you would need to do that with the styling equivalent
of a no-op. The answer is that you wouldn't unless you were stuck and
resorting to programming by mystical incantation.

Please read before posting next time. Thanks!
 
G

Garrett Smith

You're mistaken, again, Garrett.

Did you need more explanation, after all that I have explained to you
already?
Yes, there are ways to force both reflows and repaints.

If that is true, you have not proven it.
For example, this (google groups) page can be forced to repaint with:

No, it cannot. About the best you can do is hope that the browser will
repaint.

So you've made observations of what happened in the browser and
concluded that those observations are premises for causality, huh?

That is a classic Post hoc ergo propter hoc fallacy. I saw B after A.
Therefore, A causes B. (fallacious).

[snip]

That code proves nothing at all. Where is the specification (or even
browser documentation) for "how to repaint"? There is none, is there?

It does not. The browser will repaint when it needs to.

Repaint issues are not new to me. I have dealt with them many years ago
when the then popular hacks included such things as modifying the status
bar and even resizing the window.

resizeBy(0, 1);
resizeBy(0, -1);

(!)
Voodoo.
 
R

Ry Nohryb

(...) The
question is why you would need to do that with the styling equivalent
of a no-op.  The answer is that you wouldn't unless you were stuck and
resorting to programming by mystical incantation.

I always read before posting: it was a reply to Garrett's assertion
"We know that there is no way to force a repaint", which is -plainly-
false. See:

"Faster HTML and CSS: Layout Engine Internals for Web Developers",
David Baron.
Please read before posting next time.  Thanks!

You're welcome.
 
D

David Mark

I always read before posting: it was a reply to Garrett's assertion
"We know that there is no way to force a repaint", which is -plainly-
false.

Which was pointless.
See:

"Faster HTML and CSS: Layout Engine Internals for Web Developers",
David Baron.

As is that. You are your videos. :(
 
R

Ry Nohryb

On 2010-07-18 10:51 PM, Ry Nohryb wrote:
(...)


No, it cannot. About the best you can do is hope that the browser will
repaint.

So you've made observations of what happened in the browser and
concluded that those observations are premises for causality, huh?
(...)

What I said is not based on any "mystical incantation" but on what the
author of Mozilla's rendering engine explains in this video:

"Faster HTML and CSS: Layout Engine Internals for Web Developers",
David Baron.

Obviously you too (I told Mark already) ought to see it in order to
learn the fundamentals of the inner workings of rendering engines, and
once you begin to see through the black box, you (and Mark) will be
able to stop thinking about it any more in terms of mystical
incantations.

HTH,
 
G

Garrett Smith

ext-touch-debug.js..............458k
[...]


And speaking of the other efforts; you mentioned that ExtJS was the
worst of the worst with respect to queries. But I don't know how you
could get much more inept than Dojo's, which relies on their "attr"

I did not review Dojo's in depth, but the overall design approach makes
more sense. From memory, dojo uses its own engine first, and if that
works, then it tries to use NodeSelector the next time.
function, which has always been complete gibberish. It's only a
couple of dozen lines of code and I once tried to explain its illogic
to them, but they just kept chirping: "show me where it fails". I was
reluctant to do that as it would predictably lead to patches without
understanding (or fixing) the general problem. But even after
producing a couple of failure cases, they were still hesitant to
change anything, lest they break compatibility. Of course,
"compatibility" that produces one result in IE8 standards mode and
another in its compatibility view is not something to preserve.
Furthermore, their "vaunted" widgets and parser rely heavily on this
function, so the mistakes manifest themselves in virtually everything
they do. Their forums, mailing lists, etc. are full of confused
questions (and even more confused answers) related to these issues.

The predicament is that fixing the broken abstraction affects the
dependencies.

Changes to low-level abstractions propagate to higher level abstractions
and the result is instability.

The alternative to causing such instability -- and which Dojo has seemed
to favor here -- is to not fix the bugs.

Of course the problem with that is that everything is broken and as you
pointed out, broken differently across different browsers, rendering
mode, etc.

An low level abstraction that is fundamentally broken is a serious problem.
Of course it is. A child could see that.


It appears that way. And they have the gall to charge people to use
recycled garbage.

Well, if it is coming at premium cost, there will be those who think
that it must be better.
[...]
That sounds like an optimistic appraisal of ExtJS, but Sencha Touch
does nothing of the sort. It "compiles" nothing and certainly won't
work with XML documents.

Ext-JS -- not Sencha -- dynamically create functions that they reuse.
This is what they mean by "compiled". that doesn't apply to Sencha, but
just an FYI about what they mean by "compile".

[...]
That's not right. For one, a checked attribute cannot be
"true" (except in an invalid document) and the :checked pseudo queries
the *property* so as to take user input into account. Fortunately, I
think that's what they all do anyway; but unfortunately, they do the
same thing when querying the CHECKED attribute. In my experience,
most of the participants in these projects don't know the difference.

Not all, and there are some that check attributes. NWMatcher is
cognizant of that, at least.

[...]
Yes, using these things to query by style values is even less
predictable than querying by attribute values.

It is.

The selector engine can be accessed from both
Ext.Element.selectorFunction and Ext.query. These are core abstractions
in the library and are accessed from two core parts of the library, both
of which express a package interdependency.

A selector engine that offers no deliberate syntax extensions is safer,
because it does not have as much deviation from the spec.

Any library that uses custom selectors, selectors that match attributes,
and anything that uses native-first dual approach cannot be easily
fixed. Continuing to use such library either changed or unchanged would
be unsafe.

Any library that uses a broken query selector at the core is just as
broken as its query engine. Fixing the bugs causes instability. Problems
are not limited to queries, however.

When changes to low-level abstractions propagate to higher level
abstractions the result is instability.

Each bug in Ext-JS's selector engine necessarily propagates to a higher
level. When the selector engine's behavior is changed, that change is
propagated to all of the higher level dependencies. Such behavioral
changes cause instability. The alternative to causing such changes is to
not fix the bugs.

Buyer Beware.
The alternative for the end user is to not use include such things on
the page. As I have always advised for the developer who is considering
using a js library: Carefully review the source code of any js library
before using it.

No, "inherit" would be incorrect for getComputedStyle. For elements
without a visibility rule, "visible" is the expected result. Now,
IE's "cascaded styles" will indeed return "inherit" as IE doesn't
compute styles at all, simply returning whatever is specified in
applicable rules (or the default value, which is "inherit" in this
case).

That's correct.

var a = Ext.query("{visibility=inherit}");

The result of that in Ext shows that it does not work consistently
either, and a.length will be 0, depending on the browser. This is due to
the fact that it relies on Ext.Dom.getStyle, which, like most everything
in Ext-JS, is very broken.
Regardless, I'm sure that ExtJS fails to account for this (among many
other things). Just like jQuery! :)


Of course as it has no query engine; it simply hands off all queries
to QSA.

If it had simply handed queries off to `querySelectorAll`, it would not
have created as many problems.

Extra effort was required to split on "," and create a loop, adding
duplicates to the returned result.

So while they do use querySelectorAll, they go to a lot of extra effort
to complicate it and create problems. Why they expended this extra
effort, I cannot say.

The code with comments being blatantly false could be attributed to haste.
There's not a chance in hell they got any of those right cross-
browser.

You reviewed Ext.Dom.getStyle and, as you pointed out,
`hasRightMarginBug` is completely missing for the script.

"hasRightMarginBug" in Ext.platform

false

It seems they forgot to include that property, though continue to
reference it. Since the resolution results in undefined and since
undefined evaluates to false, any code that uses that identifier in a
boolean context is completely useless and dead code.

And so all of the:

| if (Ext.platform.hasRightMarginBug && marginRightRe.test(prop) && out
| != '0px') {
| display = this.getStyle('display');
| el.style.display = 'inline-block';
| result = view.getComputedStyle(el, '');
| el.style.display = display;
| }

is dead code and will never be evaluated.
| * E{display!=none} css value "display" that does not equal "none"
|
|
|
| This class is a singleton and cannot be created directly.

It's neither a class nor a singleton.
| Public Properties

All JS properties are public.
| Property Defined By
| matchers : Object
| Collection of matching regular expressions and code snippets. Each
| capture group within () will be replace the {} in ...
| Collection of matching regular expressions and code snippets. Each
| capture group within () will be replace the {} in the select statement
| as specified by their index.
| DomQuery
| pseudos : Object
| Object hash of "pseudo class" filter functions which are used when
| filtering selections. Each function is passed two ...

Oh God. As usual, these types of projects get ten steps ahead of
themselves. I mean, it's 2010 and their basic queries are still
broken. What's the point of piling all of this other nonsense on top?

[snip more delusions]

Although library author is free to make any design decision he chooses,
if the design decisions violate the CSS specifications and drafts (and
these do), then the code cannot honestly be said to be CSS3 compliant.

Ext-JS claims "DomQuery supports most of the CSS3 selectors spec, along
with some custom selectors and basic XPath". Whether Ext supports more
than half of CSS3 selectors depends on the browser and the claim of
"basic XPath" support is false (possibly outdated documentation from
previous jQuery copying).
|
| DomQuery
| selectNumber( String selector, [Node root], Number defaultValue ) :
| Number
| Selects the value of a node, parsing integers and floats. Returns the
| defaultValue, or 0 if none is specified.
| Selects the value of a node, parsing integers and floats. Returns the
| defaultValue, or 0 if none is specified.
| Parameters:
|
| * selector : String
| The selector/xpath query
| * root : Node
| (optional) The start of the query (defaults to document).
| * defaultValue : Number
|
| Returns:
|
| * Number
|
| DomQuery
| selectValue( String selector, [Node root], String defaultValue ) :
| String
| Selects the value of a node, optionally replacing null with the
| defaultValue.
| Selects the value of a node, optionally replacing null with the
| defaultValue.
| Parameters:
|
| * selector : String
| The selector/xpath query
| * root : Node
| (optional) The start of the query (defaults to document).
| * defaultValue : String
|
| Returns: String
|
| DomQuery

The `selectValue` and `selectNumber` methods are missing altogether from
Sencha.

There's a lot of that going on. They were clearly pressed for time.

Seems so. Yet another framework rushed to market, marketed heavily,
using fancy demos with nice images.

The difference between marketing and engineering seems to not very well
perceived.

Looking at demos is much more accessible than being able to make
assessments of front end code quality.

The number of individuals who look at the demos is going to be larger
than the number of individuals who review the code. This is not surprising.

What is surprising is that prior to the recent angel investment into
Sencha, they did not a few qualified individuals to do code review on
it. This would not have been much investment and could have helped avoid
such an amazing waste of money[1].

From the perspective of the investor who does not have any idea of the
code quality, he could employ two highly qualified individuals for a
maximum of one week each to review and assess the code at a cost under
10,000 USD. In reality, it is not hard to look at the code and find a
mistake at line 1:

window.undefined = window.undefined;

- and continue to find a very high defect rate and significantly bad
defects that we have covered and other glaring errors and design
mistakes that were covered by RobG[2].

Having volunteered so much free time over the years to spread knowledge
of web development, it seems that too few care about the code.

The financial losses from projects debilitated by bad code is real.

Bad code costs money.

Bad code hides bugs that might not surface immediately.

Tangled messy code can't be changed easily. The time involved to add a
new feature can be double, and then coming back to regression testing,
bugfixes for all of the change propagation.

This can lead to losing customers from bugs and even project failure
(and I have swam from such sunken ships, having failed to inspire the
captain into smart choices). It is not easy to measure how much money
was wasted by bad code. There is never a "good code" control group and
problems and debt compound.

Ext-JS is very buggy. It is awful code.

Any javascript developer who Ext-JS either has not read the source code
enough, is not capable of understanding the problems, or has read and
understood the problems but has not appreciated the consequences deeply.
The choice to use Ext-JS is a substantially irresponsible and uninformed
decision that puts quality and long-term success of his project at risk.

[1] <http://techcrunch.com/2010/06/23/sencha-html5-funding-sequoia/>
[2] "jquery vs dojo vs yui etc"
<http://groups.google.com/group/comp.lang.javascript/msg/d49c2a6b9a01c55c>
 
D

David Mark

What I said is not based on any "mystical incantation" but on what the
author of Mozilla's rendering engine explains in this video:

"Faster HTML and CSS: Layout Engine Internals for Web Developers",
David Baron.

Obviously you too (I told Mark already) ought to see it in order to
learn the fundamentals of the inner workings of rendering engines, and
once you begin to see through the black box, you (and Mark) will be
able to stop thinking about it any more in terms of mystical
incantations.

HTH,

Nope. I don't need to watch the video. You need to learn to read.
Thanks!
 
D

David Mark

On 2010-07-18 02:42 PM, David Mark wrote:
[...]
ext-touch-debug.js..............458k
[...]



And speaking of the other efforts; you mentioned that ExtJS was the
worst of the worst with respect to queries.  But I don't know how you
could get much more inept than Dojo's, which relies on their "attr"

I did not review Dojo's in depth, but the overall design approach makes
more sense. From memory, dojo uses its own engine first, and if that
works, then it tries to use NodeSelector the next time.

Its own engine is the problem. Certainly it isn't aware of whether it
works or not (unless "works" means avoiding exceptions).
The predicament is that fixing the broken abstraction affects the
dependencies.

The problem is that their abstraction is inconsistent cross-browser,
so is nothing to cling to. The other problem is that none of them can
define what it is supposed to be doing.
Changes to low-level abstractions propagate to higher level abstractions
and the result is instability.

But when you are already getting two different results for the same
browser (e.g. IE8 depending on rendering mode), it indicates you
better change something. I went through all of the dependencies and
certainly none are written to expect two different results in IE8.
The alternative to causing such instability -- and which Dojo has seemed
to favor here -- is to not fix the bugs.

There's not a chance in hell that fixing the bugs I am referring to
would cause instability. In fact, I rewrote virtually every module
and add-on and demonstrated that all of the unit tests still passed.
Hard to argue with that. Yet somehow they managed.
Of course the problem with that is that everything is broken and as you
pointed out, broken differently across different browsers, rendering
mode, etc.
Right.


An low level abstraction that is fundamentally broken is a serious problem.

Yes, and for them it remains a problem to this day. That indicates
that nobody on that project has a clue what they are doing. They
can't even fix simple problems when handed the solutions on a silver
platter (see also jQuery).
Well, if it is coming at premium cost, there will be those who think
that it must be better.

Yes, snob appeal. But I think it is the graphics that are the biggest
draw. Of course, choosing a framework based on pretty widgets is like
choosing a car based on its radio.
[...]


That sounds like an optimistic appraisal of ExtJS, but Sencha Touch
does nothing of the sort.  It "compiles" nothing and certainly won't
work with XML documents.

Ext-JS -- not Sencha -- dynamically create functions that they reuse.

I know.
This is what they mean by "compiled". that doesn't apply to Sencha, but
just an FYI about what they mean by "compile".

I've seen it elsewhere as well.
[...]


That's not right.  For one, a checked attribute cannot be
"true" (except in an invalid document) and the :checked pseudo queries
the *property* so as to take user input into account.  Fortunately, I
think that's what they all do anyway; but unfortunately, they do the
same thing when querying the CHECKED attribute.  In my experience,
most of the participants in these projects don't know the difference.

Not all, and there are some that check attributes. NWMatcher is
cognizant of that, at least.

Yes, that thing works better than most of the "majors". Certainly
mine does too. Perhaps Dojo's will some day too as one of their
owners informed me long after his contributors had refused to
implement my recommendations that they were sniffing around my
attributes primer (a la John Resig). I had to remind him that it was
copyrighted. I'll be keeping my eye on them too. ;)
[...]


Yes, using these things to query by style values is even less
predictable than querying by attribute values.

It is.

The selector engine can be accessed from both
Ext.Element.selectorFunction and Ext.query. These are core abstractions
in the library and are accessed from two core parts of the library, both
of which express a package interdependency.

A selector engine that offers no deliberate syntax extensions is safer,
because it does not have as much deviation from the spec.

Any library that uses custom selectors, selectors that match attributes,
and anything that uses native-first dual approach cannot be easily
fixed. Continuing to use such library either changed or unchanged would
be unsafe.

Where does this "native-first dual approach" term come from? I know
what you mean, but I've never heard it called that.
Any library that uses a broken query selector at the core is just as
broken as its query engine.

Of course. And Dojo uses theirs incessantly. That's why virtually
every "module" in their core requires dojo.query. How ominous is
that?
Fixing the bugs causes instability. Problems
are not limited to queries, however.

The fixes I recommended would not have destabilized anything. They
would have simply fixed the inconsistencies, which were not results
that were expected by the rest of the "modules".
When changes to low-level abstractions propagate to higher level
abstractions the result is instability.

Not in the case I'm speaking of. The result would have been exactly
the opposite (as was demonstrated in my branch of the code).
Each bug in Ext-JS's selector engine necessarily propagates to a higher
level. When the selector engine's behavior is changed, that change is
propagated to all of the higher level dependencies. Such behavioral
changes cause instability. The alternative to causing such changes is to
not fix the bugs.

I haven't bothered tracking down all of their problems as nobody has
offered me any money to do so. :)
Buyer Beware.
The alternative for the end user is to not use include such things on
the page. As I have always advised for the developer who is considering
using a js library: Carefully review the source code of any js library
before using it.

And in the case of a GP library, consider why in the hell you would
want such a thing in the first place.
<https://groups.google.com/group/comp.lang.javascript/msg/c23d62071aad...>





That's correct.

var a = Ext.query("{visibility=inherit}");

The result of that in Ext shows that it does not work consistently
either, and a.length will be 0, depending on the browser. This is due to
the fact that it relies on Ext.Dom.getStyle, which, like most everything
in Ext-JS, is very broken.

But they do have some nice graphics. :)
If it had simply handed queries off to `querySelectorAll`, it would not
have created as many problems.

Yes, I forgot about their inexplicable preprocessing.
Extra effort was required to split on "," and create a loop, adding
duplicates to the returned result.

Clearly tacked on my author(s) who had no idea what they were doing (a
common theme with these things). Who knows what they were thinking as
there are no explanatory comments.
So while they do use querySelectorAll, they go to a lot of extra effort
to complicate it and create problems. Why they expended this extra
effort, I cannot say.

Only they can and they haven't. I suspect they will quietly remove
that code some time in the near future.
The code with comments being blatantly false could be attributed to haste..

For such a Frankenstein-like effort it probably is. Much of it sounds
like it is describing ExtJS.
You reviewed Ext.Dom.getStyle and, as you pointed out,
`hasRightMarginBug` is completely missing for the script.

Haste makes waste. :)
"hasRightMarginBug" in Ext.platform

false

It seems they forgot to include that property, though continue to
reference it. Since the resolution results in undefined and since
undefined evaluates to false, any code that uses that identifier in a
boolean context is completely useless and dead code.

In a way, that describes the entire script. I can't think of one
thing they did right. And there's so much blatantly wrong that it
might as well be rewritten from scratch.
And so all of the:

| if (Ext.platform.hasRightMarginBug && marginRightRe.test(prop) && out
| != '0px') {
|     display = this.getStyle('display');
|     el.style.display = 'inline-block';
|     result = view.getComputedStyle(el, '');
|     el.style.display = display;
| }

is dead code and will never be evaluated.

Yes, dead weight.
It's neither a class nor a singleton.
All JS properties are public.
Oh God.  As usual, these types of projects get ten steps ahead of
themselves.  I mean, it's 2010 and their basic queries are still
broken.  What's the point of piling all of this other nonsense on top?
[snip more delusions]

Although library author is free to make any design decision he chooses,
if the design decisions violate the CSS specifications and drafts (and
these do), then the code cannot honestly be said to be CSS3 compliant.

There's very little CSS3 in Sencha, despite the disingenuous ad
campaign. Not much HTML5 either. Who knew marketers lied? :)
Ext-JS claims "DomQuery supports most of the CSS3 selectors spec, along
with some custom selectors and basic XPath". Whether Ext supports more
than half of CSS3 selectors depends on the browser and the claim of
"basic XPath" support is false (possibly outdated documentation from
previous jQuery copying).
Probably.
|
| DomQuery
| selectNumber( String selector, [Node root], Number defaultValue ) :
| Number
| Selects the value of a node, parsing integers and floats. Returns the
| defaultValue, or 0 if none is specified.
| Selects the value of a node, parsing integers and floats. Returns the
| defaultValue, or 0 if none is specified.
| Parameters:
|
| * selector : String
| The selector/xpath query
| * root : Node
| (optional) The start of the query (defaults to document).
| * defaultValue : Number
|
| Returns:
|
| * Number
|
| DomQuery
| selectValue( String selector, [Node root], String defaultValue ) :
| String
| Selects the value of a node, optionally replacing null with the
| defaultValue.
| Selects the value of a node, optionally replacing null with the
| defaultValue.
| Parameters:
|
| * selector : String
| The selector/xpath query
| * root : Node
| (optional) The start of the query (defaults to document).
| * defaultValue : String
|
| Returns:  String
|
| DomQuery
The `selectValue` and `selectNumber` methods are missing altogether from
Sencha.
There's a lot of that going on.  They were clearly pressed for time.

Seems so. Yet another framework rushed to market, marketed heavily,
using fancy demos with nice images.

I can't think of one of those that has really made an impact on the
Web though. Hopefully this will be just one more whale on the beach.
The difference between marketing and engineering seems to not very well
perceived.

If at all. The first question on the mind of Web developers seems to
be about popularity. They seem to think that popularity implies
continuous improvement and easy support, despite overwhelming evidence
to the contrary (see jQuery).
Looking at demos is much more accessible than being able to make
assessments of front end code quality.

Yes, by a long shot. And once they fall in love with the demos, most
developers don't want to hear about the bad code, compatibility
issues, lack of competent support, etc. They want something they can
copy and paste and ship today (and never mind the ramifications for
their clients).
The number of individuals who look at the demos is going to be larger
than the number of individuals who review the code. This is not surprising.

Yes. What is surprising is that anyone would listen to "experts" who
advocate scripts based on pretty graphics and snazzy demos.
What is surprising is that prior to the recent angel investment into
Sencha, they did not a few qualified individuals to do code review on
it.

The Ext people think they are qualified, though that misconception has
likely been shaken at this point (unless they are locked up in sound-
proof booths with blinders on).
This would not have been much investment and could have helped avoid
such an amazing waste of money[1].

Yes. It's a shame to see people throwing good money after bad.
 From the perspective of the investor who does not have any idea of the
code quality, he could employ two highly qualified individuals for a
maximum of one week each to review and assess the code at a cost under
10,000 USD.

Hell, I did it for free. Well, not really. I just touched on the
highlights here. I charged for the full analysis. Some people
realize that spending a little money to avoid wasting a lot makes good
business sense. It didn't take me a week and I didn't charge anywhere
near $5,000. But I could definitely write a similar (and much better)
framework in that neighborhood (and did so for one client about a year
back).
In reality, it is not hard to look at the code and find a
mistake at line 1:

   window.undefined = window.undefined;

Yeah, that was a bad omen.
- and continue to find a very high defect rate and significantly bad
defects that we have covered and other glaring errors and design
mistakes that were covered by RobG[2].

No, not hard at all. So you have to wonder about the *best*
developers they have on the project and what the hell they are doing
all day.
Having volunteered so much free time over the years to spread knowledge
of web development, it seems that too few care about the code.

Oh, I bet somebody from Sencha is taking notes. The question is
whether they have anyone on the payroll who can interpret them in a
timely fashion.
The financial losses from projects debilitated by bad code is real.

Bad code costs money.

Bad code hides bugs that might not surface immediately.

Tangled messy code can't be changed easily. The time involved to add a
new feature can be double, and then coming back to regression testing,
bugfixes for all of the change propagation.

Sure. Ask anyone unfortunate enough to be saddled with Dojo.
This can lead to losing customers from bugs and even project failure
(and I have swam from such sunken ships, having failed to inspire the
captain into smart choices).
It is not easy to measure how much money
was wasted by bad code. There is never a "good code" control group and
problems and debt compound.

Ext-JS is very buggy. It is awful code.

As improbably as it may seem. that's an understatement.
Any javascript developer who Ext-JS either has not read the source code
enough, is not capable of understanding the problems, or has read and
understood the problems but has not appreciated the consequences deeply.

Happens all the time.
The choice to use Ext-JS is a substantially irresponsible and uninformed
decision that puts quality and long-term success of his project at risk.

And the choice to use Sencha Touch is exponentially worse, which could
only be described as insane.
 
G

Garrett Smith

What I said is not based on any "mystical incantation" but on what the
author of Mozilla's rendering engine explains in this video:

"Faster HTML and CSS: Layout Engine Internals for Web Developers",
David Baron.

Obviously you too (I told Mark already) ought to see it in order to
learn the fundamentals of the inner workings of rendering engines, and
once you begin to see through the black box, you (and Mark) will be
able to stop thinking about it any more in terms of mystical
incantations.
That's not a standard and not any browser documentation. It does not
explain how to force a repaint. I find it painful to watch that man
speak. Is there particular citation that you would like to reference?
You can enter the text.
 
D

David Mark

That's not a standard and not any browser documentation. It does not
explain how to force a repaint. I find it painful to watch that man
speak. Is there particular citation that you would like to reference?
You can enter the text.

What he talks about is also partially present in these documents (by
same author):

<https://developer.mozilla.org/en/Notes_on_HTML_Reflow>
<https://developer.mozilla.org/en/Introduction_to_Layout_in_Mozilla>

I would also like to (once again) quote Dave Hyat of WebKit fame
(<www.stubbornella.org/content/2009/03/27/reflows-repaints-css-performa....>):

<quote>

[...]

element.style.width = ‘50px’;
var v = element.offsetWidth;
element.style.width = ‘55px’;
v = element.offsetWidth;

You just caused two reflows to happen, since asking for offsetWidth
forced the element to reflow in order to answer you question (because it
had a pending change to style).

Of course, if the element is absolutely positioned, the browser won't
have to re-flow the entire document. That's something else to keep in
mind.
This is the real performance bottleneck to be wary of. Browsers are
smart about avoiding reflows when they can, but if you create code that
forces a reflow in order to answer a question, then you can create
severe performance bottlenecks.

Yes and unnecessary repaints are even worse. Not just for
performance, but they can wreak havoc on aesthetics as well.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top