|
|
|
|
|
|
|
Encosia
|
| http://encosia.com |
| ASP.NET and AJAX code, ideas, and examples. |
|
|
|
|
|
|
|
|
|
Last Friday, the “final” two episodes of Mastering jQuery went live: Using Custom Events and Upgrading to jQuery 1.4. While we’ll almost certainly add another episode when jQuery 1.5 is released, we’ve covered what we set out to.
Weighing in at nearly six hours of video, we covered a wide range of content, and have had overwhelmingly positive feedback on the series. I hope you’ve enjoyed the episodes as much as we’ve enjoyed recording them.
I want to thank those of you who helped promote Mastering jQuery through Twitter, word of mouth, and other avenues. It became one of the most viewed series on TekPub, and that couldn’t have happened without your help and support.
Ask the Expert with Dave Ward
With Mastering jQuery wrapped up, we’ve begun a new series in a format that’s entirely different than anything else currently on TekPub.
In this new format, you’re the boss.
Instead of James and I dictating the agenda of this series, we’re going to let you suggest and vote on the topics that you’d most like to see covered. Each week or two, we’ll pick one of the highest voted topics and produce an entire episode covering it in detail.
The goal of this series is to cover specific, scenario-based “How Do I?” questions. For example, the first episode covers a question I‘ve been asked dozens of times: how to asynchronously update a server-generated image during an AJAX request. The idea is that these topics should be specific enough that we can create a concrete example and cover it in about 30-60 minutes.
Rock the Vote
Not only are you in charge of what topics we cover, but if one of your suggestions is selected then you’ll get free access to the entire series.
Before you start submitting topics, a few general guidelines:
- Avoid subjective or abstract topics. While some very good discussions fall under that umbrella, most of them won’t make very good video tutorials.
- Do suggest topics specific enough that we can build a concrete example to show you and cover the relevant parts of it in an hour or less.
- Bad: “How do I build a Facebook clone?”
- Good: “How do I implement the infinite scroll pattern?”
- Stay within the general vicinity of web development (i.e. HTML, CSS, JavaScript, ASP.NET, jQuery, and the like). If I had to do an episode on low-level database optimization, I can guarantee that you would be disappointed.
You can submit your topic suggestions and vote on existing ones at vote.tekpub.com. We’re looking forward to seeing what you come up with!
You've been reading Announcing my new TekPub series, where you call the shots, originally posted at Encosia. I hope you enjoyed it, and thanks for reading.
Related posts: - Mastering jQuery now available at TekPub
- I’m giving away 10 free months of TekPub this week
- Hear me talk jQuery and ASP.NET on the jQuery Podcast
 |
|
|
|
|
|
|
|
Last week, Ralph Whitbeck was kind enough to have me as a guest on episode #32 of the jQuery Podcast. We spoke about topics including:
- Research I’ve done on the public CDNs that host jQuery, and why it matters which one you choose
- Why you should never use a "latest version" reference to scripts on those public CDNs
- The drawbacks of always waiting on $(document).ready()
- My video tutorial series, Mastering jQuery
I really enjoyed talking with Ralph, and I think the episode turned out great. You can listen to it at: http://podcast.jquery.com/2010/08/27/episode-32-dave-ward/
You've been reading Hear me talk jQuery and ASP.NET on the jQuery Podcast, originally posted at Encosia. I hope you enjoyed it, and thanks for reading.
Related posts: - Hear me talk about jQuery on the Polymorphic Podcast
- Mastering jQuery now available at TekPub
- Alt.NET Podcast – jQuery in ASP.NET
 |
|
|
|
|
|
|
|
jQuery’s $(document).ready() event is something that you probably learned about in your earliest exposure to jQuery and then rarely thought about again. The way it abstracts away DOM timing issues is like a warm security blanket for code running in a variety of cold, harsh browser windows.
Between that comforting insurance and the fact that deferring everything until $(document).ready() will never break your code, it’s understandable not to give much thought to its necessity. Wrapping $(document).ready() around initialization code becomes more habit than conscious decision.
However, what if $(document).ready() is slowing you down? In this post, I’m going show you specific instances where postponing startup code until the document’s ready event slows perceived page load time, could leave your UI needlessly unresponsive, and even causes initialization code to run slower than necessary.
Example: live()
One of the most popular uses for jQuery’s live() is to maintain event handlers on elements that are dynamically created and destroyed over time. Instead of juggling traditional bind() handlers in response to those changes, live()’s event delegation allows you to declare handlers once up-front. Whether targeted elements exist at declaration time, or in the future, one live() handler will apply to them all.
Imagine that we have an application with several slideToggling sidebar blocks which may be dynamically added and removed while the user interacts with the page. You’ve probably seen live() used like this to simplify handling those future changes:
<html>
<head>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
<!-- The sidebar event delegation is not registered "here"... -->
$(document).ready(function () {
$('#Sidebar h3').live('click', function () {
$(this).next().slideToggle();
});
});
</script>
</head>
<body>
<div id="Sidebar">
<h3>Title 1</h3>
<p>Text 1</p>
<h3>Title 2</h3>
<p>Text 2</p>
</div>
</body>
<!-- ...but roughly down "here" -->
</html>
That usage is natural when you’re hedging against AJAX-driven changes in the future. The volatility that you’re concerned with won’t happen until after the page loads, so it’s intuitive to postpone worrying about them until after the document’s ready event.
However, what would happen if you treated your HTML document’s initial load process the same way as any other dynamic modifications?
<html>
<head>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
<!-- The event handler is wired up "here"; immediately -->
$('#Sidebar h3').live('click', function () {
$(this).next().slideToggle();
});
</script>
</head>
<body>
<div id="Sidebar">
<h3>Title 1</h3>
<!-- At this point, Title 1 is ready for action. -->
<p>Text 1</p>
<h3>Title 2</h3>
<!-- Ditto for Title 2 at this point -->
<p>Text 2</p>
</div>
</body>
</html>
Not only does that work just as well as postponing the live() declaration until the document’s ready event, but now the handlers are active during the page loading process. As the browser loads each <h3> element and adds it to the DOM, our click events are immediately ready to be handled.
Benefit: A more responsive UI
To see where the latter approach shines, imagine the page was very large and took several seconds to load, or that a script reference somewhere on the page was timing out. In scenarios like those, jQuery’s document ready event may not fire until considerably later than the targeted elements are visible to your users.
<html>
<head>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
<!-- The event handler is wired up "here"; immediately -->
$('#Sidebar h3').live('click', function () {
$(this).next().slideToggle();
});
<!-- This handler isn't active until... -->
$(document).ready(function() {
$('#Sidebar p').live('click', function() {
// Important magic goes here.
});
});
</script>
</head>
<body>
<div id="Sidebar">
<h3>Title 1</h3>
<p>Text 1</p>
</div>
<script src="http://twitter.com/fail-whale.js"></script>
<!-- ...way down here, *after* the script references times out. -->
</body>
</html>
Why hold live() back until the document is ready? It doesn’t matter if the selector matches any elements initially; they will immediately become active as they are rendered and appear on the page.
Benefit: Improved performance
A common criticism of using live() for event delegation is that it requires you to perform an initial selection of all of the elements that it targets. Since event delegation doesn’t require any initial setup on each individual element, this pre-selection is a wasteful performance drag when there are dozens or hundreds of elements targeted.
However, if you register your live() handlers before those elements exist on the page, there is no performance penalty whatsoever. The event delegation can be registered very quickly, yet still works exactly the same as if you had waited until the ready event.
<html>
<head>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
<!-- Fast. Runs before any of the TRs exist. -->
$('#MyTable tr').live('click', function () {
$(this).toggleClass('highlight');
});
<!-- Slow. Doesn't run until the table is rendered. -->
$(document).ready(function() {
$('#MyTable tr').live('click', function () {
$(this).toggleClass('highlight');
});
});
</script>
</head>
<body>
<table>
<!-- Hundreds or thousands of rows here -->
</table>
</body>
</html>
Example: $.ajax()
Another situation where $(document).ready() may be holding you back is when you make an AJAX request immediately as a page is loading. Displaying recent Twitter updates is a common example of that:
<html>
<head>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
$(document).ready(function() {
<!-- $.getJSON() request to retrieve Twitter updates. -->
});
</script>
</head>
<body>
<!-- A typically large page here -->
</body>
<!-- The Twitter request doesn't *begin* until here. -->
</html>
Even though the $.getJSON() snippet is located at the beginning of the page, it isn’t executed until the entire page has loaded and the ready event has fired. Why wait until the page is loaded in order to begin the AJAX request?
<html>
<head>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
<!-- $.getJSON() request to retrieve Twitter updates. -->
<!-- The request begins immediately. -->
</script>
</head>
<body>
<!-- A typically large page here -->
</body>
</html>
This is a nice improvement even when you’re making a request to a local endpoint, but is even more beneficial here because third-party requests circumvent the browser’s per-domain request limit. That third-party request to Twitter runs in parallel with the rest of the page’s normal loading timeline.
Better yet, since the dynamic script element injection used in a JSONP request is asynchronous, there’s no drawback to initiating the request early. Even if Twitter is slow or down (imagine that), the request won’t drag the page down.
Benefit: Performance
To show you a visualization of how the previous two approaches differ, I used my own site as a guinea pig. First, I wrapped a $.getJSON() request to Twitter in $(document).ready() and placed it in the <head> of my site template.
This is how the site loads in that configuration, taken from Firebug’s Net tab:

Now, here’s the same $.getJSON() request, located in the same position in the <head> of the page, but without the $(document).ready() wrapper:

We just pulled a bit of performance right out of thin air. This isn’t simply perceived performance, which is nice enough, but a truly faster overall load time.
Note: You might notice that the ready event came later in the second example and be concerned that it was due to the early $.getJSON() request. It wasn’t. If you look closely, a blocking <script> reference to one of the page’s local scripts took unusually long in the second run, which pushed everything back about 700ms longer than usual.
Conclusion
I think the preceding examples are compelling, but I’m also not suggesting that this is appropriate in every case. Often, it’s best to move every bit of JavaScript to the bottom of your pages (e.g. a public-facing, non-application site like this one). When your scripts are located at the bottom of the page, it doesn’t matter whether you use $(document).ready() or not; everything is effectively running when the document ready event fires anyway.
However, when you’re building the type of script-heavy “application” that behooves your placing script references in the document’s <head>, keeping these ideas in mind can have a tangible impact on the performance of your application.
You've been reading Don’t let jQuery’s $(document).ready() slow you down, originally posted at Encosia. I hope you enjoyed it, and thanks for reading.
Related posts: - $(document).ready() and pageLoad() are not the same!
- 3 reasons why you should let Google host jQuery for you
- Easily build powerful client-side AJAX paging, using jQuery
 |
|
|
|
|
|
|
|
For several years now, I have been consistently impressed with how Microsoft’s developer division gathers feedback and proactively responds. Nearly every time that I’ve participated in a survey or otherwise provided feedback (solicited or not), someone has followed up with me about my specific concerns. In my experience with how other large companies gather feedback, that’s not common.
So, when I answered a recent survey about ASP.NET development in Visual Studio 2010, I wasn’t surprised when I received a follow-up email from a friendly fellow at Microsoft named Xinyang. In the optional comments section, I had mentioned my concern that CSS and JavaScript editing are becoming second class citizens in Visual Studio. In response, Xinyang asked me to provide more detail on that comment.
As I composed a lengthy email reply to him, it occurred to me that a post here would be a much more effective way to refine my feedback and potentially gather more responses from you at the same time.
So, here are a few of my ideas for improving client-side development in Visual Studio 2010, separated into CSS and JavaScript specific feedback. Xinyang and some of his colleagues will be reading this and your comments, so if you agree, disagree, or have other ideas yourself, be sure to chime in.
CSS
Visual Studio 2010’s CSS editing experience is workable, but that’s about the best I can say about it. There aren’t any bugs that I’ve encountered, per se, but it’s Spartan.
I think a few simple features could improve the CSS editing experience dramatically.
Working with color
Displaying color swatches along with CSS color codes is a handy feature that’s been filtering into development editors lately. Whether the swatch is displayed in that line’s margin or elsewhere, having a visual representation of RGB and hex color codes is helpful.
This is how JetBrains’ WebStorm handles that, for example:

Taking that a step further, it would be great if clicking those color swatches would open a color picker. I’ve been using the Firepicker addon to Firebug to achieve similar functionality in-browser for several months now. Try it; you won’t know how you lived without it before.
I haven’t had an opportunity to try it myself yet, but DevExpress’s CodeRush apparently includes an implementation of both those features in the meantime.
Property ordering
Alphabetically sorting CSS properties is considered a best practice by many (including myself), but it’s tedious to manually rearrange properties that fall out of order. It would be great if formatting the document could automate that task, so that this:
.myCssClass {
margin: 0 auto;
border: 1px solid #000;
width: 960px;
height: 42px;
}
Would become this after formatting:
.myCssClass {
border: 1px solid #000;
height: 42px;
margin: 0 auto;
width: 960px;
}
Condensing properties
Similar to property ordering, I’d like to see the editor automatically condense overly verbose style definitions. For example, this:
div {
border: 1px 1px 1px 1px solid #000;
margin-top: 0;
margin-left: auto;
margin-right: auto;
margin-bottom: 0;
}
Could be condensed, without changing its effect, to this:
div {
border: 1px solid #000;
margin: 0 auto;
}
Respect existing formatting
One thing that nearly CSS editor I’ve used has failed at is respecting existing formatting choices. For example, if a style only includes a single attribute, I usually prefer to use the most compact syntax:
The one-liner is just as readable as the three or four line alternatives, but takes up much less space on the page.
However, once there are several attributes, I prefer to expand the declaration:
a {
color: #333;
display: inline;
text-decoration: underline;
}
Currently, if I’ve mixed those two formats in the same file, I must avoid allowing the document to be formatting, because it will homogenize the formatting.
Even better would be if I could set a threshold. Styles with less attributes than the threshold would use “compact” formatting and the rest would use “semi-expanded” formatting.
Respect hierarchical indenting
In the same vein as respecting my formatting choices, it would be great if formatting a CSS document would avoid discarding my indentation choices. Indenting CSS declarations based on their “depth” is a great way to improve the readability of CSS, but is unfortunately something that most CSS editors don’t play nice with.
For example, if I have this CSS:
#Container { … }
#Container a { … }
#Container a span { … }
#Container a strong { … }
Visual Studio will flatten it any time the document (or that section) is formatted:
#Container { … }
#Container a { … }
#Container a span { … }
#Container a strong { … }
It would be a great relief if the editor would respect my indentation choices. Currently, my CSS editing experience is overshadowed by the fear of an accidental Format Document.
This would be especially important if alphabetizing properties were added to the automatic formatting. I would ideally like to apply that feature to an entire document or large selection, but couldn’t if it would flatten the document’s indenting at the same time.
Automate hierarchical indenting
While we’re at it, respecting manual indent levels would be nice, but it would be even better if the editor could infer and automate that indenting. For example, let me throw this CSS at it:
#Content { … }
#Content a { … }
#Content a span { … }
#Content blockquote { … }
And have it format it like this:
#Content { … }
#Content a { … }
#Content a span { … }
#Content blockquote { … }
I don’t know how feasible it is to implement that as a general solution, but it would be a phenomenal addition if possible.
JavaScript
These days, I spend at least as much time editing JavaScript as I do editing C#. As the Microsoft <3 jQuery story continues to unfold, I think (hope!) that this will also be the case for an increasing number of other developers using Visual Studio.
However, the JavaScript editor needs some work before it pays proper respect to the growing importance of JavaScript in modern ASP.NET development.
Automatic outlining
If you aren’t familiar with the term, this MSDN page describes outlining in Visual Studio. Automatic outlining is the experience you’re used to in most of the files that Visual Studio edits, like C# and VB.NET, where conditional and structural blocks automatically have outlining applied to them when you open a file.
In Visual Studio 2008, editing a JavaScript file looked like this:

It didn’t have automatic JavaScript outlining, but the hard left margin made the lack of outlines less noticeable.
Here’s the same file in Visual Studio 2010:

Notice how the lack of outlining translates to a lack of a hard left margin in Visual Studio 2010. That’s tough to deal with. At a glance, my code is lost at sea, visually unmoored from the line beginnings at the left.
Looking at how other JavaScript editors display that same code puts this deficiency in stark contrast. Here’s how Notepad++ handles it, for example:

Beyond the obvious outlining in the left margin, I really like how it also drops vertical guidelines directly below each logical block. In fact, Notepad++ strikes an almost perfect balance between visual utility and distracting over-embellishment.
For another perspective, here’s the same code in JetBrains’ WebStorm:

WebStorm’s default may take this all a bit too far by outlining, highlighting, and otherwise accentuating so many different elements of the code. Emphasizing so much of the code diminishes the effect of each individual display hint.
On the bright side, there’s a Visual Studio 2010 extension that adds basic outlining to JavaScript files: JSEnhancements. I’ve been using it for a couple weeks now and it does make a big difference.
Something this basic really should be built-in though. Too many developers will needlessly struggle with this deficiency and never know about the extension (or not be allowed to install it).
Object literal outlining
In addition to offering outlining for logical blocks of code, it might also be helpful to include outlining to condense JavaScript object literals. Common as they are in any jQuery work, support for automatically outlining them may prove useful.
Something like this:

I’m on the fence about the real-world utility of this one, but decided to throw it out there anyway. What do you think?
JavaScript code navigation
The lack of code navigation in and across JavaScript files leaves a lot of room for improvement. I’ve already spent enough time hitting CTRL-F in JavaScript files to last a lifetime.
Probably the most glaring omission is “Go To Definition”, but it’s also a shame that Visual Studio 2010’s fancy new “Navigate To” feature also overlooks JavaScript files.
There’s not a lot to say about this one. What’s missing should be obvious, and it’s a very painful omission for those of us working heavily on the client-side. Improvements will be welcomed.
Parenthesis spacing
Visual Studio 2010 introduced one new formatting behavior that I really don’t understand: a forced space between the function keyword and its opening parenthesis.
For example:
// This:
function foo() { … }
// Becomes this:
function foo () { … }
// This:
function() { … }
// Becomes this:
function () { … }
I tried in vain to manually fight against that automatic formatting at first, but eventually gave up. The automatic formatting was being invoked too frequently for me to keep up with it.
Until Visual Studio 2010 started formatting my code that way, I can’t remember having ever seen that style of spacing in JavaScript function declarations. Whatever the motivation for this change, the kicker is that the new behavior isn’t even optional.
Please fix.
Intellisense
I like the idea of JavaScript Intellisense to some extent. The jQuery VSDoc files are a good example of JavaScript code completion that really does offer enhanced discoverability and increased productivity.
However, I’m concerned that the editor is lacking basic features like code navigation because too much effort is being spent on the unattainable goal of perfect code completion in a dynamic language. I hope I’m wrong about that, but it bears mentioning.
As you get acclimated to JavaScript, Intellisense for your own code really isn’t necessary. It can be neat when it works, but fails often enough that you learn not to count on it. Worse, you eventually learn not to trust it.
That’s not so bad anyway. The JavaScript language is not large or complicated; in fact, Crockford boiled it down to the “Good Parts” in less than 150 pages. There is much less need for comprehensive Intellisense when working with a smaller language.
JavaScript Intellisense on external APIs is where Intellisense really shines. Trying to infer what “this” refers to in the anonymous function callback I just wrote? Not so much.
Your turn – Leave a comment with your feedback
People in the position to make these sort of suggestions a reality are reading this and I believe they’re eager to hear your feedback. If you’ve been using Visual Studio 2010 for ASP.NET development, this is a great time to provide constructive criticism and/or your ideas for improvements early enough to make it into 2010 SP1 or v.Next.
Update: When writing this, I assumed that any of these formatting features would be optional if implemented. Just a few more checkboxes in Options > Text Editor > CSS|JS > Formatting.
Considering one of my points in this post was that my paren-spacing cheese got moved without an option to fix it, I probably should have been more clear about that. So to be clear, any of these ideas should only be added as an optional formatting choice, not something that’s forced.
You've been reading Improving client-side development in Visual Studio, originally posted at Encosia. I hope you enjoyed it, and thanks for reading.
Related posts: - Using an iPhone with the Visual Studio development server
- Automatically minify and combine JavaScript in Visual Studio
- Use jQuery and ASP.NET AJAX to build a client side Repeater
 |
|
|
|
|
|
|
|
I recently encountered what appeared to be a cross-browser issue with jQuery, which was both surprising and frustrating. After all, eliminating those cross-browser inconsistencies is no small part of jQuery’s fundamental appeal.
After some investigation, the source of the trouble actually stemmed from an oversight on my part. I doubt that many of you will have to deal with exactly the same situation, but the lessons I learned may apply to cross-browser jQuery problems you encounter in the future.
Tables all the way down
It all started with a relatively simple HTML table template being rendered on the client-side via jTemplates. The rendered markup looked something like this:
<table>
<thead>
<th>Part Number</th>
<th>Description</th>
<th>Quantity</th>
</thead>
<tbody>
<tr>
<td>Item1</td>
<td>Item1 Description</td>
<td>4</td>
</tr>
<tr>
<td>Item2</td>
<td>Item2 Description</td>
<td>2</td>
</tr>
</tbody>
</table>
A series of these tables would be rendered in chronological order, one per invoice.
The bit of jQuery in question
Once those tables were rendered, the user often needed to trigger an action on the first row of the last table. The action itself isn’t relevant, but one important detail is that it blocked interaction with the rest of the page until its workflow was complete.
Glancing at the markup, the selector to accomplish that seemed simple enough:
$('table:last tr:first').triggerSomeAction();
Nice, simple, and it worked great. We tested it thoroughly, got user-approval, and I moved on to other features.
Unfortunately, that single line of jQuery would come back to haunt me later.
IE failed me? It’s always IE!
Originally, I was fortunate enough that all this application’s users were using recent versions of Firefox. Since all my development took place in Firefox too (you still can’t beat Firebug), the application received very little cross-browser testing.
Over time, the application became a victim of its own success. It worked so well that other departments began to adopt it too; departments with Internet Explorer users. All of the IE users were using IE8, so that wasn’t as bad as it could have been, but it brought an interesting cross-browser problem to my attention.
The problem was that the bit of code which called triggerSomeAction() on the first row of the last table wasn’t working right in IE. Worse yet, it was still locking the interface though. IE users were unable to complete that bit of the workflow and remained locked out of the invoices once that action had been triggered.
I cursed IE, out of habit, and went to work debugging the issue.
Nope, I had failed myself
Tracing through the code, it seemed like the selector was finding the <thead> row instead of the first row of the table body. That didn’t make much sense at first, but then I inspected the rendered markup side-by-side in both Firebug and IE’s developer tools:

See the difference?
Firefox had been rendering the table’s markup exactly as given, even though omitting a <thead>’s <tr> isn’t valid markup, but IE tried to fix my mistake by inserting the missing <tr>. In fact, this behavior isn’t unique to IE. Chrome and Safari both do the same thing that IE does with that particular malformation.
Because jQuery’s selectors act on the DOM itself, not the raw HTML that was originally fed to the browser, this “help” was changing the result of my jQuery selector. Selecting tr:first was actually returning the row of <th> elements in every browser other than Firefox.
I stopped cursing IE and began cursing myself.
The fix
The fix was simple enough. I changed the selector to be more precise:
$('table:last tbody tr:first').triggerSomeAction();
That fixed the immediate problem. Then, I corrected the template’s missing <tr> for good measure.
What I learned
Validating HTML has a reputation as something only obsessive purists do, but Validating you HTML is a useful tool. It’s lint for your HTML. I’m often lax about validating internal-only sites, but doing that would have helped me avoid this problem before it happened.
If a jQuery selector seems inconsistent across browsers, inspect the DOM in those browsers. It’s not safe to assume that every browser will interpret your markup as its written. Thankfully, most browsers now include tools suitable for doing so.
If you think you’ve “found a problem” with a mature library like jQuery, blame yourself first. I should have known better than to think there was a problem with jQuery in such a common scenario.
And you?
I hope that having watching my mistake unfold in slow-motion will help you if you run into a similar issue in the future. Even better, maybe it will help you avoid the problem in the first place!
Do you have a similar story? What are the cross-browser issues you’ve run into when using jQuery?
You've been reading Sometimes, even jQuery can’t save you from yourself, originally posted at Encosia. I hope you enjoyed it, and thanks for reading.
Related posts: - Use jQuery and ASP.NET AJAX to build a client side Repeater
- 11 keystrokes that made my jQuery selector run 10x faster
- A few thoughts on jQuery templating with jQuery.tmpl
 |
|
|
|
|
|
|
|
Developing iPhone-optimized portions of an ASP.NET website presents a challenge. More specifically, it’s testing your creations that can be difficult.
Apple’s iPhone emulator only runs on Macs and the Windows-based alternatives don’t emulate mobile Safari well. That leaves us using an actual device as the only high-fidelity option for testing. That’s not all bad; especially when it comes to a touch-driven interface, testing with the real thing is preferable.
Unfortunately, the ASP.NET Development Server bundled with Visual Studio is severely restricted when it comes to testing externally. In fact, it could hardly be more restrictive – it refuses all external connections, even if those connections originate from the same local subnet.
In this post, I’m going to show you one way I’ve found to circumvent that restriction, how to configure your iPhone to take advantage of that, and how to connect to the development server once those steps are completed.
Note: This post specifically describes configuring an iPhone, but the same approach will work for any mobile device that supports using an HTTP proxy.
Fooling the ASP.NET Development Server
The fundamental problem is that Visual Studio’s ASP.NET Development Server actively refuses external connections. That’s a logical precaution if you’re in the business of selling web server operating systems, but it adds unnecessary friction to the legitimate endeavor of testing with mobile devices.
The solution that I stumbled onto uses a tool that you may already have installed: Fiddler. If you aren’t familiar with Fiddler, this recording of Eric Lawrence’s session at MIX10 is a great way to learn a lot about Fiddler in relatively little time.
The feature that we’re specifically interested in is its HTTP proxy server. Unlike the ASP.NET Development Server, Fiddler does not restrict connections from external devices. Even better, routing an external device’s connections through Fiddler is misdirection enough to fool the development server into accepting them.
Checking Fiddler’s proxy port
With Fiddler installed, the first step is to determine which port it’s running the proxy server on. On fresh installs, the default setting is port 8888.
If you’ve had Fiddler installed a while, it doesn’t hurt to double check the setting. You can do that in Fiddler by navigating to Tools > Fiddler Options, and selecting the Connections tab:

While you have that dialog open, also verify that the three checkboxes circled above are checked.
Finding your IP address
The next step is to determine your machine’s IP address on the local network. A quick way to do that is running ipconfig at the command prompt.
To open a command prompt, press Win + R, type cmd in the field, and hit enter.

At the command prompt that opens, type ipconfig and hit enter.

What you’re looking for here is the IPv4 address for your machine’s primary network adapter. “Local Area Connection” is mine, so I need to use 192.168.1.119 to connect to my machine. A wireless connection is fine too, as long as it’s connected to the same access point that the iPhone is.
Find yours and make note of it for the next step.
Note: This must be an IP address that your iPhone can route to while connected via Wi-Fi. In most business and almost all residential networks, you won’t need to give this much thought. However, if you’re working within a more complex corporate network and can’t get your iPhone to connect to Fiddler’s proxy server, you may need help from a system administrator.
Configuring an iPhone to route through Fiddler
With your development machine’s IP address and Fiddler’s port number in hand, you’re ready to configure your iPhone to channel its network traffic through Fiddler’s proxy server.
To do that, open the settings app and tap the Wi-Fi option (below, left).
In the Wi-Fi Networks panel (above, right), you’ll see the wireless networks that your iPhone has detected in range. Tap the arrow at the right side of the Wi-Fi connection that you intend to use for testing.
At the very bottom of the panel that opens (left), find the HTTP Proxy setting and tap Manual (1) to enable the feature. In the fields that appear, enter your computer’s local IP address for the server (2), and the port that Fiddler is listening on for the… Port (3).
That’s it! Your iPhone is configured to route its traffic through an instance of Fiddler running on your development machine.
Starting the development server
Now that you have a conduit from your iPhone to the development server, it’s time to get the development server running by starting your site in Visual Studio. Anything that starts an instance of the development server will do (e.g. Start Without Debugging or View in Browser).
Make note of the URL displayed in your browser when Visual Studio displays your website. We’ll modify that slightly in the next step and use it to access the development server from Mobile Safari.
If the development server is already running, you can also determine its address by right-clicking its icon in the system tray and choosing “Show Details”. That will present you with a window that looks like this:

The “Root URL” address there is what you’ll need in the final step.
Accessing the development server from your device
Finally, we’re ready to start testing against the development server from the browser on a mobile device. The one minor issue remaining is that the exact URL advertised by the development server won’t work in this setup.
To make Fiddler happy, you need to append a trailing period to the hostname portion of the address. For instance, this “Root URL” advertised in the example above will not work without modification:
Wrong!
http://localhost:24833/WebSite1
To make it work, we simply need to append the trailing period to localhost:
http://localhost.:24833/WebSite1
That does look odd, but it works.
Fiddler also recognizes ipv4.fiddler as an alias for the localhost loopback, which is a little bit more intuitive. So, you could also access the same example with this address if you prefer:
http://ipv4.fiddler:24833/WebSite1
That’s it. You’re armed and ready to test with any external device on your local network now, so long as it supports routing its traffic through an HTTP proxy.
Conclusion
At first, this may seem like many steps and a lot of work. Don’t worry. Once you go through the motions a few times, you’ll find that it’s a breeze.
It’s especially smooth sailing in future repetitions, since your machine’s local IP probably won’t change often, and Fiddler’s proxy IP won’t change at all.
Of course, Fiddler isn’t the only utility that will work as an intermediary like this, but using Fiddler brings the great side-effect of providing HTTP traffic analysis while you’re testing. That added utility is welcome when you’re testing on a mobile device where the on-device development tools are basically nonexistent.
You've been reading Using an iPhone with the Visual Studio development server, originally posted at Encosia. I hope you enjoyed it, and thanks for reading.
Related posts: - Automatically minify and combine JavaScript in Visual Studio
- Review: Advanced ASP.NET AJAX Server Controls
- How I Got Started in Software Development
 |
|
|
|
|
|
|
|
One group of searches that consistently brings traffic here is variations on the error: Invalid JSON primitive. Unfortunately, the post that Google sends that traffic to doesn’t address the issue until somewhere within its 150+ comments.
Today, the topic gets its own post.
If you’ve worked with ASMX ScriptServices or Page Methods without ASP.NET AJAX’s client-side proxy (e.g. using jQuery or pure XMLHttpRequest code), you’ve may have seen this cryptic error yourself. Or, perhaps you’ve just arrived here due to seeing it for the first time.
Either way, you may be surprised to learn that the most common reason for this error is that you’ve lied to ASP.NET during your AJAX request.
It all begins with the Content-Type
HTTP’s Content-Type header is a fundamental aspect of communication between browsers and servers, yet often remains hidden from us in day-to-day development. The Content-Type header allows an HTTP connection to describe the format of its contents, using Internet media types (also known as MIME types). A few common ones that you’ve probably seen before are text/html, image/png, and the more topical application/json.
Without the flexible negotiation process content types provide, your users’ browsers and your version of IIS would have to both be “ASMX Compatible” and “JSON Compatible” in order for ScriptServices to function. What a nightmare that would be! The IE6 difficulties we face today would pale in comparison.
Further, Content-Type negotiation is part of what allows a single URL, such as WebService.asmx, to represent data in more than one format (e.g. XML and JSON in ASMX’s case).
The benefits of Content-Type negotiation are well worth a bit of occasional hassle.
Okay, but why does that matter?
When your browser sends a POST request, the W3C’s recommendation is that it should default to using a Content-Type of application/x-www-form-urlencoded. The HTML 4.01 spec describes that serialization scheme:
This is the default content type. Forms submitted with this content type must be encoded as follows:
- [Omitted for brevity; not relevant to this post.]
- The control names/values are listed in the order they appear in the document. The name is separated from the value by ‘=’ and name/value pairs are separated from each other by ‘&’.
For an example of what that means, consider this simple form:
<form method="post">
<label>First Name</label>
<input id="FirstName" value="Dave" name="FirstName" />
<label>Last Name</label>
<input id="LastName" value="Ward" name="LastName" />
</form>
When the preceding form is submitted with URL encoded serialization, the request’s POST data will look like this:

That standardized serialization format allows a server-side backend like ASP.NET to decipher a form submission’s contents and give you access to each key/value pair. Regardless of what sort of browser submits a form to the server, the Content-Type facilitates a predictable conversion from POST data to server-side collection.
In other words, the Content-Type corresponds to a serialization scheme.
What does that have to do with JSON Primitives?
Understanding Content-Type negotiation and how it relates to serialization is important due to its role in coaxing JSON out of ASMX ScriptServices. Specifically, the fact that you must set a Content-Type of application/json on the request means you’re instructing ASP.NET to interpret your input parameters as JSON serialized data.
However, the W3C’s mandate of URL encoding by default means that most AJAX libraries default to that serialization scheme. Similarly, AJAX tutorials targeting endpoints other than ASMX ScriptServices (including even ASP.NET MVC examples) will describe sending URL encoded data to the server.
In other words, when you’re working with a client-side object like this:
var Person = { FirstName: 'Dave',
LastName: 'Ward' }
The default serialization scheme makes it easy to inadvertently transmit that data to the server as a URL encoded string:
FirstName=Dave&LastName=Ward
Again, remember that a Content-Type of application/json is a requirement when working with ASMX ScriptServices. By setting that Content-Type on the request, you’ve committed to sending JSON serialized parameters, and a URL encoded string is far from valid JSON.
In fact, it’s invalid JSON (primitive?), hence the cryptic error message.
Instead of the URL encoded string above, you must be sure to send a JSON string:
{'FirstName':'Dave','LastName':'Ward'}
Whether you’re using XMLHttpRequest directly or a JavaScript library that abstracts the details, getting your request’s serialization wrong is the root of the invalid JSON primitive error. However, a more specific issue tends to be the leading cause of this happening.
When good JavaScript libraries go bad
The most common source of this error stems from a subtlety of using jQuery’s $.ajax() method to call ASMX ScriptServices. Cobbling together snippets of code from the documentation, platform agnostic tutorials, and even posts here on my site, it’s easy to end up with something like this:
// WRONG!
$.ajax({
type: 'POST',
contentType: 'application/json',
dataType: 'json',
url: 'WebService.asmx/Hello',
data: { FirstName: "Dave", LastName: "Ward" }
});
Notice the JavaScript object literal being supplied to $.ajax()’s data parameter. That appears vaguely correct, but will result in the invalid JSON primitive error.
Why? jQuery serializes $.ajax()’s data parameter using the URL encoded scheme, regardless of what Content-Type is specified. Even though the contentType parameter clearly specifies JSON serialization, this URL encoded string is what jQuery will send to the server:
FirstName=Dave&LastName=Ward
That obviously isn’t valid JSON!
The solution is as simple as two single-quotes:
// RIGHT
$.ajax({
type: 'POST',
contentType: 'application/json',
dataType: 'json',
url: 'WebService.asmx/Hello',
data: '{ FirstName: "Dave", LastName: "Ward" }'
});
Did you spot the difference?
Instead of a JavaScript object literal, the data parameter is a JSON string now. The difference is subtle, but helpful to understand. Since it’s a string, jQuery won’t attempt to perform any further transformation, and the JSON string will be unimpeded as it is passed to the ASMX ScriptService.
It doesn’t have to be this way
The problem is trivial once you’re aware of the underlying issue, but there’s not a great reason I can see why things need to be this way in the first place. Either half of this equation could easily provide a remedy.
jQuery – I believe the most correct solution would be $.ajax() attempting to honor the serialization scheme indicated by its contentType parameter. In the case of application/json, fixing this could be easy as testing for JSON.stringify and using it if available. That would work great, but also avoid adding any complexity/size to jQuery core.
That would leave it our responsibility to reference a copy of json2.js in older browsers, but that convention wouldn’t be much of a burden. We generally do that anyway when the client-side objects get complex.
Microsoft – It’s absolutely correct that the framework throws an error when you lie to it about what you’re sending. However, a bit of leniency could potentially save thousands of hours spent troubleshooting this problem (if my search traffic is any indication of its prevalence).
Is there any reason that the ScriptHandlerFactory can’t intelligently differentiate between between JSON and URL encoded inputs? If the first non-whitespace character of the request isn’t an opening curly brace, why not attempt to deserialize it as URL encoded before throwing an invalid JSON primitive error?
You've been reading ASMX ScriptService mistake – Invalid JSON primitive, originally posted at Encosia. I hope you enjoyed it, and thanks for reading.
Related posts: - ASMX and JSON – Common mistakes and misconceptions
- ASMX ScriptService mistakes: Installation and configuration
- 3 mistakes to avoid when using jQuery with ASP.NET AJAX
 |
|
|
|
|
|
|
|
If you follow me on Twitter, this stack of free TekPub trials may look familiar:
Each card is redeemable for a one-month membership at TekPub, which allows free, unrestricted access to all of the videos on the site. Of course, that also includes access to my TekPub series, Mastering jQuery.
I’ve given many of them away at events like MIX10 and ReMIX Atlanta 2010, but made sure to reserve some of them for you. After all, there would be no Mastering jQuery series without you.
How to enter
Since the ultimate goal of these cards is to spread the word about TekPub, I want to have a contest that respects that aim. So, we’re going to do this on Twitter.
To enter, tweet this message, making sure to keep the hashtags and URL intact:
I just entered to win a one-month free TekPub membership. You can too at: http://encosia.com/995 #TekPub #jQuery
You can click this link to make that easier: Enter me in the contest!
How to win
I’ll use random.org to select two winners each day this week (5/17/2010 – 5/21/2010) at around 9pm EDT (GMT -4) each night. Be sure you’re following me on Twitter if you aren’t already, because I’ll be announcing the winners on my @Encosia account there.
Good luck!
Update: To clarify, you only need to tweet once to be entered in the entire week of drawings. As much as I do want us to spread the word about TekPub, I definitely don’t want this to cross the line between promotion and spam.
You've been reading I’m giving away 10 free months of TekPub this week, originally posted at Encosia. I hope you enjoyed it, and thanks for reading.
Related posts: - Mastering jQuery now available at TekPub
- Contribute to open source, get a shot at a free book
- 3 years of Encosia, the best of 2009, and my gratitude
 |
|
|
|
|
|
|
|
I spent some quality time with Dave Reed’s latest revision of John Resig’s jQuery.tmpl plugin recently, migrating a small project from jTemplates. Since both the jQuery team and Microsoft team have requested feedback on jQuery.tmpl, I decided to write about my experience using it (as I am wont to do with these templating proposals).
Overall, jQuery.tmpl is a great step in the right direction. It’s small, it’s simple, and it’s fast. Overloading append() to allow the append(Template, Data) syntax is phenomenal. That approach feels more like idiomatic jQuery than anything else I’ve used, including jTemplates.
However, if this template rendering engine is going to succeed broadly, I feel there’s one important feature still missing. Additionally, there are a couple ancillary features that are present in the current proposal, but should be protected.
Composition
One area where jTemplates still comes out on top is template composition – also known as nested templates. Specifically, this refers to the ability for templates to contain references to other templates, and the ability to render that entire group as a whole.
The need for template composition may be hard to see in simple examples, but most non-trivial scenarios benefit from template composition. Dave mentioned the example of having a person template that embeds a separate template for displaying information on one or more phone entries about those person records.
That’s a good example, but take it one more step to understand where composition really shines. Consider the possibility that each of those phone records has a type (e.g. Mobile, Home, or Work) and that each type must be presented with different markup.
Template composition provides a clean solution to this problem. By creating separate templates for each type and then rendering the correct amalgamation of those templates, the template code remains simple (but is powerful).
A composition workaround in jQuery.tmpl
Currently, something resembling nested item templates are technically possible via the each keyword in jQuery.tmpl, but it’s not pretty. This example from the jQuery.tmpl demo illustrates that approach:
// Data
cities: [ "Boston, MA",
"San Francisco, CA" ]
// Template
Cities: {{each(i,city) cities}}${city}{{/each}}
Even for this most simple case, the syntax is rough. Not the sort of readable simplicity that we’ve come to expect from jQuery.
More importantly, extending that to conditionally render different fragments of markup would be much more difficult.
A cleaner workaround (but it’s a trap!)
The jQuery.tmpl demo also contains this seemingly elegant alternative:
// Data
cityJoin: function() {
return this.cities.join(", ");
},
cities: [
"Boston, MA",
"San Francisco, CA"
]
By embedding a function in the data, referencing that object key in a template returns the result of the cityJoin function. Thus, jQuery.tmpl renders the function’s result, not the function declaration’s actual text.
That technique dramatically simplifies the template itself:
// Template
Cities: ${cityJoin}
While that approach does succeed in avoiding the messy template code that each requires, it tightly couples concerns which should not be.
When this is put into practical use, the data object will usually be requested from the server-side. Would my business logic or data repository tier need to inject the joining function? I don’t think I could bring myself to do that.
Further, it doesn’t really address the real-world scenarios I’ve encountered. A callback function to format data won’t feasibly scale to rendering heterogeneous chunks of markup. Effectively, it’s the same as the each solution, with the pain point shuffled around a bit.
How I think it should work
As long as there’s some way to name and render sub-templates, I don’t care how exactly it works.
I wasn’t crazy about jTemplates’ {#include} syntax at first, but it’s okay once you get used to it. Most any syntax shouldn’t be difficult to learn and acclimate to.
Since jQuery.tmpl already provides for caching the templates in jQuery.templates, all that’s really necessary is a method for rendering those named templates within other templates.
A concrete example
This example simplified a bit, but is functionally similar to client work I come across regularly. To be clear, this is something I’m currently using today, not something I’m just theorizing as a good idea.
I want to be able to take data that isn’t necessarily homogeneously structured:
{InvoiceItems: [
{ ItemType: 'Product',
PartNumber: '99-Designs-Logo',
Description: '99 Designs Logo design',
TotalCost: 450 },
{ ItemType: 'Service',
DescriptionOfWork: "Website development",
TotalCost: 5000 },
{ ItemType: 'Service',
DescriptionOfWork: "Deployment and testing",
TotalCost: 300 }
])
And use a set of templates like this to render that data (did I get the each syntax right in #Invoice?):
{#ServiceItem}
<tr>
<td colspan="2">{$DescriptionOfWork}</td>
<td>{$TotalCost}</td>
</tr>
{#ProductItem}
<tr>
<td>{$PartNumber}</td>
<td>{$Description}</td>
<td>{$TotalCost}</td>
</tr>
{#Invoice}
<table>
<-- Fancy thead here -->
{{each(i, InvoiceItem) InvoiceItems}}
{{if $InvoiceItem.ItemType === 'Service'}}
{{render('ServiceItem', InvoiceItem)}}
{{else}}
{{render('ProductItem', InvoiceItem)}}
{{/if}}
{{/each}}
</table>
Scenarios just like that one are common in my current work with jTemplates. Imagine trying to implement that with each or an embedded callback function.
Now imagine you wanted to conditionally render those same row templates as sub-items in more than one master template (e.g. maybe there’s also a credit memo template similar to the invoice, but not identical). The burden of maintaining an application like that quickly compounds without template composition.
Again, the exact syntax doesn’t matter. Any implementation that provides the functionality would be a win.
External templates
I’ve never understood the desire to cruft up a page with inline templates. Whether they’re hidden through CSS or embedded within a text/html type script element, cluttering my markup with templates feels sloppy.
jTemplates introduced me to the idea of storing templates externally, and then asynchronously loading them only as necessary (example). I adopted that approach at nearly the same time I began using jTemplates and haven’t looked back since.
My affinity for remotely template loading caused me to lobby for remote templates both in the DataView and more recently in jQuery.tmpl. However, what I hadn’t considered is that it’s already easy to load external templates with jQuery’s built in AJAX functionality. With the template loaded into a string variable, the append(TemplateString, Data) syntax connects the dots perfectly.
All of that is simply to say: Please do leave the append(TemplateString, Data) syntax intact. As long as we can provide templates via string variable, built in remote template loading isn’t necessary.
On the need for in-template logic
I’ve heard some dissention on the issue of conditional logic within templates.
Philosophically, I agree; mingling logic into your presentation/view is dangerous. It’s always a slippery slope, at best. However, the pragmatist in me ultimately cannot agree with the hard-line approach of banishing it completely.
A project I’m working on is a good example. My client-side code must display a collection of invoices sourced from a legacy backend, each with an upgrade number. Upgrade 0 must be displayed as “Original Invoice”, but the rest should be displayed as “Upgrade n”.
A conditional in the template makes quick work of the problem (this is jTemplates syntax, not jQuery.tmpl):
{#if $T.Upgrade == 0}
Original Invoice
{#else}
Upgrade #{$T.Upgrade}
{#/if}
Since it’s purely presentational logic, it belongs in the template as much as it does anywhere. Please do keep that functionality available, even if it does have potential for abuse.
In addition to the currently available conditional keywords if and else, elseif and switch would both be nice additions.
Conclusion
Overall, I’m excited about the potential of seeing jQuery.tmpl integrated into jQuery core, or even made available as an “official” plugin. As much as I like jTemplates, support and documentation for it is spotty at best.
Ultimately, we will all benefit from standardizing on an official templating solution rolled into the jQuery core, rather than each of us using our obscure favorite.
I’m curious what you think. Am I the only one using template composition? Anyone want to make a convincing case against conditional logic in templates?
You've been reading A few thoughts on jQuery templating with jQuery.tmpl, originally posted at Encosia. I hope you enjoyed it, and thanks for reading.
Related posts: - A sneak peak at ASP.NET AJAX 4.0′s client-side templating
- Use jQuery and ASP.NET AJAX to build a client side Repeater
- Simplify calling ASP.NET AJAX services from jQuery
 |
|
|
|
|
|
|
|
Blogging about blogging alert!
This post is a bit off-topic, but I thought it was interesting. Since many of you have asked me metablogging questions, I thought you might be interested too.
An overwhelming majority of people who end up on my site only view a single page per visit. In fact, you’ll probably do the same. As I’ve come to realize: that’s okay.
I didn’t always think it was okay though. Throughout most of 2007, that caused me a great deal of concern. I’d been reading too many blogs about blogging, was convinced that persuading you to click through multiple pages was essential to the site’s success, but wasn’t able to make that happen here
Ultimately, the number of pageviews wasn’t very worrisome, because the site continued to grow. What did frustrate me was the impact that single-view visits have on a more important metric.
My site, the trampoline
What really does make single-view visits irritating is their impact on how bounce rates are calculated. Bounce rates are a measure of how many visitors hit your site and immediately leave; a bad thing. Almost every stats package, whether server-side (e.g. AWStats) or JavaScript-driven (e.g. Google Analytics), counts a visit with only one pageview as a bounce.
For example, if you spend five minutes reading this single post and then leave the site, Google Analytics will report your visit the same as if you left instantly. It will imply that you immediately left the site, even if you read every sentence. Without a second request to calculate how long you actually spent on the page, the worst is assumed.
Who cares?
The fundamental problem is that the difference between those interpretations is profound; especially for traffic coming from search engines. Worrying about bounce rates could easily be dismissed as pointless obsessing, but I think it’s one of my most important stats.
If someone finds the site during a search and gets everything they need from a single post and its comments, I see that as a win. However, if they read for a few seconds and decide my post was a bad result for their search, something needs fixing.
Lacking an accurate metric, I’ve always hoped that the former scenario was the prevalent one. I do try to write comprehensive posts and have been fortunate to have comments that are often better than the posts themselves, so that wasn’t completely far-fetched.
It was hard not to worry about the other scenario though.
If it’s good enough for Hanselman…
Luckily, I happened to read this post by Scott Hanselman, and realized that I’d been focusing on the wrong things. The entire post is great, but this was specifically relevant to my worries:
Given that realization, I look at my stats maybe twice a month, and I’m most interested in seeing what posts folks really liked that month. I used to (maybe 3 years ago) look at every referrer and stats daily, but then I realized that my personal litmus test for my blog’s success or failure is comments and other folks’ blog posts, and nothing else.
While that was good advice by itself, the most important bit of information (to me) was that he had also revealed his site’s bounce rate: 77.71%.
At that point, I immediately stopped worrying about my bounce rate. If 77.71% was good enough for Hanselman, my 78.41% was clearly not something to fixate on.
The amazing difference 30 seconds can make
Having put those insecurities behind me a couple years ago, I was interested to recently learn that my stats provider, Clicky, was about to improve how they measure bounces. Rather than rely solely on a second pageview to calculate bounce rates, Clicky’s client-side tracking code now “pings” back periodically to confirm that you’re still viewing the page.
At a 30 second interval between pings, the resolution is still imperfect, but I’m finally able to gain a better understanding of how many single pageview visits actually are bounces. As it turns out, after a week of the new tracking method, not many:
What a difference 30 seconds makes!
Now I know that most of those single pageview visits actually did represent the best-case scenario. It’s not that the content was bounce-inducingly irrelevant/bad, but relevant/good enough that a second pageview often wasn’t necessary.
You've been reading How 30 seconds dropped my bounce rate by 78%, originally posted at Encosia. I hope you enjoyed it, and thanks for reading.
No related posts.  |
|
|
|
|
|
|
|

As you might notice soon enough, a change in ASP.NET 4’s client-side API breaks versions 0.8 through 1.0 of PostBack Ritalin. Using those older versions of the control with ASP.NET 4 will throw a JavaScript error during BeginRequest and break asynchronous postbacks as a result.
PostBack Ritalin v1.1 works around that issue, and is also backward-compatible with ASP.NET 2.0 and 3.5. It’s available on the PostBack Ritalin project page now.
Special thanks to Maciej Borzecki for reporting the issue to me early enough to have a fix ready today.
You've been reading PostBack Ritalin v1.1 – Updated for ASP.NET 4, originally posted at Encosia. I hope you enjoyed it, and thanks for reading.
Related posts: - PostBack Ritalin Updated (v0.10)
- PostBack Ritalin Updated (v0.9)
- PostBack Ritalin v1.0
 |
|
|
|
|
|
|
|
I am plagiarizing myself!
I originally wrote this article for my friend Moses (of Egypt) to be published in the .Network magazine’s inaugural issue, which coincided with this year’s Cairo Code Camp. Since the article turned out well and there was no corresponding online version, we agreed it would be a good idea to republish it online here too.
Most of us get our first taste of jQuery by implementing a simple animation effect or using a plugin for a specific purpose. This is natural because, like JavaScript itself, jQuery lends itself to beginning with the basics and building from there.
As you branch out from the trivial and begin using jQuery for more complex solutions, it’s important that you stay vigilant for new ways to approach those more involved problems. What works well enough for a dozen lines of code may not work for hundreds, and the unforgiving cross-platform environment that comes along with developing for web browsers only magnifies any trouble you run into.
With that in mind, I want to share a few tips with you that I found valuable as my work with jQuery became more complex.
Use Firebug to experiment interactively
If I could suggest only one thing to you, it would be to use Firebug’s console to prototype your ideas in real time. Nothing matches the command line’s immediate feedback when you’re learning. Rather than go through the hassle of editing a JavaScript file, saving it, and then reloading it in the browser, testing at the console allows you to eliminate those intermediate steps and focus on the task at hand.
In particular, the console is invaluable when testing complex combinations of selectors and traversal methods. Simply execute a jQuery statement at the console, with your page loaded in the browser, and you will instantly see the array of matching elements that are returned. If that result set isn’t correct, press the up-arrow key to retrieve the last command entered, refine the statement, and test it again.
That tight feedback loop is phenomenal for quickly learning the jQuery API without leaving the familiar backdrop of your existing markup.
Additionally, one lesser-known feature of Firebug’s console is how it works in conjunction with Firebug’s debugger. When execution is paused, switching to the console tab allows you to interrogate and manipulate the state of the DOM as it was at the time execution was halted. As you step through JavaScript code in the debugger, the execution context of the console remains in sync with the debugger’s.
Cache selector results
jQuery’s concise syntax makes it easy to forget just how much work the Sizzle selector engine is doing on your behalf. As powerful as the terse selectors are, it’s important not to needlessly duplicate the work that they abstract – especially when using selectors without browser-native backing methods (e.g. a[href^=http], tr:odd, p:contains(Encosia), etc).
To avoid wasteful re-querying, always cache the results of a jQuery selector in a variable if that result set will be used more than once. Once stored in a variable, the result of a selector may be used in exactly the same manner as the original selector itself. For example:
// Wasteful duplication of a slow selector
$(':input[id$=name]').val('Type your name here');
$(':input[id$=name]').select();
// Nearly twice as fast
var $name = $(':input[id$=name]');
$name.val('Type your name here');
$name.select();
Prefixing the cache variable with a dollar sign is not functionally significant, but helps to clearly indicate that the variable contains a jQuery wrapped set. The topic of Hungarian notation is a contentious one, but I’ve found the dollar sign prefix beneficial as complexity increases.
Don’t use jQuery unless there’s a good reason to
Perhaps one of the most elusive keys to jQuery mastery is knowing when not to use it. Once you’re proficient with jQuery, it seems natural to use it everywhere. However, that tendency may easily mislead you into writing less concise code that runs slower than necessary.
For instance, this egregious example is one that you will see often:
// Typical jQuery over-use
$('button').click(function() {
alert('Button clicked: ' + $(this).attr('id'));
});
In the context of that callback function, this is a reference to the DOM element that raised the click event – often referred to as the execution context. Rather than using the DOM element to create a jQuery object, with all of the overhead that goes along with that, why not use the DOM element itself?
// Not only faster, but more concise.
$('button').click(function() {
alert('Button clicked: ' + this.id);
});
Another similar misuse is using jQuery as a document.getElementById shortcut. Though jQuery’s ID selector does leverage document.getElementById, it only does so after parsing the selector and then creates a jQuery object to wrap the element. Not only is there more overhead in that process, but starting with a jQuery object by default guides you toward this mistake of overusing jQuery when it isn’t necessary.
Learn advanced selectors, filters, and traversals
A great way to improve your jQuery code is to learn its selectors, filters, and traversal methods in depth. If you find yourself iterating through a selection and manually filtering it for a desired set, there is usually a better way. Double and triple check that there isn’t a combination of selectors, filters, and/or traversals available to accomplish the same end result.
Not only does using the library’s idioms make your code more concise and expressive, but you will automatically benefit from ongoing performance improvements to jQuery’s Sizzle selector engine that come with each new release. It’s hard to beat having an entire team working to improve your code for you, but that’s exactly what happens when you use jQuery syntax that’s as idiomatic as possible.
A less-frequently documented aspect of learning advanced selectors is that you should be conscious of how to work in concert with jQuery to optimize them. Because the Sizzle engine evaluates selectors from right-to-left, being as specific as possible in the rightmost portion of selectors will improve performance.
Selectors that descend from an ID are one notable exception to the right-to-left rule. Sizzle is specially optimized for that case:
// Breaks the right-to-left specificity guideline:
$('#RegistrationForm input.required').append('*');
// jQuery automatically optimizes the previous selector
// as if you had written it using the ID as a context:
$('input.required', '#RegistrationForm').append('*');
Use CDN hosting when available
When you’re developing and testing locally, it’s easy to underestimate the impact that WAN latency will have on your site. Today’s website is often accessed by a geographically diverse set of users that it is impossible to optimally serve all of them from a single datacenter. Serving static resources, such as jQuery, from content delivery networks is one effective solution to mitigate that problem.
Not only do these CDNs provide a faster, more consistent experience to geographically dispersed users, but they also open up the potential for users to visit your site with a primed cache. Since everyone using these public CDNs reference the same URL, a single browser-cached copy of a given asset may be shared between any number of sites visited by a given user.
Even better, because these CDNs serve their content with a far future Expires header, browsers immediately use a locally-cached version of that file if it’s available. They don’t even have to check with the server for a 304 “Not Modified” response, eliminating the extra HTTP request altogether.
Assets freely available on public CDNs include jQuery itself, jQuery UI, all 14 jQuery UI ThemeRoller themes, and the jQuery validation plugin.
Conclusion
I hope that you’ll find these ideas useful on your road to jQuery mastery. Though jQuery’s clear, intuitive syntax may appear simplistic on the surface, the library is immensely powerful. The key to unlocking jQuery’s full potential is to never stop experimenting and learning new aspects of it.
In the spirit of that continued road toward mastery, consider taking the next step by watching my TekPub series: Mastering jQuery.
You've been reading 5 Steps Toward jQuery Mastery, originally posted at Encosia. I hope you enjoyed it, and thanks for reading.
Related posts: - See how I used Firebug to learn jQuery
- 11 keystrokes that made my jQuery selector run 10x faster
- Updated: See how I used Firebug to learn jQuery
 |
|
|
|
|
|
|
|
Continuing my series of posts about ASMX services and JSON, in this post I’m going to cover two common mistakes that plague the process of getting a project’s first ASMX ScriptService working: Installing System.Web.Extensions into the GAC and configuring your web.config.
System.Web.Extensions (aka ASP.NET AJAX)
The ability for ASMX services to return raw JSON is made possible by two key features originally added by the ASP.NET AJAX Extensions v1.0:
- JavaScriptSerializer – The JavaScriptSerializer class is the actual workhorse that translates back and forth between JSON strings and .NET CLR objects. Though less powerful than WCF’s DataContractJsonSerializer and third-party libraries like Json.NET, JavaScriptSerializer is likely all you’ll ever need for simple AJAX callbacks.
- ScriptHandlerFactory – There are several more classes behind the scenes*, but the ScriptHandlerFactory is the tip of the iceberg that you’ll need to remember during configuration. Redirecting ASMX requests through this HttpHandler is what coordinates the pairing of ScriptService with JavaScriptSerializer to provide automatic JSON handling.
Though both of these classes appear in the System.Web.Script namespace, they actually reside in ASP.NET AJAX’s System.Web.Extensions assembly. That has different implications depending on which version of ASP.NET your site targets:
- 1.x – No support for ScriptServices. A custom HttpHandler coupled with a third party library like Json.NET is your best bet (if anyone has a good tutorial on doing this under 1.x, let me know so that I can link to it).
- 2.0 – ScriptServices are available in ASP.NET 2.0 with the installation of the ASP.NET AJAX Extensions v1.0.
- That means that the ASP.NET AJAX installer needs to be run on the server that hosts your site, not just on your local development machine.
- For some of a ScriptService’s features to work in medium trust (i.e. shared hosting), the System.Web.Extensions assembly needs to be in your server’s global assembly cache (GAC). Don’t waste your time trying to make it work in your site’s /bin directory; insist that the extensions be properly installed on the server.
- 3.5+ – As of .NET 3.5, System.Web.Extensions ships with the framework. No additional assemblies need be installed.
* If you’re interested in the internals, I highly recommend downloading the ASP.NET AJAX Extensions v1.0 source and taking a look at ScriptHandlerFactory, RestHandlerFactory, and RestHandler. Though the classes have changed slightly since v1.0, they are still very similar.
Rerouting the ASMX handler via web.config
With the System.Web.Extensions assembly installed in the GAC, the remaining configuration step is an element in your site’s web.config. To take advantage of the ScriptService functionality, ASP.NET must be instructed to reroute ASMX requests through the ScriptHandlerFactory instead of ASP.NET’s standard ASMX handler.
This step is often unnecessary. The project templates in ASP.NET 3.5+ include all the necessary configuration elements, and ASP.NET 2.0 sites created with the “AJAX Enabled” templates are also pre-configured correctly.
However, if you find yourself unable to coax JSON out of an ASMX ScriptService, verifying your web.config is one of the best first steps in troubleshooting the issue. Whether due to a web.config generated by an older project template, accidental modification, or other issues, missing the httpHandlers web.config setting is a very common pitfall.
What should appear varies slightly depending on which version of ASP.NET your project targets. Regardless of your framework version, the config elements should be added to the <httpHandlers> section and are the only elements necessary. The variety of other config items required for the UpdatePanel and ScriptManager aren’t crucial to the ScriptService functionality.
ASP.NET 2.0 (with the ASP.NET AJAX Extensions installed)
<configuration>
<system.web>
<httphandlers>
<remove path="*.asmx" verb="*" />
<add path="*.asmx" verb="*" Culture=neutral, validate="false"
type="System.Web.Script.Services.ScriptHandlerFactory,
System.Web.Extensions, Version=1.0.61025.0,
PublicKeyToken=31bf3856ad364e35" />
</httphandlers>
</system.web>
</configuration>
ASP.NET 3.5
<configuration>
<system.web>
<httphandlers>
<remove path="*.asmx" verb="*" />
<add path="*.asmx" verb="*" Culture=neutral, validate="false"
type="System.Web.Script.Services.ScriptHandlerFactory,
System.Web.Extensions, Version=3.5.0.0,
PublicKeyToken=31bf3856ad364e35" />
</httphandlers>
</system.web>
</configuration>
ASP.NET 4
Thankfully, ASP.NET 4 has taken steps to reverse the trend of ever-enlarging baseline web.config files. By moving common configuration items such as the ScriptService’s HttpHandler to the default machine.config, each individual site need not include those configuration elements in their specific web.config files.
Unless you go out of your way to manually remove their HttpHandler, ASMX ScriptServices will work automatically in any ASP.NET 4 site.
You've been reading ASMX ScriptService mistakes: Installation and configuration, originally posted at Encosia. I hope you enjoyed it, and thanks for reading.
Related posts: - ASMX and JSON – Common mistakes and misconceptions
- 3 mistakes to avoid when using jQuery with ASP.NET AJAX
- A breaking change between versions of ASP.NET AJAX
 |
|
|
|
|
|
|
|
While we were recording episode 5 of Mastering jQuery, I found myself running down a lengthy list of misconceptions and potential pitfalls when it comes to using ASMX services for AJAX callbacks. After years of fielding questions revolving around that topic, I suppose I’ve developed a decent handle on the issues most often encountered.
To preemptively surface some of that commonly requested information, I’m going to publish a series of relatively short posts, each describing one mistake or misconception that I’ve seen come up frequently.
To get started, I want to cover one of the most fundamental of these misconceptions: That ASMX services can’t return JSON.
Misconception: ASMX services are limited to XML
One of the most stubbornly persistent misconceptions about ASMX services is the rumor that they are limited to returning XML. With that notion mind, many developers understandably avoid them for client-side AJAX callbacks. When every byte counts, raw JSON is always preferable to the bloat of XML.
However, the introduction of ASP.NET AJAX removed that XML limitation.
In any ASP.NET 2.0+ AJAX enabled site, one of ASP.NET AJAX’s additions is something called the ScriptService. When a ScriptService is called in the correct manner, it automatically returns its result serialized as JSON instead of XML.
In fact, these ASMX ScriptServices even accept their parameters as JSON.
The ASP.NET AJAX “ScriptService”
If you’ve created an ASMX service in the past few years, you’ve probably seen this blurb at the beginning of the default template:
// To allow this Web Service to be called from script,
// using ASP.NET AJAX, uncomment the following line.
// [System.Web.Script.Services.ScriptService]
public class WebService : System.Web.Services.WebService {
Since it never explicitly mentions JSON and implies a tight coupling with ASP.NET AJAX, it’s easy to understand why the ScriptService’s true power sometimes goes unnoticed. Thankfully, that attribute does much more than simply expose ASP.NET AJAX specific functionality.
In fact, the ScriptService attribute enables all of an ASMX service’s methods to respond with raw JSON if they are requested correctly. For example, these ScriptServices can easily send and receive JSON in conjunction with a third party library, without a ScriptManager or MicrosoftAjax.js anywhere to be seen.
Two simple requirements
As I alluded to earlier, the one stipulation is that these ScriptServices only return JSON serialized results if they are requested properly. Otherwise, even a service marked with the attribute will return XML instead of JSON. I can only assume that’s part of the reason for the misconception that ASMX services cannot respond with JSON.
Scott Guthrie has a great post on the specific requirements for coercing JSON out of ScriptServices. To summarize that, requests to the service methods must meet two requirements:
- Content-Type – The HTTP request must declare a content-type of application/json. This informs the ScriptService that it will receive its parameters as JSON and that it should respond in kind.
- HTTP Method – By default, the HTTP request must be a POST request. It is possible to circumvent this requirement, but it is advisable to stick with HTTP POST requests when dealing with JSON.
That’s it.
As long as those two requirements are satisfied, anything from low-level XMLHttpRequest code, to third-party libraries like jQuery, to ASP.NET AJAX itself can easily retrieve JSON serialized data from ASMX services.
You've been reading ASMX and JSON – Common mistakes and misconceptions, originally posted at Encosia. I hope you enjoyed it, and thanks for reading.
Related posts: - 3 mistakes to avoid when using jQuery with ASP.NET AJAX
- Using jQuery to Consume ASP.NET JSON Web Services
- A breaking change between versions of ASP.NET AJAX
 |
|
|
|
|
|
|
|
If you’ve already begun using Microsoft’s new Ajax Script Loader with a CDN-hosted version of jQuery, today’s release of jQuery 1.4 may have left you wondering how to upgrade. Personally, I didn’t want to wait on a new version of Start.js, nor did I want to abandon the script loader now that I’ve become accustomed to its benefits.
No doubt, an upcoming ASP.NET Ajax Library iteration will update Start.js’ jQuery definition to reference jQuery 1.4.x. Regardless, knowing how to patch the script loader on your own terms is something that will be of recurring usefulness.
Luckily, the script loader is open and extensible enough that it’s possible to change which script versions are used. So, I want to briefly show you how the script loader defines JavaScript includes and how you can patch those definitions without modifying Start.js itself.
Using the script loader to inject jQuery
If you aren’t familiar with the script loader itself or with using it to asynchronously request jQuery, I recommend checking out its documentation and examples on the new ASP.NET Ajax Wiki.
To use it most basically, simply include a reference to Start.js either locally or on the Microsoft CDN, and then use this JavaScript to instruct the script loader to inject jQuery into the page:
// Instruct the script loader to request
// jQuery in the background.
Sys.require(Sys.scripts.jQuery);
// This callback runs later, after jQuery
// has been asynchronously loaded.
Sys.onReady(function () {
console.log("Loaded jQuery " + jQuery.fn.jquery);
});
Monitoring the request in Firebug illuminates what that Sys.require statement triggered in the background:

As you can see, the end result is pretty straightforward. The primary benefit of this asynchronous loading technique is that scripts loaded through the script loader are non-blocking and may be loaded in parallel. By contrast, JavaScript includes referenced through HTML script elements block all rendering and further requests until they are parsed and executed. The difference is often significant.
Now, if only it were injecting jQuery 1.4 instead of 1.3.2.
Understanding how Sys.scripts.jQuery is defined
The Sys.scripts.jQuery parameter to the script loader is actually just a JavaScript object that defines a few parameters about the include. Here is how that is defined in Start.js (edited slightly for readability here):
var path = (window.location.protocol === "https" ? "https" : "http")
+ "://ajax.microsoft.com/ajax/";
loader.defineScripts(null, [
{ name: "jQuery",
releaseUrl: path + "jquery/jquery-1.3.2.min.js",
debugUrl: path + "jquery/jquery-1.3.2.js",
isLoaded: !!window.jQuery
}
]);
If you’re using a local copy of Start.js, one option is to modify this jQuery script definition inside Start.js itself. However, I discourage that alternative. Not only would it require constant, manual maintenance after every new release, but it isn’t an option when using the Microsoft Ajax CDN’s copy of Start.js.
Defining a new target for it
Another option is to simply modify the Sys.scripts.jQuery object itself. Letting Start.js initialize the definition with jQuery 1.3.2’s path doesn’t hurt anything as long as we redefine it before calling Sys.require.
Inspecting the Sys.scripts collection in Firebug reveals how straightforward that modification will be:

Thanks to to the power of interactively interrogating the object in Firebug, it becomes clear that updating the releaseUrl and debugUrl properties of that object should be all that is necessary.
Updating the example to use jQuery 1.4
Because jQuery 1.4 isn’t available on the Microsoft CDN yet, I’m going to target Google’s AJAX Libraries CDN for jQuery instead. Once Microsoft’s CDN is updated with jQuery 1.4.x, this approach will work for either CDN.
// These re-definitions must be executed after
// Start.js, but before Sys.require.
var CDN = "http://ajax.googleapis.com/ajax/libs";
Sys.scripts.jQuery.releaseUrl = CDN + "/jquery/1.4.1/jquery.min.js";
Sys.scripts.jQuery.debugUrl = CDN + "/jquery/1.4.1/jquery.js";
// Instruct the script loader to request
// jQuery in the background.
Sys.require(Sys.scripts.jQuery);
// This callback runs later, after jQuery
// has been asynchronously loaded.
Sys.onReady(function () {
console.log"Loaded jQuery " + jQuery.fn.jquery);
});
That’s all there is to it. Reviewing the requests in Firebug again, you can see that the same Sys.require statement is indeed now loading jQuery 1.4 from Google’s CDN:

Bonus: jQuery Validate 1.6
As I write this, Start.js’ definition for Sys.scripts.jQueryValidate is still targeting version 1.5.5 of the plugin, but 1.6 is the current version.
Using what’s been covered in this post, pointing the script loader at the newest version of jQuery Validate is no problem:
var MSCDN = "http://ajax.microsoft.com/ajax";
var GoogCDN = "http://ajax.googleapis.com/ajax/libs";
// Please forgive my ugly formatting to make this fit. Do not try
// this at home (unless your editor is only 492px too).
Sys.scripts.jQuery.releaseUrl =
GoogCDN + "/jquery/1.4.1/jquery.min.js";
Sys.scripts.jQuery.debugUrl =
GoogCDN + "/jquery/1.4.1/jquery.js";
Sys.scripts.jQueryValidate.releaseUrl =
MSCDN + "/jQuery.Validate/1.6/jQuery.Validate.min.js";
Sys.scripts.jQueryValidate.debugUrl =
MSCDN + "/jQuery.Validate/1.6/jQuery.Validate.js";
// Instruct the script loader to request
// jQuery and jQuery Validate in the background.
Sys.require([Sys.scripts.jQuery, Sys.scripts.jQueryValidate]);
// This callback runs later, after both jQuery
// and jQuery Validate have been loaded.
Sys.onReady(function () {
console.log("Loaded jQuery " + jQuery.fn.jquery);
});
The jQuery Validate situation is a good example of why knowing how to update these script definitions yourself is worthwhile. Because the script loader was designed to be so flexible, there’s no need to wait on a new release of Start.js or give up its benefits.
You've been reading How you can force the Ajax Script Loader to use jQuery 1.4, originally posted at Encosia. I hope you enjoyed it, and thanks for reading.
Related posts: - 3 mistakes to avoid when using jQuery with ASP.NET AJAX
- Using jQuery to directly call ASP.NET AJAX page methods
- Updated your web.config, but Sys is still undefined?
 |
|
|
|
|
|
|
|
Bring Batch The 90s - Blog
|