The jQuery Divide

VIInternet και Εφαρμογές Web

27 Σεπ 2011 (πριν από 5 χρόνια και 9 μήνες)

483 εμφανίσεις

Rebecca Murphey • JSConf.eu • 25.09.2010 @rmurphey • rebeccamurphey.com

The jQuery Divide
Rebecca Murphey • JSConf.eu • 25.09.2010
@rmurphey • rebeccamurphey.com
Wednesday, September 29, 2010
Wednesday, September 29, 2010
what this presentation covers
how jQuery’s popularity means newcomers
learn bad things
why I think this is worth talking about at
JSConf
what I think the larger JavaScript community
needs to do about it
Wednesday, September 29, 2010
We need you to
help us organize our
jQuery-based
application. It’s a
steaming pile of
unmaintainable
crap.
Wednesday, September 29, 2010
But we want to
keep using jQuery.
It’s just so easy!
And popular!
Wednesday, September 29, 2010
It’s almost guaranteed that the client will point
to jQuery’s popularity as a reason to keep using
it. It’s also a pretty fair bet what their code will
look like.
Wednesday, September 29, 2010

var
toggleHistItems

=
function (selTabId) {
console
.log
(
'Selected Tab ID: '

+
selTabId);
var curEl
=

$
(
'#'

+
selTabId);
var bSLTabSelected
=

$
(
'#slhis'
).is(
'[class=left selected]'
);

$
(
'#divNoRecordMsg'
).hide();

switch
(selTabId) {

case

'slhis'
:

$
(
'tr[class^=fk]'
).show();

$
(
'.cPriceRent'
).html(
'Foo/Bar'
);
rentalRateIsVisible(
true
);

$
(
'#historySortButton'
).show();

//curEl.addClass('left');

if
(
$
(
'#historySort1'
).is(
':visible'
)) {

if
(
$
(
'#fooLeaseHistory > tbody > tr[class^=fk]'
).
length

===

0
) {

if
(
!$
(
'#divAction1'
).is(
':visible'
)
&&

!$
(
'#divRSAction1'
).is(
':visible'
)) {

$
(
'#divNoRecordMsg'
).html(
'There is no history at this time'
).show();
}

$
(
'#historySortButton'
).hide();

$
(
'#fooLeaseHistory'
).slideUp();
}

else
{

$
(
'#fooLeaseHistory'
).slideDown();
}
}
else
{

if
(
$
(
'#listingDisplay > tbody > tr[class^=fk]'
).
length

===

0
) {

if
(
!$
(
'#divAction1'
).is(
':visible'
)
&&

!$
(
'#divRSAction1'
).is(
':visible'
)) {

$
(
'#divNoRecordMsg'
).html(
'There is no history at this time'
).show();
}

$
(
'#historySortButton'
).hide();

$
(
'#listingDisplay'
).slideUp();
}

else
{

$
(
'#listingDisplay'
).slideDown();
}
}

break
;

case

'shis'
:
rentalRateIsVisible(
false
);

$
(
'#historySortButton'
).show();

if
(bSLTabSelected) {

$
(
'.fkSale'
).fadeIn();

$
(
'.Thinger'
).fadeOut();
}
else
{

$
(
'.fkSale'
).show();

$
(
'.Thinger'
).hide();
}

$
(
'.cPriceRent'
).html(
'Price'
);

if
(
$
(
'#historySort1'
).is(
':visible'
)) {

if
(
$
(
'#fooLeaseHistory > tbody > .fkSale'
).
length

===

0
) {

if
(
!$
(
'#divAction1'
).is(
':visible'
)
&&

!$
(
'#divRSAction1'
).is(
':visible'
)) {

$
(
'#divNoRecordMsg'
).html(
'There is no Sale History at this time'
).show();
}

$
(
'#historySortButton'
).hide();

$
(
'#fooLeaseHistory'
).slideUp();
}

else
{

$
(
'#fooLeaseHistory'
).slideDown();
}
}

else
{

if
(
$
(
'#listingDisplay > tbody > .fkSale'
).
length

===

0
) {

if
(
!$
(
'#divAction1'
).is(
':visible'
)
&&

!$
(
'#divRSAction1'
).is(
':visible'
)) {

$
(
'#divNoRecordMsg'
).html(
'There is no history at this time'
).show();
}

$
(
'#historySortButton'
).hide();

$
(
'#listingDisplay'
).slideUp();
}

else
{

$
(
'#listingDisplay'
).slideDown();
}
}

break
;

case

'lhis'
:
rentalRateIsVisible(
true
);

$
(
'#historySortButton'
).show();

if
(bSLTabSelected) {

$
(
'.fkSale'
).fadeOut();

$
(
'.Thinger'
).fadeIn();
}
else
{

$
(
'.fkSale'
).hide();

$
(
'.Thinger'
).show();
}

$
(
'.cPriceRent'
).html(
'Rent'
);

if
(
$
(
'#historySort1'
).is(
':visible'
)) {

if
(
$
(
'#fooLeaseHistory > tbody > .Thinger'
).
length

===

0
) {

if
(
!$
(
'#divAction1'
).is(
':visible'
)) {

$
(
'#divNoRecordMsg'
).html(
'There is no other history at this time'
).show();
}

$
(
'#historySortButton'
).hide();

$
(
'#fooLeaseHistory'
).slideUp();
}

else
{

$
(
'#fooLeaseHistory'
).slideDown();
}
}

else
{

if
(
$
(
'#listingDisplay > tbody > .Thinger'
).
length

===

0
) {

if
(
!$
(
'#divAction1'
).is(
':visible'
)) {

$
(
'#divNoRecordMsg'
).html(
'There is no other history at this time'
).show();
}

$
(
'#historySortButton'
).hide();

$
(
'#listingDisplay'
).slideUp();
}

else
{

$
(
'#listingDisplay'
).slideDown();
}
}

break
;
}

//set current tab
curEl.addClass(
'selected'
);

$
(
'h3[class=history] a'
).each(function () {

if
(
$
(this).attr(
'id'
)
!==
curEl.attr(
'id'
)) {

$
(this).removeClass(
'selected'
);
}
});
};
Wednesday, September 29, 2010
Plus that way our
database guy can
still help us out
with the front end.
Wednesday, September 29, 2010
*headdesk*
Wednesday, September 29, 2010
“... it turns out that
if you have absolutely
no idea what you’re doing
in the language
you can still generally make things work
.”
Douglas Crockford, Yahoo!
http://developer.yahoo.com/yui/theater/video.php?v=crockonjs-2
Wednesday, September 29, 2010
the morals of the story
perceived popularity & perceived ease of use
factor into library choice (duh)
people who don’t know JS write non-trivial JS
apps whether we like it or not
there’s a demand for answers to app org
questions
the people seeking these answers aren’t
necessarily dumb, just untrained in JS
Wednesday, September 29, 2010
jQuery meant we didn’t have to understand
this ...
Wednesday, September 29, 2010
var xmlhttp;
if
(
window
.
XMLHttpRequest
) {
// code for IE7+, Firefox, Chrome, Opera, Safari
xmlhttp
=new
XMLHttpRequest();
}
else
{
// code for IE6, IE5
xmlhttp
=new
ActiveXObject(
"Microsoft.XMLHTTP"
);
}
xmlhttp.
open
(
"POST"
,
"ajax_test.asp"
,
true
);
xmlhttp.
setRequestHeader
(
"Content-type"
,
"application/x-www-
form-urlencoded"
);
xmlhttp.
send
(
"fname=Henry&lname=Ford"
);
xmlhttp
.
onreadystatechange

=
function() {

if
(xmlhttp.
readyState

==

4

&&
xmlhttp.
status

==

200
) {

document
.
getElementById
(
"myDiv"
).innerHTML
=

xmlhttp.
responseText
;
}
};
Wednesday, September 29, 2010
we could just write this ...
Wednesday, September 29, 2010
$
.post(

'ajax_test.php'
,
{ fname :
'Henry'
, lname :
'Ford'
},
function(resp) {
$
(
'#myDiv'
).html(resp); }
);
Wednesday, September 29, 2010
jQuery offers a really clear answer when we
need to build this ...
Wednesday, September 29, 2010
Wednesday, September 29, 2010
$
(
document
).ready(function() {

$
(
'#searchForm'
).
submit
(function(e) {
e.preventDefault();
var myVal
=

$
(this).
find
(
'input:first'
).val();

$
.ajax({
url :
'search.php'
,
data : { term : myVal },
dataType :
'json'
,

success
: function(resp) {
var tpl
=

'<li><h2>%title</h2><p>%desc</p></li>'
;

$
(
'#results'
).html(

$
.map(resp.results, function(r) {

return
tpl.
replace
(
'%title'
, r.
title
).
replace
(
'%desc'
, r.desc);
}).
join
(
''
);
);
}
});
});
});
Wednesday, September 29, 2010
... which is why we see this ...
Wednesday, September 29, 2010
Wednesday, September 29, 2010
Wednesday, September 29, 2010
But when it comes time to create this ...
Wednesday, September 29, 2010
Wednesday, September 29, 2010
... it can be hard for the average jQuery
developer to see how they might get from the
#rst version to the second without creating a
whole lot of spaghetti code.
Wednesday, September 29, 2010
It turns out jQuery’s
DOM-centric patterns

are a fairly terrible way
to think about
applications.
Wednesday, September 29, 2010
Applications require thinking in terms
of loosely coupled, DRYed out units of
functionality, designed to
work with each
other without depending on each other
.
Wednesday, September 29, 2010
require.def(
'views/Results'
, [], function() {

return
Class.extend({
itemTemplate :
'<li><h2>%title</h2><p>%desc</p></li>'
,

init
: function(el) {
this.el
=
el;

$
.subscribe(
'/search/results'
,
$
.proxy(this,
'_showResults'
));
},

_showResults
: function(results) {
var tpl
=
this.itemTemplate,
html
=

$
.map(results, function(r) {

return
tpl
.
replace
(
'%title'
, r.
title
)
.
replace
(
'%desc'
, r.desc);
}).
join
(
''
);
this.el.append(html);
}
});
});
Wednesday, September 29, 2010
require.def(
'views/Results'
, [], function() {

return
Class.extend({
itemTemplate :
'<li><h2>%title</h2><p>%desc</p></li>'
,

init
: function(el) {
this.el
=
el;

$
.subscribe(
'/search/results'
,
$
.proxy(this,
'_showResults'
));
},

_showResults
: function(results) {
var tpl
=
this.itemTemplate,
html
=

$
.map(results, function(r) {

return
tpl
.
replace
(
'%title'
, r.
title
)
.
replace
(
'%desc'
, r.desc);
}).
join
(
''
);
this.el.append(html);
}
});
});
omg wtf is this???
Wednesday, September 29, 2010
We shouldn’t scold; cartoon client man — and
the developers lured to JavaScript by jQuery —
don’t know what they don’t know.

Wednesday, September 29, 2010
Some people i’ve talked to think we or the
market should discourage these people from
writing code, but that ship has already sailed.
Wednesday, September 29, 2010
ey’re writing code whether we like it or not,
and it’s not good code.
Wednesday, September 29, 2010
is has actual effects on the perception of
JavaScript, and on our ability to do interesting
things with it.
Wednesday, September 29, 2010
In a nutshell, this is what these developers
need to learn:
Wednesday, September 29, 2010
jQuery
JavaScript
Wednesday, September 29, 2010
Companies need developers, and if bad ones
are all that’s available, they’ll hire them
anyway.
Wednesday, September 29, 2010
Wednesday, September 29, 2010
Aaron Newton from Cloudera wrote a post a
while back about how hard it is to #nd “badass”
JavaScript developers.
Wednesday, September 29, 2010
e productive reaction to a post like that isn’t
to feel superior because you’re a badass
JavaScript developer.
Wednesday, September 29, 2010
e productive reaction is to #gure out how to
#x it.
Wednesday, September 29, 2010
jQuery’s ease has brought us legions of
developers who think of an application like
this: disparate pieces with few organizing
principles; components that are fun but aren’t
made to work together.
Wednesday, September 29, 2010
We need to turn them into developers who think
of applications like this.
Wednesday, September 29, 2010
five things
to think about
Wednesday, September 29, 2010
popularity contests are stupid
#1
Wednesday, September 29, 2010
Making decisions based on this graph ...
Wednesday, September 29, 2010
Wednesday, September 29, 2010
... makes as much sense as making decisions
based on this graph ...
Wednesday, September 29, 2010
Wednesday, September 29, 2010
We have to be
intellectually honest when we
discuss library pros & cons
— and vigorous
in correcting those who are not.
http://xpandapopx.deviantart.com/art/The-Prideful-Hypocrite-68848153
Wednesday, September 29, 2010
#2
choose tools, not APIs
Wednesday, September 29, 2010
// YUI3
var parent
=
Y.Node.create(
'<div/>'
),
child
=
Y.Node.create(
'<p>foo</p>'
);

child.on(
'click'
, fn);
parent.
appendChild
(child);
// Dojo
var parent
=
dojo.create(
'div'
),
child
=
dojo.create(
'p'
, { innerHTML :
'foo'
});

dojo.connect(child,
'click'
, fn);
dojo.place(child, parent);
// jQuery
var parent
=

$
(
'<div/>'
);
$
(
'<p>foo</p>'
)
.
click
(fn)
.appendTo(parent);
Wednesday, September 29, 2010
$
(
document
).ready(function() {

$
(
'#searchForm'
).
submit
(function(e) {
e.preventDefault();
var myVal
=

$
(this).
find
(
'input:first'
).val();

$
.ajax({
url :
'search.php'
,
data : { term : myVal },
dataType :
'json'
,

success
: function(resp) {
var tpl
=

'<li><h2>%title</h2><p>%desc</p></li>'
;

$
(
'#results'
).html(

$
.map(resp.results, function(r) {

return
tpl.
replace
(
'%title'
, r.
title
).
replace
(
'%desc'
, r.desc);
}).
join
(
''
);
);
}
});
});
});
Wednesday, September 29, 2010
(function(d,
$
) {
d.ready(function() {
d.connect(
'searchForm'
,
'submit'
, function(e) {
e.preventDefault();
var myVal
=

$
(
'input'
, this)[
0
].
value
;
d.xhrGet({
url :
'search.php'
,
content : { term : myVal },
handleAs :
'json'
,

load
: function(resp) {
var tpl
=

'<li><h2>%title</h2><p>%desc</p></li>'
;
d.byId(
'results'
).innerHTML
=
d.map(resp.results, function(r) {

return
tpl.
replace
(
'%title'
, r.
title
).
replace
(
'%desc'
, r.desc);
}).
join
(
''
);
}
})
});
});
})(dojo, dojo.query);
Wednesday, September 29, 2010
understanding the problem
is key to determining the solution
#3
Wednesday, September 29, 2010
Decision-makers need help to make actual
decisions
... and understand their consequences.
Wednesday, September 29, 2010
understand the project
application vs. website?
team skills: dedicated F2E?
team size & turnover?
project lifecycle: long-term, evolving product?
service-oriented back-end?
Wednesday, September 29, 2010
assess the application’s needs
code & #le organization?
dependency management & build tools?
templating & templated widgets?
data abstractions & binding?
a11y, i18n & l10n?
Wednesday, September 29, 2010
then
and only then
, choose your tools
features that address the application’s needs?
active development?
active community?
documentation & resources?
institutional backing?
Wednesday, September 29, 2010
RTFM can’t be our go-to answer
#4
Wednesday, September 29, 2010
“[It’s] a difficult time to
learn
to be a JavaScript
ninja, or even a JavaScript street beggar.
Good
resources for getting beyond the very
basics are hard to !nd,
documentation is
sparse or wrong, and a snippet of code that
may have been viable last year is now an anti-
pattern.”
http://www.clientcide.com/deep-thoughts/why-its-a-good-idea-to-be-a-javascript-developer-and-what-it-takes-to-be-one/#comment-32703
Wednesday, September 29, 2010
sharing what we know
is as important as
making new things
#5
Wednesday, September 29, 2010
Wednesday, September 29, 2010
rebeccamurphey.com • blog.rebeccamurphey.com • @rmurphey
anks, in guilt-free alphabetical order, to: Tim Caswell, John Hann, Peter Higgins, Tom Hughes-
Croucher, Paul Irish, Brian LeRoux, Roger Raymond, Alex Sexton, Colin Snover, Adam Sontag, Chris
Williams, and to everyone who listened to me formulate my thoughts.
Wednesday, September 29, 2010