The Source for Java Technology Collaboration
User: Password:



Greg Murray

Greg Murray's Blog

JavaScript Recomendations for AJAX Component Writers

Posted by gmurray71 on March 08, 2006 at 02:00 PM | Comments (13)

With AJAX there are many choices on how to use different aspects of JavaScript. Here are some recommendations we came up with for using JavaScript with the focus on creating AJAX components that will interact with a Java technology based server. Each of these recommendations is linked to a larger document that contains more details and in many cases code samples.

  • Use JavaScript Programming Conventions

    Standardize style makes code easy to work with and maintain especially in larger organizations. See the of JavaScript Programming Conventions created by the Dojo folks.

  • Use object oriented JavaScript

    Writing object orient JavaScript will allow for code re-use, enables you or others to extend your objects, and allows your scripts to be loaded and initialized dynamically.

  • Use object hierarchies to organize JavaScript objects

    When writing components use objects and object hierarchies to organize related objects and prevent naming collision.

  • Use the prototype property to define shared behavior and to extend objects

    Use the prototype property to extend, add functionality, or provide defaults to your objects. Use the prototype property to define shared functions (behavior) across instances of an object as it will reduce the number of objects in JavaScript and its use provides a good separation of behavior from data.

  • Store state specific to the view in JavaScript and state that span pages on the server

    Store view state related to a specific page using JavaScript objects. Keep in mind that JavaScript objects are specific to a HTML page and will be lost if the "Reload" button is pressed, if the browser is relaunched/crashes, or if you navigate to another page. Store state that spans pages on the server as Java objects scoped to the HttpSession. The client and server objects should be synched on page refreshes and page loads.

  • Write reusable JavaScript

    JavaScript should not be tied to a specific component unless absolutely necessary. Consider parameterizing data in your functions instead of hard coding the data.

  • Use object literals as flexible function parameters

    Object literals are very handy in that they can be used as generic for passing in arguments to a function. Since the function signature does not change if you choose to require more properties in a function, consider using an object literal as the parameter for a function.

  • Compress your JavaScript

    Not to be confused with a zip compression scheme compression refers to removing the white spaces and shortening the names of variables and functions in a file. Consider compressing your JavaScript resources when you deploy your application.

  • Do not compress your Jar files that contain your scripts

    Do not use zip compression on jar files with scripts or styles that are served by a server side component. Compressing those jars will cause the server to decompress the file for each client request for the script or resource. Larger scripts could cause performance problems for your server.

  • Protect your server side assets

    Never put business logic or server-side access code in JavaScript. Always validate request parameters on the server regardless of whether the request originated from an AJAX client or not.

  • Consider loading JavaScript on demand

    JavaScript may be loaded dynamically at runtime using a library such as JSAN or done manually by using AJAX to load JavaScript code and calling eval() on the JavaScript. This is useful if you have a large library or set of libraries.

  • Consider using JSON for model data transport

    While the XML is still a valid format for model data transport in AJAX (especially in cases where you're communicating with XML based services or your services must also address non-AJAX based clients), you should consider using JSON to communicate data from your server to your JavaScript based client.

  • Provide a clean separation of content, CSS, and JavaScript

    A rich web application user interface is made up of content (HTML/XHTML), styles (CSS), and JavaScript. JavaScript is invoked by user gestures such as mouse clicks and can manipulate the content. Separating the CSS styles from the JavaScript is a practice which will make your code more manageable, easier to read, and easier to customize. It is recommended that the CSS and JavaScript are placed in separate files.

  • Avoid static content in JavaScript

    Keep the amount of static HTML/XHTML content in JavaScript to a minimum. This will make managing the source and updating static content easier. You may want the content in your components updateable without changing your source.

  • Use caution with element.innerHTML

    If you choose to use element.innerHTML try to write JavaScript that generates minimal HTML. Rely instead on CSS for enhancing the presentation. Remember to always strive to separate content from presentation. Make sure to de-register event listeners in the existing innerHTML of the element before re-setting the element.innerHTML as it will lead to memory leaks. Keep in mind that instances of DOM elements inside the element.innerHTML are lost when you replace the content and references to those elements will be lost as well.

  • De-reference unused objects

    Make sure you de-reference variables when they are no longer needed so they may be garbage collected. If you are using element.innerHTML, make sure you de-reference any listeners in the code before it is replaced.

  • Use care with closures

    If you use closures take caution not to hold on to references to browser objects such as DOM related objects using the local variables of a closure as this can lead to memory leak. Objects are not garbage collected until all references to objects are gone. Make sure you understand closures in order to avoid creating them accidentally.

  • Enable resource overrides in your components

    Provide a means to override the loading of resources such as dependent scripts, CSS files, or images by your JavaScript centric, JSP, Servlets, or JSF components. If you jar your component for distribution with a JSP tag or JSF component, move those resource files into the WEB-INF directory and create code to stream them out to the client. This will allow your customers to customize the component styles or JavaScript on a case by case basis without rebuilding and re-packaging the component.

  • Design with I18n in mind

    Internationalization should not be an after thought. From the JavaScript client's perspective you need to do two things: Set the page encoding and make sure localized text is passed back to your server backend. Consider using XML as the return content type for localized data as XML can specify encoding information that is understood and applied by the XMLHttpRequest object. If you are passing around localized content you need to make sure you server encodes the return content properly.

What would you add to the list?


Bookmark blog post: del.icio.us del.icio.us Digg Digg DZone DZone Furl Furl Reddit Reddit
Comments
Comments are listed in date ascending order (oldest first) | Post Comment

  • Concrete inheritance is generally avoided in "true" OOP technologies, so I dont think even js should get an exception. I also prefer placing the method definitions with the protoype call, but maybe some people are of the "header file" variety :)

    The Dojo team really knows their stuff though. I think their competition only comes from people like X. I tend to favor X, because of their JS compiler http://cross-browser.com/. I haven't even tried it yet, I just favor it because I was thinking of making the very same thing, but as an online service.

    I think everyone agrees we're not all building bindows, so why do we even need that mega js file on the first request!

    Posted by: ilazarte on March 09, 2006 at 04:06 AM

  • Great article Greg! There is something I don't quite understand. When you refer to de-registering event listeners when replacing innerHTML, what listeners are you talking about ? Does it mean that if I am replacing an element in my document, where i.e. I hava a "select" with a listener for onchange event, I should explicitly remove that listener ? Could you be more precise or give an example ?

    Posted by: gbanos on March 09, 2006 at 02:27 PM

  • On using JSON, also see The AJAX response: XML, HTML, or JSON discussion initiated by PPK. For the reasons I stated there, I prefer XHTML.

    Well, you meant model data transport, meaning that presentation is not transferred. Using coarse-grained in-place update is sometimes more practical than uncompromising Ajax application.

    Posted by: michael_jouravlev on March 09, 2006 at 03:11 PM


  • Micheal, I like your blog entry The AJAX Response: XML, HTML, or JSON in that it lays out the choices well. Regarding the "Use JSON for Model Data Transport." I originally wrote the recomendation to refer to all data transport and later realized that would mean presentation too and thus the qualifier "model data." I agree that XHTML is ideal for transfering around straight presentation.


    I have spent a bit of time playing with cross domain JSON will try to blog on that soon on the benefits and potential risks.

    Posted by: gmurray71 on March 09, 2006 at 03:31 PM

  • Regarding memory leaks with innerHTML. A great resource on this topic is JSript Memory Leaks by Douglas Crockford. There are also scripts provided to prevent such memory leaks.

    Posted by: gmurray71 on March 09, 2006 at 03:45 PM

  • It looks the Memory leak example is wrong, I dont think the script will make memory leak. Can somebody make sure for it?

    function Cart() {
    var total;
    var items = [];

    this.showTotal = function() {
    var totalDiv = document.getElementById("total");
    totalDiv.innerHTML = "$" + total;
    totalDiv = null;
    }
    }

    i do think the totalDiv = null is unneeded.

    Posted by: wangzaixiang on March 10, 2006 at 02:42 AM

  • I'm pretty sure the closures example you give doesn't create a memory leak. I haven't tested, but each element reference only lives within the local variables of the function, not the outer environment of the closure.

    The examples at the bottom of this page illustrate the problem, I think: http://simon.incutio.com/slides/2006/etech/javascript/js-reintroduction-notes.html

    Posted by: tjpalmer on March 10, 2006 at 03:06 PM

  • Oh, so in other words, I agree with wangzaixiang. I didn't read his post first.

    Posted by: tjpalmer on March 10, 2006 at 03:08 PM


  • I'm using Internet Explorer 7 Beta 2. Please don't try these scripts unless you want to potentially run your browser into the ground. I have updated the scripts to create a real leak in IE. with the BadCart. Run the script and watch your memory leak like a sieve. Reload the page and you'll see more of your precious memory go away. Many had hoped these types of leaks would get fixed with IE 7, but for now you will still see them. The GoodCart does not leak.


    function init() {
    var cart = new GoodCart();
    for (var l=0; l < 3000; l++) {
    cart.addItem("item " + l);
    }
    }

    function BadCart() {
    var total;
    var items = [];

    this.addItem = function(text) {
    var cart = document.getElementById("cart");
    var itemRow = document.createElement("div");
    var item = document.createTextNode(text);
    itemRow.appendChild(item);
    cart.appendChild(item);
    itemRow.onClick = function() {
    // do something
    }
    }
    }

    function GoodCart() {
    var total;
    var items = [];

    this.addItem = function(text) {
    var cart = document.getElementById("cart");
    var itemRow = document.createElement("div");
    var item = document.createTextNode(text);
    itemRow.appendChild(item);
    cart.appendChild(item);
    itemRow.onClick = function() {
    // do something
    }
    itemRow = null;
    item = null;
    }
    }

    For more on memory leaks in closures with IE see: Memory Leak Linkdump on Quirksmode.org.

    Posted by: gmurray71 on March 10, 2006 at 03:57 PM

  • Greg, You got to check out the Java reusable GUI Classes that generate Ajax components. The process is novel and potentially groundbreaking. The web pages:
    http://cbsdf.com/misc_docs/why-gui-api.htm
    http://cbsdf.com/misc_docs/gui-api-brief.htm

    The Java reusable GUI Classes are used like Java/Swing classes to show multiples instances of each component in the web page. Hence one can create better GUI applications than possible using Java/Swing.

    It has nice JavaScript classes and unique method to avoid name collisions.

    You must validate this for the Java developer community. What you think about this process?

    Posted by: petesadler1 on March 11, 2006 at 07:28 PM

  • I'm extra late now, but the new examples for memory leaks look accurate. Just two concerns: (1) Is there no need to dereference cart for the good example? (2) It's worth noting that item and itemRow (and others set to null) will be null if the closure is executed later. It's easy to forget that when new to the game.

    Posted by: tjpalmer on March 27, 2006 at 07:52 AM

  • Here is a Visual AJAX tool and library for AJAX Developers.

    It is free trial. http://eng.joyistar.com

    Posted by: testdll on June 12, 2006 at 07:24 PM

  • I am beginner in Java and can't add much but just want to thank you for this information. It will help me in my work.

    --------------------------------------------------------------------------------
    Statistical analysis software

    Posted by: frida1 on August 23, 2007 at 10:35 PM



Only logged in users may post comments. Login Here.


Powered by
Movable Type 3.01D
 Feed java.net RSS Feeds