5. Things You Could Be Doing
Instead of Fixing Bugs
● Sleeping ● Playing Bioshock 2
● Reading a book ● Shopping for new shoes
● Working out ● Getting your picture
● Enjoying a frosty brew taken at those little
booths at the mall
● Mowing the lawn ● Shoveling snow
● Watching a movie ● Actually, this is worse
● Bowling that fixing bugs
● Doing laundry ● Selling junk on eBay
● Attending this ● Buying junk on eBay
presentation!
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
6. Debugging Dojo
& JavaScript
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
7. Types of Bugs
● Syntax errors
● Runtime errors
● Logic errors
● Performance issues
● Bugs that other people committed into svn
● Because our code is flawless
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
9. Old School Debugging
<form>
<textarea name="output"></textarea>
</form>
<script type="text/javascript">
alert("If you're reading this, it doesn't work.");
document.write("x should be 10, but for some reason it's " + x);
document.forms[0].output.value += "Loading external resource...n";
document.forms[0].output.value += "Still loading...n";
document.forms[0].output.value += "Hello?n";
</script>
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
10. Old School Debugging
● Write some code, reload, test, write some code,
reload test, write some code, reload, test
● But if you write too much code
● Comment out / remove huge chunks of code until
things work again
● View source
● What exactly did the server send?
var quote_of_the_day = "Who said "debugging" ain't easy?";
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
11. Old School Debugging
● Custom error handling awesomeness
window.onerror = function(msg, url, lineno){
alert("Thou art detects an error:n"
+ "Message: " + msg + "n"
+ "URL: " + url + "n"
+ "Line #: " + lineno);
};
function foo(){
var bar = "fail";
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
12. Old School Debugging
● JavaScript console
● Netscape 4, Mozilla, Firefox
● Internet Explorer
● Generally sucked
● Line # rarely correct
● Crappy error messages
– "Object required"
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
13. Old School Debugging
● Microsoft Script ● Microsoft Script Editor
Debugger ● Uses Visual Studio
● Steaming pile ● It's on your Office
2003 CDs
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
14. Old School Debugging
● Venkman
● Component of the Mozilla Suite
● Also a Firefox extension
● Sloooooooooooow
– Provided it didn't crash
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
15. Not So Old School
● try/catch/throw
● New in ECMAScript 3!
– Published Dec 1999
● Implemented by IE6/NS6
try {
if (something) {
throw new Error("oh snap!");
}
} catch (e) {
alert(e);
}
● Catches that suppressed errors
● All over Dojo code base
● If something is not working, check if it's being silently
being caught
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
16. Advanced Tactics
● Proxy server
● Packet sniffing
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
18. JavaScript Bugs
● Syntax errors
● Things that the cause the parser to hate life
function foo() {
foo(1 2);
dojo..isFunction(foo);
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
19. JavaScript Bugs
● Runtime Bugs
● Undefined variables & methods
● Unexpected results
foo(); // foo() undefined
var i = 10 + x; // x undefined
function bar() {
return arguments.join(',');
}
function baz(y) {
return
y * y;
}
alert(baz(2)); // undefined!
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
20. JavaScript Bugs
● Variable scopes ● Watch out for reserved
● Local vs global words!
● Naming ● Rhino (used by Dojo's
build tool) is very picky
● Case sentivity break, case, catch, continue, default,
delete, do, else, finally, for,
● Try to use unique function, if, in, instanceof, new,
names to avoid return, switch, this, throw, try,
accidentally overwriting typeof, var, void, while, with
abstract, boolean, byte, char, class,
● Use meaningful names const, debugger, double, enum, export,
– Unless you need a little extends, final, float, goto,
implements, import, int, interface,
more job security long, native, package, private,
protected, public, short, static,
super, synchronized, throws,
transient, volatile
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
21. JavaScript Bugs
● Functions
● Forgetting commas between arguments
● Forgetting braces
● Misspelling funtcion
● Avoid resuing function names
function foo(){
alert("hello");
}
foo(); // alerts "world"
function foo(){
alert("world");
}
foo(); // alerts "world"
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
22. JSON Bugs
● Missing commas
● Hanging commas
● Confusing } and ]
● Not quoting names that contain special chars
var i = { var k = [
firstName: "Chris" {
lastName: "Barber" "class": "JavaScript",
}; "course #": 101
},
var j = { {
firstName: "Chris", "class": "C++",
lastName: "Barber", "course #": 102
}; };
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
23. JavaScript Engine Limits
● Max string length
● Implementation dependent
● Max integer value
● Really, really huge
● Max z-index
● 2,147,483,647
● ...
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
25. djConfig.isDebug
● Only useful in browsers that don't have a console
● IE6/7
● Firefox without Firebug
● Old versions of Opera/Safari
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
26. djConfig.isDebug
● Automatically loads dojo._firebug.firebug
● Limited functionality
● ReCSS, console, DOM viewer, Object viewer
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
27. dojo.declare
● Used to define objects
● Careful what you initialize
● Numbers, booleans, & strings are OK
● Arrays & objects are a bad idea
– Use constructor() or postCreate() (if a dijit)
dojo.declare("MyObj", null, {
foo: [ "Hello" ],
bar: null,
constructor: function() { this.bar = ["baz"]; }
});
var obj1 = new MyObj;
var obj2 = new MyObj;
console.debug(obj1.foo); // outputs ["Hello"]
console.debug(obj2.foo); // outputs ["Hello"]
obj1.foo.push("world!");
console.debug(obj1.foo); // outputs ["Hello","world!"]
console.debug(obj2.foo); // outputs ["Hello","world!"]
obj1.bar.push("zap");
console.debug(obj1.bar); // outputs ["baz","zap"]
console.debug(obj2.bar); // outputs ["baz"]
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
28. dojo.declare
● Extending objects
● Invoking an inherited object's method
dojo.declare("MyObj", nullj, {
foo: function(){
alert("Hi from MyObj!");
}
});
dojo.declare("MyNewObj", MyObj, {
foo: function(){
alert("Hi from MyNewObj");
this.inherited(arguments);
}
});
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
29. dojo.data
● fetchItemByIdentity()
● Make sure IDs are unique!
dojo.require("dojo.data.ItemFileReadStore");
var s = new dojo.data.ItemFileReadStore({
data: {
identifier: "id",
items: [
{
id: "/foo",
name: "foo",
children: [
{
id: "/foo/bar",
name: "bar"
}
]
}
]
}
});
s.fetchItemByIdentity({
identity: "/foo",
onItem: function(item){
console.info(item);
},
onError: function(item){
console.error(item);
}
});
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
30. Manipulating the DOM
● Wait until onload
● dojo.addOnLoad() or dojo.ready() (new in 1.4)
● If you can't wait, use document.write()
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
31. dojo.parser
● djConfig.parseOnLoad does not autoload
dojo.parser
● Must dojo.require("dojo.parser")
● Can fire the parser manually
● dojo.parser.parse()
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
32. dojo.require()
● Build system is a little too smart
● Uses regex to find requires
if(condition){
dojo.require("my.module");
}
if(condition){
dojo["require"]("my.module");
}
dojo.requireIf("my.module", condition);
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
33. Closures & dojo.hitch()
// assume we're in an object's function...
dojo.forEach([1, 2, 3], this.foo); // Error!
var _t = this;
dojo.forEach([1, 2, 3], function(n){ _t.foo(n) });
dojo.forEach([1, 2, 3], dojo.hitch(this, "foo"));
// does the same thing internally as dojo.hitch()
dojo.forEach([1, 2, 3], "foo", this);
// dojo.connect does the same thing
dojo.connect(myButton, "onclick", this, "foo");
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
37. Widget Params
● Param must be defined before mixin
<div dojoType="MyObj" param1="abc" param2="def" param3="ghi"></div>
<script type="text/javascript">
dojo.require("dijit._Widget");
dojo.declare("MyObj", dijit._Widget, {
param1: "",
constructor: function(){
this.param2 = "";
},
postCreate: function(){
console.debug(this.param1); // abc
console.debug(this.param2); // def
console.debug(this.param3); // undefined
}
});
</script>
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
38. Template Errors
● 404 File not found
● No root node
● Invalid variables ${foo}
● Variables must be defined before buildRendering()
– member variable
– initialize in constructor()
– initialize in postMixInProperties()
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
39. Template Errors
● Say you want to speed up development
● Do a Dojo build of dojo, dijit, code that is good to go
● Your namespace is "foo" and you have a custom
dialog that extends dijit.Dialog
● If using Dojo 1.3.2 or earlier, you MUST define
templateString:null before your templatePath
● Otherwise the dijit.Dialog's templateString overrides
your templatePath!
dojo.declare("foo.MyDialog", dijit.Dialog, {
templateString: null,
templatePath: dojo.moduleUrl("foo", "MyDialog.html")
});
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
40. Template Errors
● Not an issue with 1.4 and newer
● Just use templateString
● Use dojo.cache!
● You can still use dojo.moduleUrl()
dojo.declare("foo.MyDialog", dijit.Dialog, {
templateString: dojo.cache("foo", "MyDialog.html")
});
// After build, template is inlined! Awesome
dojo.declare("foo.MyDialog", dijit.Dialog, {
templateString: dojo.cache("foo", "MyDialog.html", "<div>Hi from my dialog!</div>")
});
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
41. Template Errors
● Build system uses regex to inline templates
● Don't get cute
(function($){
$.declare("foo.MyDialog", dijit.Dialog, {
templateString: $.cache("foo", "MyDialog.html") // NO!
});
})(dojo);
(function($){
$.declare("foo.MyDialog", dijit.Dialog, {
templateString: dojo.cache("foo", "MyDialog.html") // OK!
});
})(dojo);
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
42. Templates Caching Issues
● When not using a build, templates are loaded via
XHR
● Templates may be cached by the browser
● Definitely in Firefox
● Disable cache or empty cache after template
changes
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
43. postCreate() vs startup()
● postCreate()
● Template created
● Can create new DOM nodes
● Not every widget's postCreate() has been called yet!
● startup()
● Called after a widget and its children have been created
and added to the page
● All parent/child widgets created, postCreate() has been
called
● Now you can start talking to other widgets :)
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
44. Dijit Themes
● Live coding mistake #253
● Forgetting to include the dijit theme's css file
<link rel="stylesheet"
href="/path/to/dijit/themes/tundra/tundra.css"
type="text/css"/>
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
45. Dijit Themes
● Live coding mistake #254
● Forgetting to add the theme name to the body class
<body class="tundra">
...
</body>
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
46. Dijit Themes
● Only use what you need!
● Example: you only need a dijit.Calendar
// mytundra.css
@import url("/path/to/dijit/themes/dijit.css");
@import url("/path/to/dijit/themes/tundra/Common.css");
@import url("/path/to/dijit/themes/tundra/form/Common.css");
@import url("/path/to/dijit/themes/tundra/Calendar.css");
● Build system inlines only those files!
<link rel="stylesheet"
href="/path/to/mybuild/mytundra.css"
type="text/css"/>
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
48. Build Profiles
● Define the prefixes you need
● Build system copies each namespace
● Don't need to specify "dojo" prefix
dependencies = {
stripConsole: "normal",
version: "1.4.1",
cssOptimize: "comments",
copyTests: false,
optimize: "shrinksafe.keepLines",
layerOptimize: "shrinksafe.keepLines",
layers: [
{
name: "dojo.js",
dependencies: [
"dijit.Dialog",
"dijit.layout.BorderContainer",
"dijit.layout.ContentPane"
]
}
],
prefixes: [
[ "dijit", "../dijit" ]
]
}
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
49. ShrinkSafe
● optimize & layerOptimize
● shrinksafe
– Awesome for production!
● shrinksafe.keepLines
– Awesome for debugging!
● dojo.js & dojo.js.uncompressed.js
● Use the uncompressed version for debugging
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
51. dojox.analytics
● Use it to send info back to the server
● Dojo startup info
● Window information
● mouseover sampling
● idle activity
● console.* messages
<script type="text/javascript"
src="/path/to/dojo.js"
djConfig="sendMethod:'script', sendInterval:5000,
analyticsUrl:'http://example.com/dojox/analytics/logger/dojoxAnalytics.php'"
></script>
<script type="text/javascript">
dojo.require("dojox.analytics");
dojo.require("dojox.analytics.plugins.consoleMessages");
dojo.require("dojox.analytics.plugins.dojo");
dojo.require("dojox.analytics.plugins.idle");
dojo.require("dojox.analytics.plugins.mouseClick");
dojo.require("dojox.analytics.plugins.mouseOver");
dojo.require("dojox.analytics.plugins.window");
</script>
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
52. CSS Tricks
● Disable a style/property by changing the name to
something invalid
● x.myStyle{padding:10px;}
● Styling dojo.dnd.Avatars
● Start a drag, then disable JavaScript
● Use Firebug/ReCSS to finish styling
● Empty cache or disable cache to refresh
background images
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
53. Missing Images
● Create images and be notified if the image is 404
● dojox.image.Lightbox uses this technique
dojo.create("img", {
id: "myimage",
src: "/path/to/my/image.jpg",
onerror: function(){
dojo.create("img", {
id: "missingimage",
src: "/path/to/missing/image.jpg"
}, dojo.body());
}
}, dojo.body());
// note: this code is untested... don't shoot me
// if it doesn't work :)
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
54. Performance
If it's slow, it's a bug
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
55. Performance
● Use a Dojo build
● Only include the dijit css files you need
● Cache values that won't change
● getViewport(), marginBox(), etc
● Destroy non-visible tab content
● Combine XHR payloads
● Use a profiler
● Write better code
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
56. Performance
● Combine images into sprites
● Additional sprite for repeat-x & repeat-y
● Enable gzip
● Use a CDN
● Or multiple subdomains
● Put scripts at the bottom of the page
● Read Steve Souder's books!
● http://stevesouders.com/
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
58. Test Cases
● Write simple test cases
● Individual html files to test a specific feature
● DOH: Dojo Objective Harness
● Little chunks of code to test stuff
dojo.require("doh.runner");
dojo.addOnLoad(function(){
doh.register("myTest", [
function myFunction(){
var foo = [];
foo.push(6);
foo.push(1);
foo.push(2);
doh.is(foo.indexOf(1), 2);
}
]);
doh.run();
});
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
59. Testing Multiple Browsers
● Use a bunch of old computers
● Or join the modern web development revolution and
use a virtual machine
● Virtual Box
● VMware Workstation
● VMware Fusion
● Parallels
● IE6/IE7/IE8
● FF2/FF3
● Safari 3/4
● Opera 9/10
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
60. Testing Multiple Browsers
● Microsoft Virtual PC Disk Images
● http://tinyurl.com/osoomm
Disk Image Expires Size
IE6 + XP SP3 April 1, 2010 753.8MB
IE7 + XP SP3 April 1, 2010 813.1MB
IE8 + XP SP3 April 1, 2010 812.9MB
IE7 + Vista 120 days after first run 700.0MB, 700.0MB, 590.5MB
IE8 + Vista 120 days after first run 50.6MB, 700.0MB, 700.0MB, 687.9MB
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
62. Firefox Extensions
● Lori – Life-of-request info (page load times)
● Tamper Data
● Dated, but can still be useful
● Web Developer Toolbar
● Firebug
● Firecookie
● Yslow
● Many, many, many, many more...
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
63. Firebug
● http://www.getfirebug.com/
● console.log(), console.debug(), console.info(),
console.warn(), console.error()
● Use "," instead of "+": console.debug("x =", x);
● Console
● Debugger
● Profiler
● more...
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
64. Firebug Lite
● http://getfirebug.com/firebuglite
● Bookmarklet
● More featureful than Dojo's FBL
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
65. Webkit Web Inspector
● Chrome/Safari/Epiphany/Titanium
● Enable in Safari from command line:
– defaults write com.apple.Safari IncludeDebugMenu 1
● Console
● Debugger
● Profiler
● more...
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
66. IE Developer Toolbar
● IE6/IE7
● DOM viewer
● Modify CSS
● Clear cache
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
67. Internet Explorer 8
● Integrated into IE8!
● Console
● Debugger
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
68. IDEs With JavaScript Debuggers
● Netbeans
● http://netbeans.org/kb/67/web/js-debugger-ug.html
● Firefox & IE
● Aptana Studio
● http://www.aptana.org/studio
● Eclipse + Fireclipse
● http://www.almaden.ibm.com/u/bartonjj/fireclipse
● Still active?
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/
69. dair
● Dojo Extensions for Adobe AIR
● http://o.sitepen.com/labs/dair/
● Debug console
● Command line logger
● File logger
dojo.connect | 2.10.2010 | Chris Barber | CB1, INC. | http://www.cb1inc.com/