Move Scripts To Bottom

Last night's jQuery Meetup was once again pretty awesome. Thanks again to BrightMix for hosting it and providing the Pizza and to Jonathan Sharp for making it all happen.

Andrew from Blue Cross Blue Shield presented on AJAX. He showed us his concept of building a global jQuery handler using a Namespace. This would allow other programmers in the organization and himself to skip all the repetitive programming. Some examples included a predefined spinner object and a global AJAX error handler. He'll post his example to the group and I'm sure I'll benefit from it in my projects.

One thing that caught my attention was with any larger JavaScript scripts you should consider moving the include to the bottom of the body tag. He explained this was so the page will load without hanging on scripts that must parse a lot of information. So I did a little research on this.

Remember Microsoft's Blue Screen of Death? Thank God I haven't seen this in a long time thanks to advancements in XP, Vista and 2007! Well, apparently there's a similar "White Screen of Death". This happens when the browser gets caught up in the JavaScript code for awhile before passing the content to the DOM. To avoid this move the script include to the bottom of the body tag. This will load the content into the DOM and then load things like the JavaScript and images.

The HTTP/1.1 specification suggests that browsers download no more than two components in parallel per hostname. This is where CDN's (content delivery networks) come into place nicely. While your website is loading your content and images using only two parallel paths, a third path can be opened to load libraries such as jQuery, not to mention it may already be cached in the browser if they visited another site using the same CDN.

I've always been taught to include CSS and JavaScript in the head tag, but I never really looked into the reasons behind it. Technically they can be included almost anywhere in the page. In the case of CSS includes, what you get is the Style Sheet is loaded and then the content when the CSS is included in the head tag. So when the content is being displayed, it progressively styles the content instead of going back after it's all loaded and then style it causing some visual confusion.

Yahoo! Developer Network provides a great document titled "Best Practices for Speeding Up Your Web Site". there are 35 best practices in 7 categories including conent, server, cookie, CSS, JavaScript, Images, and Mobile.

One more thing I picked up on; and I know I've seen it before; is how to break up large string blocks in JavaScript. Consider the following:


$('div').append('<ul><li>item1</li><li>item2</li><li>item3</li><li>item4</li><li>item5</li><li>item6</li></ul>');

Break it up into multiple lines for better code organization using the + sign:


$('div').append('<ul>'
+ '<li>item1</li>'
+ '<li>item2</li>'
+ '<li>item3</li>'
+ '<li>item4</li>'
+ '<li>item5</li>'
+ '<li>item6</li>'
+ '</ul>');

Query of Queries Trims Whitespace Automatically

After literally hours of tracking down what was causing a large code base to behave badly, I found an odd and frustrating features when doing a query of queries with <cfquery>. Take the following code as an example of what you would think works:


<cfquery name="q1" datasource="#application.DSN#">
    SELECT ' A2010 ' as v1
    FROM Seasons
    WHERE teamid = <cfqueryparam value="18513" cfsqltype="cf_sql_integer">
</cfquery>

<cfquery name="q2" dbtype="query">
    SELECT v1
    FROM q1
    WHERE LOWER(v1) = '#Lcase(' A2010 ')#'
</cfquery>

The above code will return 10 results for q1 but none for q2 even though they are both matching " 2010 ".

To fix the issue I tried using in the second query and even tried replacing the space with a #chr(32)# character code. Neither worked.

Changing the query to the following works:


<cfquery name="q1" datasource="#application.DSN#">
    SELECT ' A2010 ' as v1
    FROM Seasons
    WHERE teamid = <cfqueryparam value="18513" cfsqltype="cf_sql_integer">
</cfquery>

<cfquery name="q2" dbtype="query">
    SELECT v1
    FROM q1
    WHERE LOWER(v1) = '#Lcase('A2010')#'
</cfquery>

Notice I removed the space before and after the 2010 in the second query. This will return all 10 results even though it is not an exact match.

ColdFusion is automatically trimming the whitespace of the values returned from q1.

The only solution I can find is to trim the value to match as well. This will provide for an inexact match, but will work for my purpose. This is very concerning because you could have a lack of results and not even know it without inspecting it.

The final code I've come up with for a "sorta-fix-workaround" is:


<cfquery name="q1" datasource="#application.DSN#">
    SELECT ' A2010 ' as v1
    FROM Seasons
    WHERE teamid = <cfqueryparam value="18513" cfsqltype="cf_sql_integer">
</cfquery>

<cfquery name="q2" dbtype="query">
    SELECT v1
    FROM q1
    WHERE LOWER(v1) = '#Lcase(Trim(' A2010 '))#'
</cfquery>

Inspect AMF Traffic for Flex

Whenever I develop in Flex, I've always used ServiceCapture. It is a commercial product that inpects all type of traffic including Flex's AMF, a binary format based loosely on the Simple Object Access Protocol (SOAP). ServiceCapture runs about $34 per seat. It allows me to see what traffic is being sent back and forth between my ColdFusion Server and Flex for debugging and QA purposes.

I was made aware today of a new player in town that integrates into FireBug for FireFox. It's currently experimental, but seems to work nicely. Check it out.

Removing a Select Option in IE using jQuery

I have a selection list, that once selected I would like to remove or disable the option choosen. However, at a later time I may want to add or enable it again.

There is a bug in Internet Explorer that does not allow you to use the .hide() method on an option. It works just find in other browsers of course.

Searching Google I've determined that if I want it hidden in IE, that I would have to use the .remove() method, which removes it from the DOM, store it in an array, and add it back in when needed. I thought this was overkill.

So I found a good solution. The attribute 'disabled' works in IE. Since the hide() method will silently fail, do both. Therefore the option will just not be choosable in IE, and it will disapear in other browsers.


<select>
<option value="">Select One</option>
<option value="1">One</option>
<option value="2">Two</option>
</select>
<a href="javascript:void(0);">add</a>

<script type="text/javascript">
//do this when the add link is clicked
$('a').click(function() {
//hide or disable the option
$('select :selected').attr('disabled','disabled').hide();
//reset the options back to the top
$('select').val('');
});
</script>

FCKEditor running ColdFusion Stops Working with FireFox 2010 Releases

FCKEditor will stop working with FireFox 3.5.7, 3.6 and future releases. There is a "Year 2010" bug that breaks the regular expression method they use to find what browser you are using. I found this in FCKEditor v.2.6.4.1. ColdFusion 8 and 9 appears to be okay, however I would double check them.

The issues lies in the file fckutils.cfm located in the FCKEditor root install directory. It checks for your useragent such as "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.5; en-US; rv:1.9.2) Gecko/20100115 Firefox/3.6".

The glitchy code can be found on line 47:


stResult = reFind( "gecko/(200[3-9][0-1][0-9][0-3][0-9])", sAgent, 1, true );

Replace this line with:


stResult = reFind( "gecko/(20[0-9][0-9][0-1][0-9][0-3][0-9])", sAgent, 1, true );

This will give the expression another 90 years of matching. You can also pass "checkBrowser=false" to the FCKEditor component to disable this check.

If you don't have a fckutils.cfm file, a similar line can be found in fckeditor.cfc.

Another "fix" is to upgrade to CKEditor as it's a Javascript only add-on.

Thanks to Pete Freitag for find a fix for this.

MSSQL Update/Insert Based Upon Existing Record

In the past I learned how to combine one query to correctly update or insert a record based upon if it exists or not. I would only use this if I didn't already know if it existed because an un-needed select statement would be run and it increases the size of the query string.

Example:


IF EXISTS (SELECT * FROM Table1 WHERE Column1='SomeValue')
UPDATE Table1 SET (...) WHERE Column1='SomeValue'
ELSE
INSERT INTO Table1 VALUES (...)

Thanks to Jeremiah Clark's Blog, I've found an often better way of doing this.


UPDATE Table1 SET (...) WHERE Column1='SomeValue'
IF @@ROWCOUNT=0
INSERT INTO Table1 VALUES (...)

The first example will do a table/index scan for both the SELECT and UPDATE statements. The second example will perform one less table/index scan, likely increasing performance.

Google CDN Tips

Thanks to BrightMix for hosting the jQuery meetup presented by Jonathan Sharp last night in Omaha.

Jonathan presented on the new features of jQuery 1.4 last night along other Q&A topics.

Lately I've been experimenting with the Google CDN for delivering jQuery and jQuery UI. The reasons behind using the CDN is faster library loads, cross-internet library caching, automatic version management, and decreased hosting bandwidth.

Jonathan offered a few tips:

1. SSL works with the CDN's path based requests. Use either "http://ajax.googleapis.com" or "https://ajax.googleapis.com".

2. For automatic switching between http:// and https:// get rid of it. Yep - just use "//ajax.googleapis.com". Don't confuse the slashes as "\\" will get you a network path. This should also work for "<img src='//..." and "<a href='//..." but I haven't tested that yet.

3. When using a path such as "//ajax.googleapis.com/ajax/libs/jquery/1.4/jquery.js", you can control the automatic versioning by increasing or decreasing the dot notation on the version. In the example above, I will always get the latest version of 1.4 - currently 1.4.1. If I wanted to always get 1.4.0, I would append the ".1". If I always wanted to get the laster 1.x version, I'd remove the ".4".

Apple's credibility flashing by...

Apple released the Apple iPad last week. Other than a horrible name, I thought it was a great design and am very tempted to buy one. Three things I think will make this device:

  1. It's thin, it's lightweight, and looks good (hopefully they don't break too easily)
  2. Battery life is up to 10 hours (we'll have to see real-world numbers though)
  3. A simple, easy-to-use OS

But I wondered, what about Adobe Flash support? Jobs said that "you will be able to see the web as it actually is". I figured I'd read about it in a few days. The answer was no. Jobs gave two reasons:

  1. Flash will eventually die and give way to HTML5
  2. Flash is one of the largest reasons why a Mac crashes. (Really? I thought a Mac doesn't crash :() )

According to Adobe, 99% of all Internet-enabled desktops in mature markets as well as a wide range of devices have some version of Flash installed. While taking into account a little marketing tweeking, it is still used by the majority of everyday web users.

HTML5 is still being developed and accoring to Ian Hickson, editor of HTML5 specification, the expected W3C Candidate Recommendation stage will be in 2012 which means Microsoft will likely not pick it up until after then. So what are we going to do until then? Two choices. One being make the end-users see a broken flash placeholder or second being make and maintain two versions of your website. Neither are a good solution.

HTML5 is aimed at reducing the need for proprietary plug-in-based RIA technologies such as Adobe Flash, Microsoft Silverlight, and Sun JavaFX according to Wikipedia. HTML5 will introduce native 2D drawing, media playback, drag-and-drop, messaging and more. So does Jobs expect that everyone just drop the millions if not billions of Flash apps out on the Internet now and try to convert everything to HTML 5? Besides, flash is still rapidly evolving with new features and frameworks like Flex. It's just not going to die, anytime remotely soon.

Right now Apple seems to have it out for Google. But Google did one thing right with their Chrome browser. They managed plugins that break. So if Flash crashed, only the specific block of the webpage would show a broken-flash placeholder and you could either reload and try again or go on to the rest of the webpage uninterrupted. So wouldn't that be a little more reasonable solution for Apple? In Apple's mobile browser, mimic this great Chrome feature and Jobs second reason would be void and the end-user would benefit greatly.

Jobs needs to step up and not hide behind whatever agenda he has against Adobe. So, I will probally wait to buy another competitor's Tablet until Jobs can get in gear. Not to mention it's limited to AT&T for 3G wireless service again. Ug.

Other resources:

Google phasing out support for IE6

As a programmer I've had to deal with Microsoft's Internet Explorer 6 since, well... since it first came out. Non-standards driven, needing multiple hacks to make things show up right. It costs me frustration and time and the client time and money.

But today is a good day. The big-wig of the Internet, Google, is stepping up and saying it's had enough. According to cnet's News site "As of March 1, Google will no longer support IE6 on its Google Docs and Google Sites services...". Recently a flaw in IE6 was exploited and allowed access to Google's network.

Perhaps this will force a few more IE users to upgrade their browsers and make my and countles other developer's life a little easier.

Avast 5

I've used Avast as my primary anti-virus solution for close to half-a-decade now. There are a number of reasons for this but the two foremost are it's free and non-bloated.

Anytime I get a new computer or setup a friend's computer, the first thing to go is Norton's solution. At first it was just anti-virus. It would always hog memory and slow down resources. Then came along their Security Suite which hogged even more resources.

After uninstalling Norton, Avast would always go on. I've never had any issues with it hogging up my resources. It's always been fast, clean, efficient, and reliable for me. All you had to do was register each year and turn off the annoying voice announcment every day when the definitions update.

It has caught most viruses through file-copy and file-download for me and have rarely seen one slip by unless someone hit ignore and let it continue. People! Read the warnings!

Today I read on cnet News that Avast 5 was released. It features a new GUI which makes things much more pleasant to look at and even easier to use. But what caught my attention the most is what I've never taken the time to research.

From cnet:

"In November 2009, Avast 4.8 and Microsoft Security Essentials were the only freeware to score Advanced+ in the Retrospective/Proactive Test done by AV Comparatives. It's also the only program that tested faster than Norton AntiVirus 2010, and was tied with Microsoft for second place in fewest false positives detected. The detection score was also high, at 98 percent. That's worse than Avira, but Avast noted far fewer false positives. ...Avast Free 5 [is] probably the strongest, free antivirus currently available."

"Sold"

More Entries

BlogCFC was created by Raymond Camden. This blog is running version 5.9.1. Contact Blog Owner