Activate your free membership today | Log-in

Tuesday, September 22nd, 2009

Gmail Mobile team talks Latency and Code Loading

Category: Google, Mobile, Tip

Bikin Chiu of the Gmail Mobile team picks up the HTML5 series with a piece on reducing startup latency.

It starts off by talking about lazily loading code via the old favorites of adding a <script> to the DOM, or XHR+eval, but then it gets beyond the typical and discusses the nuance of mobile + offline caching. The hack that is used, is another oldie.... which is to hide the script and eval it later:

For an HTML 5 application that takes advantage of the application cache to reduce startup latency and to serve the application offline, there are a few caveats one should be aware of. Mobile networks have decent bandwidth, but poor round trip latency, so listing each module as a separate resource in the manifest incurs quite a bit of extra startup latency when the application cache is empty. Also, if one of the module resources fails to be downloaded by the application cache (e.g. disconnected from network), additional error handling code needs to be written to handle such a case. Finally, applications today have no control when the application cache decides to download the resources in the manifest (such a feature is not defined in the current specification of the draft standard). Typically, resources are downloaded once the main page is loaded, but that's not an ideal time since that's when the application requests user data.

To work-around these caveats, we found a trick that allows you to bundle all of your modules into a single resource without having to parse any of the JavaScript. Of course, with this strategy, there is greater latency with the initial download of the single resource (since it has all your JavaScript modules), but once the resource is stored in the browser's application cache, this issue becomes much less of a factor.

To combine all modules into a single resource, we wrote each module into a separate script tag and hid the code inside a comment block (/* */). When the resource first loads, none of the code is parsed since it is commented out. To load a module, find the DOM element for the corresponding script tag, strip out the comment block, and eval() the code. If the web app supports XHTML, this trick is even more elegant as the modules can be hidden inside a CDATA tag instead of a script tag. An added bonus is the ability to lazy load your modules synchronously since there's no longer a need to fetch the modules asynchronously over the network.

On an iPhone 2.2 device, 200k of JavaScript held within a block comment adds 240ms during page load, whereas 200k of JavaScript that is parsed during page load added 2600 ms. That's more than a 10x reduction in startup latency by eliminating 200k of unneeded JavaScript during page load! Take a look at the code sample below to see how this is done.

HTML:
  1.  
  2. <script id="lazy">
  3. // Make sure you strip out (or replace) comment blocks in your JavaScript first.
  4. /*
  5. JavaScript of lazy module
  6. */
  7. </script>
  8.  
  9.   function lazyLoad() {
  10.     var lazyElement = document.getElementById('lazy');
  11.     var lazyElementBody = lazyElement.innerHTML;
  12.     var jsCode = stripOutCommentBlock(lazyElementBody);
  13.     eval(jsCode);
  14.   }
  15. </script>
  16.  

In the future, we hope that the HTML5 standard will allow more control over when the application cache should download resources in the manifest, since using comments to pass along code is not elegant but worked nicely for us.

Posted by Dion Almaer at 6:09 am
11 Comments

+++--
3.4 rating from 20 votes

Wednesday, September 2nd, 2009

FireCrystal: Observe and roll back interactions

Category: Tip, Utility

FireCrystal is a Firefox extension that helps designers and programmers alike figure out how interactive behaviors on the web work. FireCrystal allows users to record and rewind their interactions with web pages while showing the relevant code.

Posted by Dion Almaer at 6:52 am
8 Comments

+++--
3.3 rating from 14 votes

Wednesday, July 29th, 2009

Text rotation for all

Category: CSS, Tip

Jonathan Snook has posted a nice nugget on text rotation with CSS that takes a nice bit of markup like this:

HTML:
  1.  
  2. <div class="example-date">
  3.   <span class="day">31</span>
  4.   <span class="month">July</span>
  5.   <span class="year">2009</span>
  6. </div>
  7.  

and converts it to:

all via the CSS:

CSS:
  1.  
  2. -webkit-transform: rotate(-90deg);
  3. -moz-transform: rotate(-90deg);
  4. filter: progid:DXImageTransform.Microsoft.BasicImage(rotation=3);
  5.  

Yup, even IE.

Posted by Dion Almaer at 10:20 am
33 Comments

++++-
4.3 rating from 52 votes

Thursday, July 2nd, 2009

More than you ever want to see about encoding

Category: Tip, Utility

Paul Baukaus linked to jsescape, a little form that shows escaping and unescaping across a number of encodings.

Andrea Giammarchi had his own post on encodings in a different way.... as he talked about
en-code which you can check out in action here on the page that lets you do simple encodings, especially for source code, in short order.

Posted by Dion Almaer at 5:03 am
17 Comments

+++--
3.5 rating from 17 votes

Friday, April 24th, 2009

CSS Browser Hacks

Category: CSS, Tip

Paul Irish tries not to use CSS browser hacks anymore and instead "uses IE's conditional comments to apply classes to the body tag, but he put up a concise list of browser specific hacks he has used:

CSS:
  1.  
  2. /***** Selector Hacks ******/
  3.  
  4. /* IE 6 and below */
  5. * html #uno  { color: red }
  6.  
  7. /* IE 7 and below */
  8. *:first-child+html #dos { color: red }
  9.  
  10. /* IE 7 and modern browsers */
  11. html>body #tres { color: red }
  12.  
  13. /* Modern browsers (not IE 7) */
  14. html>/**/body #cuatro { color: red }
  15.  
  16. /* Opera 9.27 and below */
  17. html:first-child #cinco { color: red }
  18.  
  19. /* Safari */
  20. html[xmlns*=""] body:last-child #seis { color: red }
  21.  
  22. /*safari 3+, chrome 1+, opera9+, ff 3.5+ */
  23. body:nth-of-type(1) #siete { color: red }
  24.  
  25. /* safari 3+, chrome 1+, opera9+, ff 3.5+ */
  26. body:first-of-type #ocho {  color: red }
  27.  
  28. /* saf3, chrome1+ */
  29. @media screen and (-webkit-min-device-pixel-ratio:0) {
  30.  #diez  { background: #FFDECE; border: 2px solid #ff0000  }
  31. }
  32.  
  33. /***** Attribute Hacks ******/
  34.  
  35. /* ie6 and below */
  36. #once { _color:blue }
  37.  
  38. /* ie7 and below */
  39. #doce { *color: blue } /* or #color:blue */
  40.  
  41. /* 'Modern Browsers' includes IE8, whether you agree or not.. :) */
  42.  

He has included a test page and you can view the different browsers via browsershots.

Finally, he links to another concise list... of JavaScript sniffs.

Posted by Dion Almaer at 10:35 am
15 Comments

+++--
3.3 rating from 32 votes

Thursday, April 23rd, 2009

How many ways can you iterate over an array in JavaScript?

Category: JavaScript, Tip

Myk is one of the nicest chaps that I have had the pleasure to sit closely to in Mozilla building "S".

He has a nice little tip on the many syntaxes that you can use to iterate over arrays in various JavaScript implementations and standards. Some folks had some interesting points on the various approaches:

for each in:

JAVASCRIPT:
  1.  
  2. for each (var item in [1, 2, 3]) alert(item);
  3.  

The MDC docs for "for each" say not to iterate arrays that way, too, so I never use it on them. The usual (would need to guard with hasOwnProperty() issue).

JavaScript 1.6 added the Array.forEach method:

JAVASCRIPT:
  1.  
  2. [1, 2, 3].forEach(function(item) { alert(item) });
  3.  

JavaScript 1.7 added array comprehensions for array initialization:

JAVASCRIPT:
  1.  
  2. var squares = [item * item for each (item in [1, 2, 3])];
  3.  

I just realized I can (ab)use comprehensions to iterate arrays with Perl-like syntax by throwing away the result:

JAVASCRIPT:
  1.  
  2. [alert(item) for each (item in [1, 2, 3])];
  3.  

I can iterate object properties the same way:

JAVASCRIPT:
  1.  
  2. var obj = { foo: 1, bar: 2, baz: 3 };
  3. [alert(name + "=" + obj[name]) for (name in obj)];
  4.  

Edward Lee points out how to use Iterators:

JAVASCRIPT:
  1.  
  2. [alert(key + "=" + val) for ([key, val] in Iterator({a:1,b:2,c:3}))]
  3.  

Posted by Dion Almaer at 4:29 am
18 Comments

+++--
3.4 rating from 37 votes

Friday, April 3rd, 2009

Detecting event support in browsers

Category: JavaScript, Tip

Kangax has a really nice article on testing for event support in browsers in which he delves into the quirks and work-arounds needed to get 'er done, coming up with a nice generic solution:

JAVASCRIPT:
  1.  
  2.   var isEventSupported = (function(){
  3.     var TAGNAMES = {
  4.       'select':'input','change':'input',
  5.       'submit':'form','reset':'form',
  6.       'error':'img','load':'img','abort':'img'
  7.     }
  8.     function isEventSupported(eventName) {
  9.       var el = document.createElement(TAGNAMES[eventName] || 'div');
  10.       eventName = 'on' + eventName;
  11.       var isSupported = (eventName in el);
  12.       if (!isSupported) {
  13.         el.setAttribute(eventName, 'return;');
  14.         isSupported = typeof el[eventName] == 'function';
  15.       }
  16.       el = null;
  17.       return isSupported;
  18.     }
  19.     return isEventSupported;
  20.   })();
  21.  

Along with this, he put up a simple test case that you can point at.

Posted by Dion Almaer at 7:19 am
18 Comments

++++-
4.5 rating from 19 votes

Friday, March 6th, 2009

Calculate your content to markup ratio

Category: Tip, Utility

Stoyan Stefanov has created a fun little bookmarklet that calculates the content to markup ratio of a webpage:

When you care about performance, or SEO (or just doing a good job as web dev) an interesting data point is the ratio of page content vs. the markup used to present this content. Or... how much crap we put in HTML in order to present what the users want to see - the content.

So I played tonight with a bookmarklet to provide this piece of stats.

The bookmarklet code is served from here. The code is also on github.

And some fun results:

Here are some random results of running the bookmarklet on different sites.

http://www.cnn.com:
Total size: 92004 bytes
Content size: 11475 bytes
Content-to-markup ratio: 0.12
Fair ratio * : 0.16

http://www.sitepoint.com

Total size: 65989 bytes
Content size: 16199 bytes
Content-to-markup ratio: 0.25
Fair ratio * : 0.60

Article on http://en.wikipedia.org:
Total size: 21648 bytes
Content size: 3315 bytes
Content-to-markup ratio: 0.15
Fair ratio * : 0.35

http://www.phpied.com
Total size: 31899 bytes
Content size: 7933 bytes
Content-to-markup ratio: 0.25
Fair ratio * : 0.48

http://www.google.com SERP
Total size: 29963 bytes
Content size: 3351 bytes
Content-to-markup ratio: 0.11
Fair ratio * : 0.14

Posted by Dion Almaer at 2:58 am
3 Comments

++++-
4.4 rating from 14 votes

Monday, February 23rd, 2009

Watching Prototype events and a nice little tip

Category: Prototype, Tip

Kangax shows a nice use of Prototype as he writes a tip to let you see your Prototype based events as they run in your application. A nice little view.

He also realized that the core piece of the bookmarklet is actually a nice view of the power of Prototype as a library:

JAVASCRIPT:
  1.  
  2. $H(Event.cache).inject(0, function(m, p) {
  3.   m += $H(p.value).values().flatten().size();
  4.   return m;
  5. });
  6.  

Posted by Dion Almaer at 6:56 am
2 Comments

+++--
3 rating from 24 votes

HTML5 Canvas Cheat Sheet

Category: Canvas, Examples, Tip

Jacob is back, and this time he has a cheat sheet with him. It is nice to see the Canvas API fitting on one sheet here, and I really like the images showing how things look like and work.

Posted by Dion Almaer at 12:56 am
1 Comment

++++-
4.1 rating from 20 votes

Thursday, January 29th, 2009

IE=’\v’==’v’

Category: Tip

JAVASCRIPT:
  1.  
  2. IE='\v'=='v'
  3.  

That is the current winner in the shortest way to test for IE (including 8). The other notable was:

JAVASCRIPT:
  1.  
  2. IE=top.execScript?1:0
  3.  

Huh :)

Gareth Heyes (the chap who did the v trick) has posted on this himself and comes up with One Line To Rule Them All:

JAVASCRIPT:
  1.  
  2. B=(function x(){})[-5]=='x'?'FF3':(function x(){})[-6]=='x'?'FF2':/a/[-1]=='a'?'FF':'\v'=='v'?'IE':/a/.__proto__=='//'?'Saf':/s/.test(/a/.toString)?'Chr':/^function \(/.test([].sort)?'Op':'Unknown'
  3.  

Posted by Dion Almaer at 1:02 am
23 Comments

++++-
4.4 rating from 52 votes

Tuesday, January 27th, 2009

Browser Detection with XSLT

Category: Tip

This is a fun little hack by Manfred Staudinger.

Thanks to select="system-property('xsl:vendor')", he has a style sheet that allows you to show items depending on the browser:

To include a link or a style element for one of the above choices you use the dr:select attribute and specify one or more tokens as a comma separated list. For example dr:select="Firefox, Safari 3" will cause the link or style element to be included for any Firefox and for Safari 3. If you specify more than one token, each of which constitutes a positive selection, you may use any combination of tokens from the non-IE browsers plus the token "IE".

To select a specific IE only one token in the dr:select attribute is allowed, because it is directly used in constructing a Conditional Comment (CC). These are constructed on the fly only if the current browser is actually an IE. Any valid CC expression is allowed, so you can specify for example dr:select="lte IE 7" (positive selection) or dr:select="!IE 6" (negative selection). To clarify, a positive CC selection will allow only the IE's specified to read the CSS, and a negative CC will exclude them from seeing it. The best, you don't need anymore to include Microsoft proprietary CC's for selecting CSS in your HTML!

Link and style elements without a dr:select attribute are considered common stylesheets which every browser will see. They will remain unchanged, as any other HTML element. Only the dr:select attributes will be nullified.

You could do this when JavaScript isn't enabled for example.... although I am not sure how practical it actually is :)

Posted by Dion Almaer at 5:50 am
14 Comments

++++-
4.3 rating from 18 votes

Monday, January 19th, 2009

Web Resources He Uses

Category: Tip

"Ethan" has a really nicely packaged set of web resources that he uses.

From JavaScript core libraries, to widgets, to tools, to CSS frameworks, to CSS techniques, to browser compatibility, to typography, to extensions, and much much more. Nicely done.

Posted by Dion Almaer at 5:27 am
5 Comments

+++--
3.6 rating from 24 votes

Monday, January 12th, 2009

Forcing a UI redraw from JavaScript

Category: JavaScript, Tip

Thomas Fuchs has run into those annoying times when a redraw is required to irk the browser into a correct layout, and his weapon of choice is:

JAVASCRIPT:
  1.  
  2. Element.addMethods({
  3.   redraw: function(element){
  4.     element = $(element);
  5.     var n = document.createTextNode(' ');
  6.     element.appendChild(n);
  7.     (function(){n.parentNode.removeChild(n)}).defer();
  8.     return element;
  9.   }
  10. });
  11.  

This is an update to the Script.aculo.us forceRerendering so it will probably be in Scripty 2? :)

Sebastian of Qooxdoo had a similar technique:

You may also use some kind of addClass/removeClass combo. That would result into the same effect but without creating unused DOM elements. We use this method in qooxdoo and it works well.

Do you run into these issues?

Posted by Dion Almaer at 1:45 pm
11 Comments

++++-
4 rating from 8 votes

Friday, November 14th, 2008

Guid0: JavaScript GUIDs

Category: JavaScript, Library, Tip

Our own Michael Mahemoff is at it again, creating a simple little GUID generator called Guid0:

Guid0 is a GUID library for Javascript. Okay, it doesn't yet do official, bona fide, 128-bit, GUIDs yet, mainly for API design reasons. But this is a library you might find useful if you want to generate a unique ID in your Ajax app.

JAVASCRIPT:
  1.  
  2. // simple
  3. guid = new Guid();
  4. var newguid = guid.generate();
  5.  
  6. // options
  7. guid = new Guid(
  8.   {
  9.         chars: Guid.constants.base85// or you could say "abc" if you only wanted those chars to appear
  10.         epoch: "June 1, 2003",
  11.         counterSequenceLength: 2, // a counter field appended to the end
  12.         randomSequenceLength: 2 // a random field appended to the end
  13.   }
  14. );
  15.  

He is working on 128-bit support.

Posted by Dion Almaer at 6:47 am
3 Comments

+++--
3.1 rating from 15 votes

Wednesday, October 1st, 2008

Finding those trailing commas

Category: Tip, Utility

Dan Fabulich got bitten by the "trailing comma" issue one too many times, so he created a script to solve his problem:

“How many thousands of developer hours have been lost to random IE bugs like this?” I asked myself. I decided that there had to be a good way to detect this problem in an automated way, without firing up a copy of IE and running a full test suite.

It turns out that these and other syntax errors can be detected automatically from the Windows command line, using the Windows Scripting Host (WSH). On Windows XP and higher, the command-line tool “cscript.exe” can be used to run JavaScript (ahem, JScript) headlessly (outside of any browser).

Just create a file called “wsh-parser.js” like this:

JAVASCRIPT:
  1.  
  2. var fso = new ActiveXObject( "Scripting.FileSystemObject" );
  3.  
  4. function parse(fname) {
  5.     var file = fso.OpenTextFile( fname, 1 );
  6.     ret = file.ReadAll();
  7.     file.Close();
  8.     try {
  9.         eval("(function(){\n"+ret+"\n});");
  10.     } catch (e) {
  11.         WScript.Echo("Syntax error parsing " + fname);
  12.         WScript.Echo("  " + e.message);
  13.     }
  14. }
  15.  
  16. function findJavaScript(folder) {
  17.     for (var fc = new Enumerator(folder.files); !fc.atEnd(); fc.moveNext()) {
  18.         var file=fc.item();
  19.         if (/.js$/.test(file.Name)) {
  20.             parse(file);
  21.         }
  22.     }
  23.     for (var fc = new Enumerator(folder.subfolders); !fc.atEnd(); fc.moveNext()) {
  24.         var subfolder = fc.item();
  25.         if (subfolder.Name == ".svn") continue; // ignore .svn folders
  26.         findJavaScript(subfolder);
  27.     }
  28. }
  29.  
  30. var rootPath = "src/main/javascript";
  31. var rootFolder = fso.GetFolder(rootPath);
  32.  
  33. findJavaScript(rootFolder);
  34.  

Other tools will help you hunt this down too, and I am sure some of you have Perl/Ruby/Python one liners to do the same ;)

Posted by Dion Almaer at 5:37 am
Comment here

+++--
3.7 rating from 3 votes

Next Page »