ctodx

This Blog

News

Favorite Posts

Archives

May 2011 - Posts

  • Webinar wrap-up: Julian on JavaScript–reading jQuery (part 2)

    I decided to take a slightly different tack with the second part of my “reading jQuery” webinar duet. First, I looked at the whole of the jQuery project with regard to what we might learn for our own multi-developer JavaScript project and, second, I discussed what the heck is returned from a call to jQuery or $ and what we might learn from that.

    You can watch the webinar here.

    Writing a JavaScript codebase in a team

    Unbox/Unwrap. Pralus Papouasiephoto © 2009 Everjean | more info (via: Wylio)You can find all of the code for the jQuery project in a Git repository. Fro the root, open up Makefile. This contains the commands needed to build JQuery using either make or ant. Note the productions BASE_FILES and MODULES: they define the individual code files that, once concatenated, produce jquery.js (and its minified version). The files are concatenated a little further on: search for the call to the system command @@cat.

    The first and last files mentioned in MODULES are intro.js and outro.js. If you look at those files in the src folder you’ll see that they are the preamble and postscript to jquery.js:

    /*!
    * jQuery JavaScript Library v1.6.1
    * http://jquery.com/
    *
    * Copyright 2011, John Resig
    * Dual licensed under the MIT or GPL Version 2 licenses.
    * http://jquery.org/license
    *
    * Includes Sizzle.js
    * http://sizzlejs.com/
    * Copyright 2011, The Dojo Foundation
    * Released under the MIT, BSD, and GPL Licenses.
    *
    * Date: Thu May 12 15:04:36 2011 -0400
    */
    (function (window, undefined) {
    
      // Use the correct document accordingly with window argument (sandbox)
      var document = window.document,
    	navigator = window.navigator,
    	location = window.location;
    
      // rest of code
    
      window.jQuery = window.$ = jQuery;
    })(window);

    code.js is a special case (it’s the foundation of jquery itself), so take a look at deferred.js. Notice it has a preamble and postscript of its own, forming an anonymous auto-executing function:

    (function (jQuery) {
    
    // rest of deferred.js
    
    })(jQuery);

    But that code is not found in the final jquery.js: it is stripped out by the sed system command in the same production as the “”@@cat” command:

    @@cat ${MODULES} | \
    	sed 's/.function..jQuery...{//' | \
    	sed 's/}...jQuery..;//' | \
    	sed 's/@DATE/'"${DATE}"'/' | \
    	${VER} > ${JQ};

    That same code inserts the current date and version number into the code.

    This wrapping of the individual JavaScript modules with an anonymous auto-executing function means that you can work on a single module without affecting any of the other modules. You can load the current jQuery source, then load your particular module, and everything in that module will replace what’s already in jQuery. Hence you can design, develop, test individual modules without affecting the rest of the team.

    Notice also from the Makefile that a module called selector.js is concatenated, but that it doesn’t appear in the src tree. That’s because it’s created from sizzle.js, another open source library.

    Another part of the Makefile shows that the build entails the use of jsLint (the source is under the build folder) to perform a code-checking pass over the code before it’s built. jsLint is a code checker from Douglas Crockford and is usually found in an interactive version at jslint.com. Here it is being used locally to check the jQuery code as it’s being built. The minifier is also called as part of the jQuery build process: it’s encapsulated by uglify.js (apt name!) and uses parse-js.js, and so on.

    So, in conclusion, the entire build process for jQuery points the way to how to structure a multi-developer team working on the same codebase. All you need is a Linux machine or a Mac or Windows supplemented with Cygwin in order to build jQuery yourself.

    The jQuery Collection

    What the heck does a call of the form $(someSelector) return? The first question that should come to you is: is it an array? After all, it holds a set of elements and even comes with an each method. Let’s investigate. I wrote a function to “dump” such an object:

    var dumpObj = function (obj) {
      console.log($.isArray(obj));
      console.log(obj.length);
      if (obj.length > 0) {
        console.log(obj[0]);
      }
    };
    
    var p = $(".post");
    dumpObj(p);
    
    p = $("#post_280");
    dumpObj(p);

    The function first writes out if the object is an array (using the jQuery helper function), then it writes out the value of the length property, and if that is non-zero, the first element. (The code is designed to run on my personal blog’s home page: the structure of the page is fairly simple and consists of a set of divs of class post, with each post having a unique id.)

    If you run this you’ll see that the object returned by the jQuery function is not an array, but is array-like: it has a length property, and it has a set of properties named from 0 to length-1. But the similarities with an array end there; there are no array methods like slice, splice and so on. Let’s call the returned “wrapped set” (as the jQuery authors call it) a jQuery collection.

    Let’s look at the code for the jQuery function. It merely creates a new object using the init constructor.

        var jQuery = function (selector, context) {
          // The jQuery object is actually just the init constructor 'enhanced'
          return new jQuery.fn.init(selector, context, rootjQuery);
        },

    The cd:init constructor uses the jQuery prototype as its prototype.

        jQuery.fn = jQuery.prototype = {
          constructor: jQuery,
          init: function (selector, context, rootjQuery) {
            // code
          },
    
          // Start with an empty selector
          selector: "",
    
          // The current version of jQuery being used
          jquery: "1.6.1",
    
          // The default length of a jQuery object is 0
          length: 0,
    
          // The number of elements contained in the matched element set
          size: function () {
            return this.length;
          },
    
          toArray: function () {
            return slice.call(this, 0);
          },
    
          //etc

    And init is defined as part of that prototype. Notice the length property there, and an empty selector as well as some other properties and methods.

    OK, then, so what are the elements of a jQuery collection? Time for a bit more exploratory code:

    var isDOMElement = function (obj) {
      return !!obj.nodeType;
    };
    
    var dumpObj = function (o) {
      if (o.length > 0) {
        var e = o[0];
        console.log(e);
        console.log("Is DOMElement? " + isDOMElement(e));
        if (isDOMElement(e)) {
          console.log(e.nodeName);
        }
      }
      else {
        console.log("Is DOMElement? " + isDOMElement(o));
        if (isDOMElement(o)) {
          console.log(o.nodeName);
        }
      }
    };
    
    var p = $(".post");
    dumpObj(p);
    
    p = $("#post_280");
    dumpObj(p);
    
    p = $(p);
    dumpObj(p);

    I’ve written a small helper function that determines if the object passed in is a DOM element. It uses the presence/absence of the cd:nodeType property to determine this: all DOM objects have this property defining the type of the element. (1 is an ELEMENT_NODE, 2 is an ATTRIBUTE_NODE, 3 a TEXT_NODE, and so on). So we’ll assume that if the object has such a property it is a DOM element of some description. I’ve also expanded the dumpObj function a bit more. Finally I call jQuery on a class selector, an id selector, and just for fun on that last jQuery collection.

    If you run this code, you’ll see that the elements of a jQuery collection are nothing more or less than DOM elements. And the last test works just fine: wrapping a jQuery collection just returns the jQuery collection again (actually, it’s a duplicate of the first).

    Let’s investigate the cd:each method, since it’s used so often to apply some changes to all of the elements of a jQuery collection.

    Suppose we have this code:

    $(".post").each(function (index, obj) {
      // what type is obj?
    });

    A few moments with the test functions I’ve already provided will convince you that it is a DOM element. (OK, agreed, you could have looked it up in the jQuery documentation or you could have puzzled out the code itself.) But as a DOM element we’re locked out of all the cool jQuery features like animations, and so on. We have to resort to some kludgey old-style code to set attributes, set event handlers, and so on. Or do we?

    Take a look at the cd:init constructor once again. We see this code:

            // Handle $(DOMElement)
            if (selector.nodeType) {
              this.context = this[0] = selector;
              this.length = 1;
              return this;
            }

    (selector is the first parameter in the call to $; in our case the DOM element.) As you can see it wraps the DOM element as a jQuery collection of length 1. This code is really high up in the init code, way before any selector-finding logic, so executes rapidly in practice. In other words, this works very well:

    $(".post").each(function (index, obj) {
      $(obj).someCoolJQueryMethod();
    });

    Before we leave each, look at its last statement: it returns the object each was acting on. In fact this is a general feature of the jQuery methods: they all return the original collection they were called on. This is a cool feature: it actually means that we can chain calls to methods like this:

    $(".post")
      .hide("slow")
      .each(function (index, obj) {
        $(obj).css("background-color", "teal");
      })
      .show("slow");

    So: “find all elements of class ‘post’, hide them all, change the background color to teal on them all, and then show them all”. It avoids nasty code like this:

    $(".post").hide("slow");
    $(".post").each(function (index, obj) {
      $(obj).css("background-color", "teal");
    });
    $(".post").show("slow");

    Actually this brings up another point. Suppose we have code like this:

    $(".post").hide("slow");
    // other code not changing the DOM structure
    $(".post").show("slow");

    Think about what this is doing: it has to go to the DOM and query it for all the elements of class “post” using the Sizzle code. No matter how you look at it, it takes a relatively long time. Far better is to save the jQuery collection in a local variable and reuse it:

    var allPosts = $(".post");
    allPosts.hide("slow");
    // other code not changing the DOM structure
    allPosts.show("slow");

    And that’s it for now. Next time, on June 6, we’ll be looking at the basics of using jQuery in my next webinar. We’ve looked at the code, now it’s time to use it.

  • Roadmaps and promises

    I’ve just replied to a thread in our General Discussion forum that I think is worthwhile bringing to a wider audience here. The backstory is that a customer is pointing out that a particular feature promised in the roadmap didn’t make it into DXperience v2011.1 and this omission has compromised his plans for the release of his software application in the summer. Whereas I am totally sympathetic to his predicament – “WTF am I going to do now?” is what I’d be saying for sure – there’s part of me that is less so. Let me repost my reply:

    sand stone tabletphoto © 2008 Howie Le | more info (via: Wylio)Every time I write a roadmap, I insert language to say that although we hope to complete everything we describe in it, in reality some things won't get done, others will get done early or late, and yet others, previously undefined, will suddenly get done instead. Every time we publish a roadmap, someone gets upset that feature X (for some value of X) didn't make the mix during the year, and so every time I resolve that the next roadmap I write will contain stronger language pointing out the caveats. Here's the paragraph from the 2011 roadmap:

    And what are those caveats? As is usual I have to sound my standard note of caution. These plans are our best estimate at this point in time for what we should be able to do in 2011, given our resources and our understanding of the technology landscape in which we operate. Any dates given are estimates. Any functionality we describe in this roadmap, especially the further out it is, may be postponed or cancelled altogether. We strongly advise our customers not to make firm plans based on what they see here: in an industry such as ours, things can change very quickly and we have to react just as rapidly to new opportunities that may present themselves.

    Although I am sorry that the lack of X in our v2011.1 release has thrown off your plans, I honestly don't know how to make this language any clearer. The roadmap is a guide only. It's a way of communicating what we envision doing over a period of 12 months, not a set of features on engraved stone tablets from which we won't deviate.

    I firmly believe that a roadmap -- despite these caveats -- is a worthwhile document to produce for our customers. It gives them a idea of what to expect and reassurance that, heck, DevExpress is planning and executing on some great new features. It's also beneficial for us: it lays down a development path for our programming teams (so they don't go off on wild "wouldn't it be cool" tangents), and it gives strong goals for our marketing teams (booking ad space in magazines requires 3 months or so, for example), and evangelists. The alternative -- no roadmap at all -- is unacceptable to me.

    We’re all developers, right? We know that drawing up set-in-stone software development plans for a full twelvemonth is silly: there will always be events and circumstances beyond our control that will alter those “best laid plans”. However, having the guidance of those plans, although they should be treated as being more nebulous, is still valuable. I mean what I say: I believe spending the time discussing and writing a roadmap is more constructive for you, our customers, and for us than the alternative, staying quiet until we do the sneak peeks.

    We just have to be careful in how we interpret a roadmap. It’s a guide, not a set of promises.

    What do you think? Do you like the roadmap? More provocatively: Do you produce a yearly roadmap for your customers? Do you stick to it no matter what? Or are you more “event-driven”?

  • Event-Driven Programming (Message from the CTO, newsletter 47)

    You may have noticed that I’m on a JavaScript kick at the moment. My introduction to node.js and real async programming came out of that and I’m still amazed at it all.

    Schrodinger's catphoto © 2006 Jie Qi | more info (via: Wylio)Event-driven programming

    Event-driven programming? Haven't we been doing that since the dawn of time? Well, since Windows 1 at any rate? What's possibly new that we can talk about?

    Let me approach it like this: multithreaded programming is hard, very hard. It suffers from data access and sharing issues, it seems to function under the Observer effect — the observer observing the system can change its state — leading to what is colloquially known as Heisenbugs. Yet, given the state of play of the CPU hardware at the moment, surely writing multithreaded programs is the only way to go to get the performance we need?

    The answer is, surprisingly, no. Consider the new async functionality coming in C# 5.0. For a certain set of problems, the performance of a program is dependent on its I/O. Far too often a thread will sleep waiting for a read or write request to be completed and processing to continue. The C# 5.0 async functionality is designed to produce a simple way of doing asynchronous programming or "evented I/O". This allows us to write programs that do I/O in a fairly normal easy-to-read manner but that function as small request tasks with callbacks called when the request has completed. This, in turn, ensures that the CPU is being used at full-speed with minimal thread switching. Since the majority of work is being done on one thread, there are no real issues with the sharing and concurrency of data.

    In the server world as well, there's a new player in town called node.js. Node is an encapsulation of the Google V8 engine that provides an evented I/O environment for JavaScript. On the server, not on the client. This environment allows programmers to create web servers (and other kinds of servers like ftp, irc, and the like) that scale to many concurrent users easily. The reason for the scalability is that the main process never waits. All I/O is done through issuing a request to a hidden event loop, with a callback being notified (and queued on the event loop) on completion.

    So, I would recommend that you read up on asynchronous programming and evented I/O. You may be needing it sooner rather than later.

    (You can watch the video here.)

    Part of me wonders what a node-ified ASP.NET runtime would look like.

    By the way, I shall be at Tech·Ed in Atlanta next week. If you’re going too, pop by the booth to say hello and so we can talk about DevExpress’ products and services.

  • Sneak peek: Improving the navigation bar support in our VCL subscription (coming in v2011.1)

    Normally, writing about removing support for an older control in favor of the newer one is enough to get me worried. In this case, the VCL team have done a bang-up job to make the transition as painless as possible.

    In essence, we’re making the older ExpressSideBar (no, I didn’t know we had one!) obsolescent. You should be using the ExpressNavBar instead: it has more features, looks better, and is actively maintained. To help with migrating your legacy code to use ExpressNavBar, the developers on the team have implemented a design-time converter.

    The dxsbar unit has been moved to ExpressNavBar. It contains the design-time templates for the TdxSideBar, TdsSideBarStore and and TdxSideBarPopupMenu controls. Note that this means, from v2011.1.3, the dxsbar unit can be used at design time only.

    Here’s how it all works (click image to expand).

    SideBar

    On the left, you can see the TdxSideBar in a previous version of the VCL subscription. If you open the same project in the IDE with v2011.1.3 installed, you’ll see that its look has changed to a warning box stating the side bar is now deprecated and that you should convert your older code to use a TdxNavBar. Double-click on the warning box (or right-click to get the context menu shown and click on the relevant menu option), and the reference to the old TdxSideBar is changed to use the current TdxNavBar to produce the result on the right.

    After the conversion is done, you should delete the reference to the dxsbar unit from your uses clause of your application unit.

    Seems pretty simple to me and the results will make your apps look better.

  • Webinar wrap-up: Julian on JavaScript – reading jQuery (part 1)

    This time round, I took on jQuery: what can we learn about writing JavaScript code from reading the latest version of jQuery? This was not a webinar about what jQuery does but how it does it. I used version 1.5.2 of jQuery. (You can watch the webinar – full of my usual ums and ers, sorry! – here.)

    1. Again, like last time with underscore.js, the code is structured like this:

    (function (window, undefined) {
    
      // lots of code
    
    })(window);

    That is, as an autoexecuting anonymous function. Again: a very common pattern in JavaScript. This time notice that the anonymous function is called with one parameter, but that it is declared with two. The undeclared parameter will get set to the undefined value. This is merely a trick to make sure we have a valid value for undefined: JavaScript stupidly allows the global variable undefined to be changed.

    I’m in two minds about the messing around with window. I’d probably write it like this:

    (function (undefined) {
      var window = this;
      
      // lots of code
    
    })();

    The this parameter will automatically get set to the global object when the anonymous function is called.

    2. The main point about this is that local variables (and remember scope is function-based in JavaScript) are resolved faster than any other variable. So declaring window as a local variable means we can access it faster than just letting it be there at the end of the resolution chain.

    3. Next thing to note is the next to last line of code:

    window.jQuery = window.$ = jQuery;

    We’re setting the global variables jQuery and $ to the local variable. Prior to this point, all the jQuery code used the local jQuery variable.

    4. Back to the top and we have this:

    var document = window.document;

    Again, we’re capturing some value as a local variable for performance reasons.

    5. Now we get some right weird code:

    var jQuery = (function() {
    
    // Define a local copy of jQuery
    var jQuery = function( selector, context ) {
    		// The jQuery object is actually just the init constructor 'enhanced'
    		return new jQuery.fn.init( selector, context, rootjQuery );
    	},
    
    // other code   
    
    // Expose jQuery to the global object
    return jQuery;
    
    })();

    So… the local jQuery is the return value from an autoexecuting anonymous function that declares a local jQuery variable (actually a function) and returns it. Got that?

    As it happens this rather weird way of doing things is because of the way the source code is written and maintained. We’ll get back to that in a moment. (By the way, that final comment is a bit misleading; it’s not until much later on that we expose jQuery globally).

    6. Take a note of these lines:

    	// Map over jQuery in case of overwrite
    	_jQuery = window.jQuery,
    
    	// Map over the $ in case of overwrite
    	_$ = window.$,

    We’re capturing the current values of the global jQuery and $ variables that we’re going to overwrite later (see point 3 above). The reason for this is so we can declare a noConflict method:

    	noConflict: function( deep ) {
    		window.$ = _$;
    
    		if ( deep ) {
    			window.jQuery = _jQuery;
    		}
    
    		return jQuery;
    	},

    This method will reset the original values of the two global variables we’ve stomped all over in point 3. This does mean that we can, if we want, use two libraries that use $ as an identifier (Mootools is an example of this): just call $.noConflict(false) and use jQuery thereafter.

    7. Notice again that we capture the values of some prototype methods for speed purposes:

    	// Save a reference to some core methods
    	toString = Object.prototype.toString,
    	hasOwn = Object.prototype.hasOwnProperty,
    	push = Array.prototype.push,
    	slice = Array.prototype.slice,
    	trim = String.prototype.trim,
    	indexOf = Array.prototype.indexOf,

    Same principle: local variables implies faster access. Plus it’s easier to type…

    8. The next thing that struck me when I was reading the code was the declaration and use of the extend method. This is like a really popular method in the jQuery codebase and it’s worth investigating why.

    An extend function is a pretty cool function to have in your toolbox anyway. What it does is to take an object (call it the target) and add all the properties that are present in another (source) object. Or source objects. The canonical example of its use is that of an options object (sometimes called a hash) containing properties for the individual options. In your library code you can have a default options object containing default values. Here’s an example of its use, merging the default options with a user-supplied set of options:

    var defaultOptions = { animate: true, color: "red" };
    var myOptions = { color: "blue" };
    var actualOptions = $.extend({}, defaultOptions, myOptions);
    // result: { animate=true, color="blue"}
    

    So we have as target an empty object. We apply the properties from the default hash, and then we apply my changes. Simple enough, and that’s one way of using jQuery’s extend.

    The first nifty thing about jQuery’s version is that it can accept an optional boolean value as the first parameter. If this value is true, it means that properties in the target are not overwritten if they exist already. Instead it’s the properties of the object properties that will be overwritten. Simples way is to look at an example:

    var target = { point: { x: 0, y: 0, color: "red"} };
    var source = { point: { x: 10, y: 20 }, animate: true };
    $.extend(true, target, source);

    The result is target will be set to { point: { x:10, y:20, color: “red”}, animate: true }. If you like the source is “deep merged” into the target.

    Anyway the main point about this is to go read the code to see how the jQuery developers pulled off having an optional initial boolean parameter (it involves playing around with the arguments array). You may find the technique useful in your own code.

    9. The other interesting behavior of jQuery’s extend is this: if there is only one parameter, an object, it’s assumed to be a source object and the target object is assumed to be jQuery itself. If you look at the source code, you will see lots of examples of extend being called like this:

    jQuery.extend({
      //code defining a set of properties/methods
    }); 

    Why do it this way instead of having a monolithic bit of code defining the jQuery object?

    It turns out that jQuery is implemented by a team of developers each working on different parts of the main source code. The source code comprises a set of a dozen or so individual .js files and the makefile concatenates them all into the single jQuery.js file that we’ve been using. Here’s the relevant code from the makefile:

    BASE_FILES = ${SRC_DIR}/core.js\
    ${SRC_DIR}/deferred.js\
    ${SRC_DIR}/support.js\
    ${SRC_DIR}/data.js\
    ${SRC_DIR}/queue.js\
    ${SRC_DIR}/attributes.js\
    ${SRC_DIR}/event.js\
    ${SRC_DIR}/selector.js\
    ${SRC_DIR}/traversing.js\
    ${SRC_DIR}/manipulation.js\
    ${SRC_DIR}/css.js\
    ${SRC_DIR}/ajax.js\
    ${SRC_DIR}/ajax/jsonp.js\
    ${SRC_DIR}/ajax/script.js\
    ${SRC_DIR}/ajax/xhr.js\
    ${SRC_DIR}/effects.js\
    ${SRC_DIR}/offset.js\
    ${SRC_DIR}/dimensions.js
    
    MODULES = ${SRC_DIR}/intro.js\
    ${BASE_FILES}\
    ${SRC_DIR}/outro.js

    For fun, here’s the outro.js file:

    window.jQuery = window.$ = jQuery;
    })(window);

    So, for ease of developing & debugging the devs can use the individual .js files (in the right order of course). Since they are separate, they use the extend function in order to merge their pieces of functionality into the main jQuery object. This technique might be an idea to pursue if you are writing a large JavaScript library.

    10. A quick couple of extra points before I finish. The first is a simple way of creating a constant that is a string array. Typing it out by scratch (or extending an existing one) is a pain in the neck, making sure that you have typed the quotation marks and the commas. An easier idea is to use this pattern:

    props: "altKey attrChange attrName bubbles … view wheelDelta which".split(" "),

    In other words define a string with the keywords separated by spaces and then call split() on it. Much easier to type.

    11. Here’s the final second point for now. There are a few objects that are used as “translation hashes”; that is an object whose property keys are simple identifiers and whose values are more complicated or are magic numbers. One example is jQuery.props, but the better one is jQuery.fx.speeds. This hash contains properties whose keys are human-readable words (with semantic meaning) and whose values are values in milliseconds.

    	speeds: {
    		slow: 600,
    		fast: 200,
    		// Default speed
    		_default: 400
    	},

    It’s far easier to remember “slow” and ”fast” than the actual magic values. You can of course add others if you find you need them:

    $.fx.speeds[veryfast] = 150;

    It’s certainly a technique to be aware of.

    That’s it for now. In three weeks’ time I’ll be presenting a second webinar on reading and understanding jQuery. Hope to see you then.

LIVE CHAT

Chat is one of the many ways you can contact members of the DevExpress Team.
We are available Monday-Friday between 7:30am and 4:30pm Pacific Time.

If you need additional product information, write to us at info@devexpress.com or call us at +1 (818) 844-3383

FOLLOW US

DevExpress engineers feature-complete Presentation Controls, IDE Productivity Tools, Business Application Frameworks, and Reporting Systems for Visual Studio, along with high-performance HTML JS Mobile Frameworks for developers targeting iOS, Android and Windows Phone. Whether using WPF, ASP.NET, WinForms, HTML5 or Windows 10, DevExpress tools help you build and deliver your best in the shortest time possible.

Copyright © 1998-2017 Developer Express Inc.
All trademarks or registered trademarks are property of their respective owners