Fantastic video on Software Engineering

Posted in development by Kris Gray on December 28th, 2010

If your not following @dalmaer you are really missing out. I feel like I can stay up to date with my field of JavaScript development by simply following Dion. Something he posted a few days ago was this video that he called must watch, and I totally agree. It really redefines a few common perceptions that I’ve had ever since I’ve been programming.

Real Software Engineering – Glenn Vanderburg from Engine Yard on Vimeo.

Update: This second video has been posted as a great follow up video.

No comments

Self executing recursive javascript functions

Posted in development by Kris Gray on December 28th, 2009

The title is intimidating, but fear not. This will be short, sweet and probably really easy to understand. And you’ll have something to impress me with in interviews if you ever have the pleasure.

Why?

A while back I was writing some code and it turned out it was executed by two different code paths. In one case, the control was all ready and the code needed to be executed right away. In the other case, the control wasn’t ready but would be shortly after the window.load event has been fired. Yea I’m not explaining it very well, but really it doesn’t matter, lets see code.

Code

  1. var isLoaded = false;
  2.     (function() {
  3.         if(isLoaded) {
  4.             document.getElementById("out").innerHTML = "Loaded";
  5.             return;
  6.         }
  7.        
  8.         // Every 10th of a second call this method again.
  9.         document.getElementById("out").innerHTML += "Trying Again<br/>";
  10.         setTimeout(arguments.callee, 100);
  11.        
  12.         // If your inside an object, you probably want to keep the THIS pointer.
  13.         // For that, you would do the following.
  14.         // var self = this, fn = arguments.callee;
  15.         // setTimeout(function() { fn.call(self); }, 100);
  16.        
  17.         // The page will be loaded in 3 seconds
  18.         // We would probably want to wait for something like
  19.         // a DOM event, but its just sample code. So...
  20.         setTimeout(function() { isLoaded = true; }, 3000);
  21.     })();

We have both techniques of the example in use here, a self executing anonymous function, and a recursive function.

For the self executing anonymous function, we are wrapping our function in parenthesis and then calling it just like any other function.

  1. // The anonymous part
  2. (function(){})();

For the self executing part, we get a reference to the function using arguments.callee, which just so happens to be itself. With it we can use a setTimeout to have the function try again later. We could have just kept calling it, but with javascripts single threaded nature, I would think nothing would happen while your calling your function over and over.

  1. (function(){
  2. // BAD
  3. // At least in our case. You could have
  4. // a perfectly justifiable reason for doing this
  5. // though.
  6. arguments.callee();
  7. })();

You can see a live example of this code here

No comments

IE 6, 7, 8 Only CSS

Posted in development by Kris Gray on December 22nd, 2009

Introduction

This topic doesn’t really need an introduction, so lets move on!

Options

DOM wrappers using Conditional Comments

This is the technique used by the jQuery UI site. The basics are that if you wrap your entire page in a DIV with the browser version as the class name, you can just add extra rules to your one stylesheet that will get picked up. Then you can use conditional comments to show the appropriate DIV when necessary.

  1. <body id="home">
  2. <!--[if IE 5]>
  3.  
  4.  
  5. <![endif]-->
  • </body>
  • With this solution, you can include all your CSS in one file, so everything is tidy and theres no extra web requests necessary.

    It comes at the cost of your HTML cleanliness, but its overall very minimal.

    Conditional Stylesheets

    Using the same trick as above, you can include stylesheets conditionally on IE with conditional comments. The abilities of the conditional comment syntax is quite powerful, it seems like its wasted doing just stylesheet inclusion.

    1. <!--[if IE]> <link href="ie_only.css" rel="stylesheet" type="text/css"> <![endif]-->

    This is probably what I would suggest to most of you out there. Its quick, un-invasive and you can pretty much throw it out there and only worry about it when you really have to do something for just IE.

    Let the server do it

    I only mention this because I work in an enterprise environment that does just that. It includes an IE version of the stylesheet you referenced if the user is browsing in IE.

    So if you have a stylesheet Calendar.css and you navigated to the page using IE, you would get tags for both Calendar.css and Calendar_ie.css. If of course Calendar_ie.css exists.

    CSS Hacks, Syntax and Selector

    So I’m regurgitating a bunch of information from this Web Dev Out CSS Hacks page which is that there are some CSS hacks based on selector engine parsing issues that are possible.

    The primary options are those which are valid CSS, as invalid CSS is much more likely to cause you problems down the line.

    Here’s some of the selectors from that article.

    IE 6 and below
    * html {}

    IE 7 and below
    *:first-child+html {} * html {}

    IE 7 only
    *:first-child+html {}

    IE 7 and modern browsers only
    html>body {}

    Modern browsers only (not IE 7)
    html>/**/body {}

    Recent Opera versions 9 and below
    html:first-child {}

    Its perfectly understandable that these may be your only options at the moment, but the chance they come back to bite you is so much higher as to make conditional comments worth your effort.

    So, what to use?

    Well, I tend to use the conditional extra stylesheet method, but between that and the DOM inclusion which are both good options its really up to you. You’ll still have the comfort of knowing that your doing things the right way, and that the next .0.0.1 version of FireFox, IE, or WebKit won’t break your site and bring down the internet.

    1 comment

    JS Methods, static and instance

    Posted in javascript by Kris Gray on December 21st, 2009

    When you start having objects in your code, its only natural that methods would follow. With methods there are many different ways to define them, all have various side effects so it’ll be important to know why one is preferable to the other.

    Instance method in object

    1. function FooObject() {
    2.    this.mBar = function(){};
    3.    this.mBlah = fnBlah;
    4. }
    5.  
    6. function fnBlah() {}

    Here we have an object FooObject, and every time we instantiate it, it gets methods of mBar and mBlah on it.

    The primary thing to consider here is that every time you instantiate an instance of FooObject, a new copy of the function assigned to mBar is created. So we have a memory penalty.

    We also get two extra operations which assign functions to the two method properties of our FooObject for each new instance of FooObject.

    Though because mBar's function is defined inside of the FooObject, it does have access to its scope via closure. Which is something.

    Instance method on prototype

    1. function FooObject() {};
    2. FooObject.prototype = {
    3.    mBar: function() {},
    4.    mBlah: fnBlah
    5. }
    6.  
    7. FooObject.prototype.mBoo = fnBoo;
    8.  
    9. function fnBlah(){};
    10. function fnBoo(){};

    Assigning to the Prototype of your new class has some major advantages. The prototype object is consistent for each instance of the FooObject, so you don’t have extra operations for each method you assign on each object instance.

    You can specify a new blah method that will inject itself as first into the chain to be called, yet still maintain a copy of the old method.

    1. // New FooObject with a blah method which alerts a string.
    2. function FooObject(){};
    3. FooObject.prototype = {blah: function(s){alert(s)}};
    4.  
    5. // New instance of Foo Object
    6. var x = new FooObject();
    7.  
    8. // Redefine the Blah method, now it should prompt instead of alert.
    9. x.blah = function(s) { prompt(s,s); };
    10.  
    11. // Call the original blah method which alerts.
    12. FooObject.prototype.blah.call(x, 'asdf');
    13.  
    14. // Call the blah method on our instance, it will prompt not alert.
    15. x.blah('xyz');

    A note about assigning to the prototype though, if your doing inheritance, you’ve just blown up your inheritance chain. Here’s some code to show you what I mean.

    1. function Animal(){};
    2. function Cat(){};
    3.  
    4. // Cat is an animal
    5. Cat.prototype = new Animal();
    6.  
    7. // Uhhh yea, now its no longer an animal
    8. Cat.prototype = { 'meow': function(){} }

    Its because of this most (all?) of the JS Libraries out there would end up Iterating over the Animal class and assigning all its properties to the Cat prototype. Its a bit of a brute force technique, but its what must be done.

    The only thing I dislike about this method is how clean looking it is. I’m not a fan of having your methods declared after your object all the way down the page, its just not very easy on the eyes. But with using a method like Mootools’s Class.Implement you can still use this basic technique with it still looking good.

    Static Methods

    With static methods, we want to call the method from the definition of the object, not an instance of it. Since functions are essentially objects themselves, we can add whatever we like to them.

    1. function Animal() {};
    2. function Cat(){}
    3. Animal.GetName = function(petObj){};
    4.  
    5. // This works
    6. Animal.GetName(new Cat());
    7.  
    8. // FAIL!
    9. new Animal().GetName(new Cat());

    Since Static methods are declared on the declaration it doesn’t get inherited. Thus, there is no Cat.GetName().

    No comments

    Google Sites Data API Prototype

    Posted in development by Kris Gray on December 19th, 2009

    I’ve made note of my fondness of Google sites before.

    This project originated from the need to consolidate our JSDocs into a single search able source with all our other data. As that data is all in Google Sites at the moment, integration with Google Sites seemed the sensible choice.

    Last thing I want to mention is that I don’t claim to be super knowledgable on this topic, I’m only going to talk about what I’ve experienced in developing this prototype.

    High Level

    Google provides REST API’s for a lot of its services as well several different client libraries to interact with said REST API’s without having to worry to much about xml, namespaces and such.

    I used the gdata-javascript-client in this example as its more my specialty.

    In the js client, for getting the content feed (which is the listing of your sites information) you’ll want to login, instantiate a GoogleService, and make a getFeed call using the GoogleService instance. Lets get to the prototype to see how we do that.

    Prototype

    In my prototype, I have 3 buttons that allow you to login, get your content feed, and then update one of the pages with new HTML.

    Here’s a link to the Prototype. Be aware, you’ll need to to change the URL’s to a google site you control (probably), otherwise you won’t be able interact with its API. (At least not the update, the get should work)

    Here’s the full text of that prototype.

    1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
    2. "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    3. <html>
    4. <head>
    5. <title>Sample using the Google data JavaScript client library</title>
    6. <link rel="stylesheet" type="text/css" href="http://code.google.com/css/dev_docs.css">
    7. <style>
    8.     blockquote { margin: 2px 6px; padding: 0; border: 1px solid silver; }
    9.     span { display: block; font: 11px Arial; color: #999; }
    10.     input { border: 1px solid #333; margin: 3px 0 12px 0; width: 600px; }
    11.     textarea { width: 600px; height: 300px; }
    12.     h3 { display: block; margin: 0; padding: 0; height: 25px;}
    13.     #out { margin: 10px 0 0 0; border: 2px solid #F00; }
    14. </style>
    15. <script type="text/javascript" src="http://www.google.com/jsapi"></script>
    16. <script type="text/javascript">
    17.  
    18. /* Loads the Google data JavaScript client library */
    19. google.load("gdata", "2.x");
    20.  
    21. function init() {}
    22.  
    23. function logMeIn() {
    24.     var nameOfMyGoogleServiceThatIsTotallyMadeUp = "test-app";
    25.     var scope = "http://sites.google.com/feeds/";
    26.     var token = google.accounts.user.login(scope);
    27.    
    28.     service = new google.gdata.client.GoogleService("jotspot", nameOfMyGoogleServiceThatIsTotallyMadeUp);
    29. }
    30.  
    31. function get() {
    32.     var feed = document.getElementById("siteUrl").value;
    33.     logMeIn();
    34.     // Call the content feed, pass the result to the output function
    35.     service.getFeed(feed, output);
    36. }
    37.  
    38. function update() {
    39.     var pageId = document.getElementById("pageId").value;
    40.     logMeIn();
    41.     // Get an entry object for the page
    42.     service.getEntry(pageId, function(entryRoot) {
    43.    
    44.         // $t indicates the text of the content node.
    45.         // We are setting it to whats in the textarea.
    46.         entryRoot.entry.content.$t = txt();
    47.         service.updateEntry(pageId, entryRoot.entry, output, output);
    48.     });
    49. }
    50.  
    51. function output(obj) {
    52.     if(!obj) { out('Watch was passed nothing');}
    53.     out((function(o) {
    54.         var s = [];
    55.         for(var i in o) {
    56.             s.push([i, '=', o[i]].join(''));
    57.             if(!o[i]) {
    58.                 continue;
    59.             } else if(o[i].constructor == Object) {
    60.                 s.push('<blockquote>' + arguments.callee(o[i]) + '</blockquote>');
    61.             } else if(o[i].constructor == Array) {
    62.                 for(var c=0;c<o&#91;i&#93;.length;c++) {
    63.                     s.push('<blockquote>' + arguments.callee(o[i][c]) + '</blockquote>');
    64.                 }
    65.             }
    66.         }
    67.         return s.join('<br/>');
    68.     })(obj));
    69. }
    70.  
    71. function out(str){ document.getElementById("out").innerHTML = str; }
    72. function txt() { return document.getElementById("updateText").value; }
    73.  
    74. google.setOnLoadCallback(init);
    75.  
    76. </script>
    77. </head>
    78. <body>
    79.     <button onclick="logMeIn()">Login</button>
    80.     <button onclick="get()">Get Content of Site</button>
    81.     <button onclick="update()">Update</button>
    82.     <br/>
    83.     <h3>Site Id</h3>
    84.     <input type="text" id="siteUrl" value="http://sites.google.com/feeds/content/site/justisetest"/>
    85.     <br/>
    86.     <h3>Page Id</h3>
    87.     <span>Obviously you should get this programmatically, but its a prototype so yea...</span>
    88.     <input type="text" id="pageId" value="http://sites.google.com/feeds/content/site/justisetest/8416968326017325843"/>
    89.     <br/>
    90.     <textarea id="updateText"><h1>updated!</h1></textarea>
    91.     <div id="out">
    92.    
    93.     </div>
    94.     <img src="bullet.jpg" border="0"/>
    95.    
    96. </body>
    97. </html>

    Login and instantiate a service

    1. var scope = "http://sites.google.com/feeds/";
    2.     var token = google.accounts.user.login(scope);
    3.    
    4.     service = new google.gdata.client.GoogleService("jotspot", nameOfMyGoogleServiceThatIsTotallyMadeUp);

    Here we are logging into the google service using oAuth, then we create a new GoogleService object, passing the type of service we want to interact with. (Which is jotspot) Then we supply just some name for our application.

    Getting the content

    1. var feed = document.getElementById("siteUrl").value;
    2.     logMeIn();
    3.     // Call the content feed, pass the result to the output function
    4.     service.getFeed(feed, output);

    The feed URL for my little public site is http://sites.google.com/feeds/content/site/justisetest

    So thats what I plug into our service’s get feed. (It gets declared as a global variable in the logMeIn() call)

    Its an async call, so it doesn’t return anything, it passes the result to an onSuccess function.

    My onSuccess function is just a method that takes something and outputs it to a div, so its basically a kind of a little watch window.

    Updating content

    1. var pageId = document.getElementById("pageId").value;
    2.     logMeIn();
    3.     // Get an entry object for the page
    4.     service.getEntry(pageId, function(entryRoot) {
    5.    
    6.         // $t indicates the text of the content node.
    7.         // We are setting it to whats in the textarea.
    8.         entryRoot.entry.content.$t = txt();
    9.         service.updateEntry(pageId, entryRoot.entry, output, output);
    10.     });

    The Page id I just stole from the content field, which I’m basically hard-coding.

    Ensure I’m logged in, and then I make a call to the service to request the entry object.

    Once my onSuccess function is called, I update the entry’s page text, and then use the service to update the entry again.

    Those two output calls are the onSuccess and onError functions, which right now just output the result.

    Thats it

    Obviously a lot left to figure out, but I think once you’ve got to this point, you can actually start exploring the features of the API without having to figure out how to the most basic of operations.

    No comments

    « Previous PageNext Page »