On Oct 29, 3:00 pm, Matt Kruse <m...@mattkruse.com> wrote:
> On Oct 29, 12:42 pm, David Mark <dmark.cins...@gmail.com> wrote:
>
> > Run it through JSLint.
>
> Which is about as useful as validating HTML. Great for academic
Invalid markup is certainly not useful.
> purposes, perhaps it will catch a few errors, etc.
In jQuery's case, virtually every line will have a problem (or
multiple problems.) That indicates a slap-dash effort.
> But in the end it doesn't matter if code passes analytics, just if it
It matters for the people who have to maintain it. And since you are
relying on these people, it matters to you.
> accomplishes the goal or not. My goal never includes "pass
> validation". Validation is merely a tool to reach my goal, when
> needed.
I don't know what that means. If you write invalid markup and messy
script, you invite problems.
>
> > Then search it for "userAgent."
>
> Browser sniffing is not encouraged, and in some cases in jQuery it is
> really unnecessary. There are cases where it is beneficial.
It is never beneficial.
> Rather than writing lengthy logic to solve for every possible case,
> you can write shorter logic to solve for a subset of cases you care
> about.
Which you could do without parsing the userAgent string.
> It's not ideal, but it is a strategy. The amount of browser sniffing
> in jQuery is minimal.
>
Hardly. It is woven into many important low-level functions. Here is
a particularly stupid snippet from the get/setAttribute wrapper called
attr:
} else if ( jQuery.browser.msie && name == "style" )
return jQuery.attr( elem.style, "cssText", value );
Do you have any idea how many agents jQuery will identify as IE? Do
you have any idea how trivial it is to properly feature detect IE's
broken get/setAttribute functionality?
Forget that for the moment, why is this function passing a style
object to itself? Its first parameter is supposed to be an element.
Later in the same function, it becomes apparent (that the author is
out of his mind.)
// IE elem.getAttribute passes even for style
else if ( elem.tagName ) {
....
// elem is actually elem.style ... set the style
} else {
There couldn't be a more critical function in the entire library and
it is pure gibberish. Even the comments are senseless. There are
several additional sniffs in this same function.
if ( jQuery.browser.msie && /href|src/.test(name) && !
jQuery.isXMLDoc(elem) )
return elem.getAttribute( name, 2 );
Just what sort of XML document runs script in IE? Certainly not an
XHTML document. Realize that this absurd line of code is evaluated
every time jQuery looks at an element's attribute.
Then there is this gem:
// Certain attributes only work when accessed via the old DOM 0 way
if ( fix[name] ) {
if ( value != undefined ) elem[fix[name]] = value;
return elem[fix[name]];
This demonstrates a stunning lack of understanding of attributes (and
IE's problems with them.) Where's the sniff (or feature detect) for
IE? This IE-specific workaround runs on everything.
Still in the same function:
else if ( value == undefined && jQuery.browser.msie &&
jQuery.nodeName(elem, "form") && (name == "action" || name ==
"method") )
return elem.getAttributeNode(name).nodeValue;
No comment for this magic spell, so there is no telling what it is
trying to do. One thing is certain. This code will run on lots of
non-IE agents.
It gets worse.
if ( value != undefined ) {
if ( name == "type" && jQuery.nodeName(elem,"input") &&
elem.parentNode )
throw "type property can't be changed";
elem.setAttribute( name, value );
}
Another example of confusing attributes with properties. This is also
an IE-specific workaround with no sniff (or feature detect.)
And just when you think you have seen every conceivable miscue (all in
a single function mind you.)
if ( name == "opacity" && jQuery.browser.msie ) {
if ( value != undefined ) {
// IE has trouble with opacity if it does not have layout
// Force it by setting the zoom level
elem.zoom = 1;
What in God's name do opacity (and other styles) have to do with
attributes?
That's enough of that function. Keep in mind that the code therein is
called constantly by jQuery. Unfortunately for those who rely on
jQuery, it is error-prone, confused, inefficient and convoluted. The
design (and documentation) is of such poor quality that it is an
assault on the senses of anyone unfortunate enough to glance at it.
And speaking of opacity. In the curCSS function:
if (prop == "opacity" && jQuery.browser.msie) {
ret = jQuery.attr(elem.style, "opacity");
return ret == "" ? "1" : ret;
}
So any agent that identifies as IE and will be re-routed to the attr
function, which has nothing to do with style, but does contain more
sniffing and some IE-specific DirectX twiddling, which will have no
(positive) effect on non-IE agents.
It would seem that querying style rules would be almost as critical to
querying attributes in a library like jQuery. Yet, in this same
function you find this gem:
// A helper method for determining if an element's values are broken
function color(a){
if ( !jQuery.browser.safari )
return false;
var ret = document.defaultView.getComputedStyle(a,null);
return !ret || ret.getPropertyValue("color") == "";
}
This is the author's idea of a feature detect for getComputedStyle.
Why Safari-like browsers are excluded is a mystery. After that
inauspicious start, it blunders into the defaultView, getComputedStyle
and getPropertyValue properties with the impunity of somebody who
hasn't got a clue as to what they are doing.
It goes on and on. From the clean function:
if ( jQuery.browser.msie ) { // String was a <table>, *may* have
spurious <tbody>
if ( !s.indexOf("<table") && s.indexOf("<tbody") < 0 )
tb = div.firstChild && div.firstChild.childNodes;
div *may* have a firstChild property.
>From the same function:
// IE can't serialize <link> and <script> tags normally
jQuery.browser.msie && [1, "div<div>", "</div>"]
You have to keep in mind while reading this stuff that
jQuery.browser.msie is meaningless on the Web. It isn't of much use
on an Intranet either, unless you use the same version and
configuration of IE forever.
>From merge:
// Also, we need to make sure that the correct elements are being
returned
// (IE returns comment nodes in a '*' query)
if ( jQuery.browser.msie ) {
for ( var i = 0; second[i]; i++ )
if ( second[i].nodeType != 8 )
first.push(second[i]);
} else
Same problem different function. What if some agent that doesn't
identify as IE has the same problem? Also note how hard it is to
follow with all of the missing brackets.
More madness:
var styleFloat = jQuery.browser.msie ? "styleFloat" : "cssFloat";
Obviously you should just check (or set) them both. What happens if
IE8 switches gears on this? And what of an IE-spoofing agent that
doesn't use "styleFloat?"
// Check to see if the W3C box model is being used
boxModel: !jQuery.browser.msie || document.compatMode == "CSS1Compat",
That could have far-reaching implications. A quick search found it in
an attempt to measure the viewport:
return this[0] == window ?
jQuery.browser.safari && self["inner" + name] || jQuery.boxModel &&
Math.max(document.documentElement["client" + name],
document.body["client" + name]) ||
document.body["client" + name] :
this[0] == document ?
Math.max( document.body["scroll" + name], document.body["offset" +
name] ) :
h == undefined ?( this.length ? jQuery.css( this[0], n ) : null ) :
this.css( n, h.constructor == String ? h : h + "px" );
I characterized this as a "million monkey" project earlier and I want
to take a moment to apologize to monkeys everywhere. I think even a
single monkey could write a better solution to this very common
problem. Certainly there are many better solutions floating around on
the Internet.
And boxmodel can also be observed in the positioning code:
// IE adds the HTML element's border, by default it is medium which is
2px
// IE 6 and IE 7 quirks mode the border width is overwritable by the
following css html { border: 0; }
// IE 7 standards mode, the border is always 2px
if ( msie ) {
var border = jQuery("html").css("borderWidth");
border = (border == "medium" || jQuery.boxModel &&
parseInt(version) >= 7) && 2 || border;
add( -border, -border );
}
There are so many misconceptions here it is hard to know where to
begin. Suffice to say that the clientLeft/Top properties hold the
needed information in IE.
In the same function:
// Mozilla and Safari > 2 does not include the border on offset
parents
// However Mozilla adds the border for table cells
if ( mozilla && /^t[d|h]$/i.test(parent.tagName) || !safari2 )
border( offsetParent );
Apparently, in the jQuery universe there is only Opera, Mozilla,
Safari and IE. IE never gets here. Opera (and Safari <= 2 if you
believe the comments) adds borders when it shouldn't. So this logic
excludes everything the author has ever heard of that isn't Opera.
Speaking of Mozilla. Does this look like a good indication of Mozilla-
based browsers?
mozilla: /mozilla/.test(userAgent) && !/(compatible|
webkit)/.test(userAgent)
Why not call that the everything-under-the-sun property?
Getting back to border issue, in the mozilla-and-newer-Safari-only
(and oddly named) border function:
add( jQuery.css(elem, "borderLeftWidth"), jQuery.css(elem,
"borderTopWidth") );
What an outrage. The author apparently never heard of clientLeft/Top.
Backing up to where boxModel was first spotted, this is deja vu:
styleFloat: jQuery.browser.msie ? "styleFloat" : "cssFloat",
Yes, this logic is repeated just three lines below the first instance.
Moving on. In the ready function:
if ( jQuery.browser.mozilla || jQuery.browser.opera )
document.removeEventListener( "DOMContentLoaded", jQuery.ready,
false );
So if it is virtually any agent, assume there is a document object (a
fair assumption) and assume that it has a removeEventListener method
(an outrageous assumption.) Why the event listener needs to be
removed at all is another interesting question. The comments
mentioned memory leaks.
Here is the flip-side of this in bindReady:
// If Mozilla is used
if ( jQuery.browser.mozilla || jQuery.browser.opera )
// Use the handy event callback
document.addEventListener( "DOMContentLoaded", jQuery.ready,
false );
So two of the four browsers that the author knows of are known to
support DOMContentLoaded. Of course, it wouldn't hurt to add this
listener for everything. Come to think of it, he did (unknowingly)
add it for virtually everything.
You've got to love the comments. "Use the handy event callback" may
be the least informative one yet. Here's another interesting one from
makeArray:
// Need to use typeof to fight Safari childNodes crashes
if ( typeof a != "array" )
for ( var i = 0, al = a.length; i < al; i++ )
r.push( a[i] );
else
r = a.slice( 0 );
And why would you pass an array to a "makeArray" function anyway?
This reminds me of the function test code, which was blistered in
another recent "jQuery is a joke" thread.
Enough is enough. If you use jQuery after reading this, you are
deserve everything you get.
> > Then look at the logic that tests for a function.
>
> It may not be perfect, but have you ever come across a real-world case
> where it has failed for you?
>
> Me neither.
Asked and answered? I still want to know what reak-world you are
from.
>
> > How is it beneficial to swap one's own terrible code for the terrible
> > code of another. Is it easier to debug somebody else's code?
>
> jQuery's code is not terrible. It is a substantial improvement over
> most javascript code written by average developers. In my experience.
>
Ten years, according to a previous post, and you haven't learned a
thing. And who cares how it stacks up to "average developers?" If
you take an average JavaScript developer and give them this mess to
play with, are you really empowering them to write competent
applications?
I didn't think so either.
> > > There is a minified download option. Check it out.
> > Isn't that what I said? Running it through a minifier will lose about
> > 30K. I just tried it here and my estimation was almost exactly right.
>
> The packed version is 26kb. Plenty small.
Really? Define packed. Minified it is roughly 50K. GZIP doesn't
enter into it (unless you can't comprehend why it is silly to compare
file sizes after compression.) How small would a 20K library be after
compression? Regardless, you shouldn't manually compress JavaScript
files.
>
> > > > Having recently looked over the code, I can tell you it is poorly
> > > > written and full of mistakes.
> > > Without any examples or real critiques to back up that broad
> > > statement, it's worthless.
> > Try searching this very newsgroup for jQuery. You will find lots of
> > examples.
>
> But why should I look up past examples? You said you recently looked
> over the code and found that it was poorly written and full of
> mistakes.
Sure did.
> Surely you could provide some examples from your recent investigation?
Sure could.
>
> > > I've been writing javascript for over 10 years, and I've seen poorly
> > Lots of people can make that claim. How many of them are competent to
> > script browsers?
>
> I'm not sure "lots of people can make that claim". I consider myself
> to be very knowledgeable about Javascript development, and I disagree
> with your conclusions. Surely not everyone who disagrees with you is
> categorically an amateur?
What you consider yourself to be is hardly relevant. If you use and
recommend jQuery, then you are worse than an amateur. You are doing a
disservice to anyone who is unfortunate enough to use your creations
or listen to your advice.
>
> > > written code. jQuery is not poorly written. Nor is it "full of
> > > mistakes".
> > Then despite your vast experience with JavaScript, you still don't get
> > it.
>
> What don't I get? You are not providing any actual arguments. You
You don't get JavaScript, browser scripting, etc.
> might as well just say "You're stupid!" and stick your tongue out.
>
If you use or advocate jQuery after today, you are stupid.
> Further, have you considered that perhaps it is you who just doesn't
> get it?
I've looked at that. I don't think so.
>
> > > Would you also throw out the Wikipedia as "junk" because you find an
> > > article with technical errors?
> > That is an odd comparison.
>
> Perhaps. The point is, just because you notice a few flaws in
> something does not mean it is worthless. It merely means it has flaws.
A few flaws?!
> Which means it was probably developed by humans. If your goal is
> perfection, you'll never find it.
>
Finding a library was never my goal. Regardless, there is a big
difference between competent and perfect.
> > > My real-world experience differs from your hypothesis. I can measure
> > > the _huge_ benefits of using jQuery in real dollars, and it is
> > > significant.
> > And how would you quantify the benefits of "using jQuery" in dollars?
>
> #1:
> (Previous time to develop functionality) - (current time to develop
> similar functionality) = Time Savings
> Time Savings * Pay Rate = Money Saved
Oversimplification.
>
> #2:
> (Number of JS bugs before) - (Number of JS bugs now) = Bug Savings
> (Bug Savings) * (Avg Time to Fix JS Bugs) * Pay Rate = Money Saved
>
You've got lots of bugs and future maintenance issues. Perhaps you
didn't know about a lot of them before today. And if you can't write
relatively bug-free code without jQuery (God knows you can't with it),
then perhaps you should consider another line of work.
> Consider the effects of introducing jquery to a large development
> team:
[snip considerations]
>
> Now, how are you arguing that using jquery is not a huge benefit?
>
I didn't read the considerations. I am tired of hearing about
jQuery. It sucks. Case closed.
> You would recommend that we stop using it and start coding from
> scratch?
Why do library-advocates invariably see just those two choices? Do
whatever you want.
>
> > > I'd love to hear about your experience with jQuery and the maintenance
> > Having read the script, I concluded it was worthless. Therefore, I do
> > not use it.
>
> Then how would you know anything about an increase in maintenance
> caused by using jQuery?
You don't have to be psychic to see what lies ahead for your team.
> Can you quote the experience of anyone else who has used it and found
> it to be a maintenance problem?
I really don't talk to jQuery users. They tend to babble on and on
about nothing.
> Or hell, can you quote anyone who has used it and found it to be a bad
> decision for any reason?
I don't think I need to quote anyone at this point.
> Do you have any real-world experience with it?
You are repeating yourself.
> If not, how do you possibly feel justified in criticizing it?
See above.