Archive for April, 2007

Non-record based Json calls across Domains with Ext

From a forum question I posted at Ext: http://extjs.com/forum/showthread.php?t=5430

I am trying to make a call to a webpage that returns a json object that is hierarchical in nature and not record based so as far as I am aware, jsonreader / datareader are not suitable.

The Server returns something looking like this:

   1: (
   2:     { 
   3:     children: [
   4:         { 
   5:         id : "1", 
   6:         name : "Dim Item 1", 
   7:         children : [
   8:             { 
   9:             id : "1.0", 
  10:             name : "Dim Item 1.0"
  11:             },
  12:             { 
  13:             id : "1.1", 
  14:             name : "Dim Item 1.1"
  15:             } 
  16:         ]
  17:         } 
  18:     ]
  19:     }
  20: );

Where each item can have children in a hierarchy. (I am not trying to use this data with the Ext Tree by the way)

To complicate matters the server providing the data is hosted on a different port, so I have to use the Ext.data.ScriptTagProxy to get the data, which is successful. I had a few teething problems until I realized you had to wrap the json object returned with the callback function name.
However, with my limited understanding and debugging the code, the Ext.data.ScriptTagProxy requires a reader to be supplied, but all I want in this instance is the object.

This is the client side code:

   1: function GetData()
   2: {
   3:         var url = "http://localhost:4855/largeJasonHierarchy.aspx";
   4:         var conn = new Ext.data.ScriptTagProxy({
   5:             url: url
   6:         });
   7:         
   8:         var reader = new Ext.data.ObjectReader();
   9:         conn.load({},reader,GotData);
  10: }
  11:  
  12:  
  13:  
  14: function GotData(x)
  15: {
  16:     alert(x);
  17: }

As a reader is required, I had to hack a copy of the jsonReader to create a ObjectReader that simply returns the object and does not process it.

ObjectReader.js

   1: Ext.data.ObjectReader = function(meta, recordType){
   2:     Ext.data.ObjectReader.superclass.constructor.call(this, meta, recordType);
   3: };
   4: Ext.extend(Ext.data.ObjectReader, Ext.data.DataReader, {
   5:  
   6:     readRecords : function(o){
   7:         return o;
   8:     }
   9: });

This all works, but I can’t help feeling like I’ve missed something crucial in the Ext library. Could someone with more experience than me confirm I have gone down the correct route, or let me know if there is a better way of getting json objects back in any format. (cross domain of course)
One concern, is that I have seen articles saying that any json data passed back from a server should be run through a regex parser to check that there are no functions /etc being injected in the data packets (anti-hacking and the likes) I’m not yet sure how I would fit this into the ObjectReader.
Thanks for any help.

 


 Response by Animal, notice the way he has used the Ext override to override the default implementation on ScriptTagProxy.handleResponse. 

As it stands, that’s the best way.
I think an enhancement request could be in order. If you don’t pass a reader, it should skip the call to reader.readRecords, and just call your callback passing the returned object.

That way, the following would work.

   1: conn.load({},null,GotData);

 

by adding:

   1: Ext.override(Ext.data.ScriptTagProxy, {
   2:     handleResponse : function(o, trans){
   3:         this.trans = false;
   4:         this.destroyTrans(trans, true);
   5:         var result;
   6:         if (trans.reader) {
   7:             try {
   8:                 result = trans.reader.readRecords(o);
   9:             }catch(e){
  10:                 this.fireEvent("loadexception", this, o, trans.arg, e);
  11:                 trans.callback.call(trans.scope||window, null, trans.arg, false);
  12:                 return;
  13:             }
  14:         } else {
  15:             result = o;
  16:         }
  17:         this.fireEvent("load", this, o, trans.arg);
  18:         trans.callback.call(trans.scope||window, result, trans.arg, true);
  19:     }
  20: });

Javascript Namespaces

 One of the big problems as the number of toolkits that you can use in your RIA increases is variable collision.  Constructing your classes and widgets in the form of a namespace reduces the risk that the global variables you are using will have been used by someone else.  The following code demonstrates a pattern for defining a namespace utilizing objects to create an object hierarchy for your namespace.

   1: var MyNamespace = {};
   2: MyNamespace.test = function(){
   3:         alert("MyNamespace.test");
   4: };
   5:  
   6: MyNamespace.common = {};
   7: MyNamespace.common.test = function(){
   8:         alert("MyNamespace.common.test");
   9: };
  10:  
  11: MyNamespace.utilities = {};
  12: MyNamespace.utilities.test = function(){
  13:         alert("MyNamespace.utilities.test");
  14: };
  15:  
  16: MyNamespace.common.dataaccess = {};
  17: MyNamespace.common.dataaccess.test = function(){
  18:         alert("MyNamespace.common.dataaccess.test");
  19: };
  20:  
  21:  

 

Notice that before the namespace can be assigned variables and functions, it needs to be initialized to an empty object.

This allows you to make calls like:

MyNamespace.common.dataaccess.test();

However, it is important that you only initialize the name space object once, and it is important that the full path of namespace objects be declared before you try and assign functions and properties to them.

If you want to separate your name space implementation across separate files, then you really need to check that all the stages of the namespace are assigned and create them if not. e.g.

   1: if(!MyNamespace) MyNameSpace = {};
   2: if(!MyNamespace.common ) MyNameSpace.common = {};
   3: if(!MyNamespace.common.dataaccess) MyNameSpace.common.dataaccess = {};

 

You can imagine that if your namespaces get quite deep, you start having quite a lot of code at the start of each of your Javascript files just to ensure the namespace objects are created.  There is however a very nice solution in the Ext library which helps you with this:

Ext.namespace() – this takes a variable list of namespace names and creates the objects for you if they don’t exist.

e.g.

   1: Ext.namespace("MyNamespaces","MyNamespace.common","MyNamespace.common.dataaccess");

Creating a JavaScript Singleton object

If we want to create a singleton object, i.e. there can only every be one instance of it that is referenced by a global variable, in JavaScript it is very easy.  We simply declare the class function inline, returning a new object with the public methods and properties on, directly followed by () parenthesis and assign it to our global variable.

If you want to create private methods and functions then you should be able to see the similarities of this and the JavaScript Class Patterns article.

   1: var MySingleton = function(){
   2:     return {
   3:         // variables and methods 
   4:         id : 1,
   5:  
   6:         test : function()
   7:         {
   8:             return this.id;
   9:         }
  10:     }
  11: }();

JavaScript Class pattern

The following example show a basic template of how to define a JavaScript class.  As far as I am aware this is becoming the standard pattern for allowing private and public variables and methods to be implement into a class.

How it works

The function MyClass is the constructor, note the Capitalization of the first letter to denote a constructor.  Within the function object we add methods and functions.  If we left the object definition as that, then javascript would automatically return the object definition as the result and the methods and properties we added would be public on that object. 

Instead we return a new object, not the initial object definition.  The new object has all the methods an properties that we wish to expose as public.  This is what gets passed back to the calling code.  Because of the javascript rules of scope in a function, the new object has access to any variables defined in the initial object definition. 

So the first thing we do is create a self variable that is set to this.  The public methods can then use the self variable to access any methods or variables that have been assigned to the initial object definition’s ‘this’.  In addition any other vars e.g. private1 are accessible by the public functions also.

This all works because javascript closure causes the ‘new object’ to keep a reference to the ‘initial object’ even after the constructor function has returned.

   1: // myobject.js
   2:  
   3: function MyClass(param1)
   4: {
   5:     // Private Section
   6:         
   7:     // create a reference to this, called self so the self variable 
   8:     // can then be accessed by the public object 
   9:     var self = this;
  10:     
  11:     
  12:     // Totally private variables are defined with var
  13:     var private1 = "fred";
  14:  
  15:     
  16:     // Private variable that can be accessed by the implementation of the public object only
  17:     this.private2 = "private2 data";
  18:      
  19:     
  20:     // private functions
  21:     this.privateMethod1 = function()
  22:     {
  23:         alert("private Method 1 called : private1 variable value is (" + private1 + ")");
  24:     }
  25:     
  26:     
  27:     // public Object defintion which gets returned to the outside world.
  28:     return {
  29:         publicVariable : 10,
  30:         
  31:         publicMethod1 : function()
  32:         {
  33:             alert("public method 1 called");
  34:         },
  35:         
  36:         publicMethod2 : function()
  37:         {
  38:             alert("public method 2 called about to call privatemethod1");
  39:             // Note: this refers to the current object about to returned
  40:             //       to access the private methods, we need to use 'self' 
  41:             self.privateMethod1();
  42:             alert("Private Variable (private1):" + private1);
  43:             alert("Private Variable (private2):" + self.private2);
  44:         }
  45:         
  46:     };
  47:     
  48: };
  49:  
  50: // static members and properties
  51: MyClass.prototype.staticFunction = function()
  52: {
  53:     alert("Hello from a static function");
  54: }
  55:  
  56: MyClass.prototype.staticVar = 69;

 

A test page to prove the scoping of the private and public members and properties.

 

   1: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
   2: <html>
   3:     <head>
   4:         <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
   5:         <title>Untitled Document</title>
   6:  
   7:         <script src="myobject.js" type="text/javascript"></script>
   1:  
   2:         
   3:         <link href="./css/ext-all.css" media="screen" rel="stylesheet" type="text/css">
   4:  
   5:     
   6:         <script  type="text/javascript">
   7:         var test = new MyClass("Private1 passed in by constructor");
   8:         
   9:         function callPublic1()
  10:         {
  11:             test.publicMethod1();
  12:         }
  13:         
  14:         function callPublic2()
  15:         {
  16:             test.publicMethod2();
  17:         }
  18:         
  19:         function tryCallPrivateMethod1()
  20:         {
  21:             test.privateMethod1();
  22:         }
  23:         
  24:         function tryAccessPrivateVariable()
  25:         {
  26:             alert("Private 1:" + test.private1);
  27:             alert("Private 2:" + test.private2);
  28:         } 
  29:         
  30:         function tryAccessPublicVariable()
  31:         {
  32:             alert(test.publicVariable);
  33:         } 
  34:         
  35:         function callStaticFunction()
  36:         {
  37:             MyClass.prototype.staticFunction();
  38:         }
  39:         
  40:         function getStaticVariable()
  41:         {
  42:             alert(MyClass.prototype.staticVar);
  43:         }
  44:         
  45:         
  46:         

</script>

   8:         
   9:     </head>
  10:     
  11:     <body>
  12:         <a href="javascript:callPublic1();">Call Public Method 1</a><br/>
  13:         <a href="javascript:callPublic2();">Call Public Method 2</a><br/>
  14:         <br>
  15:         <a href="javascript:tryCallPrivateMethod1();">Try and call PrivateMethod1</a> This should fail<br/>
  16:         <a href="javascript:tryAccessPrivateVariable();">Try and access private variable</a> This should return undefined as the variable does not exist<br/>
  17:         <a href="javascript:tryAccessPublicVariable();">Try and access public variable</a> This should display 10<br/>
  18:         <br>
  19:         <a href="javascript:callStaticFunction();">Call static function on class prototype</a><br/>
  20:         <a href="javascript:getStaticVariable();">Get static variable from class prototype</a> Should display 69<br/>
  21:     </body>
  22: </html>

Invocation of Functions in Javascript

There are four ways to call a function:

Function form

functionObject(arguments)

  • When a function is called in the function form, this is set to the global object (not very useful). It makes it harder to write helper functions within a method because the helper function does not get access to the outer this.
  • To get round it we assign a new variable the value this which can then be accessed by the function. 
    var that = this;
    the function can then access that.

Method form

thisObject.methodName(arguments)
thisObject["methodName"](arguments)

  • When a function is called in the method form, this is set to thisObject, the object containing the function.
  • This allows methods to have a reference to the object of interest.

Constructor form

new functionObject(arguments)

  • When a function is called with the new operator, a new object is created and assigned to this.
  • If there is not an explicit return value, then this will be returned.

Apply form

functionObject.apply(thisObject, [arguments])

  • When the function is called on the functionObject you can pass an object as the first parameter, the object passed becomes this for the scope of the function.
  • With apply, you can write a method once and then inherit it in another object, without having to rewrite the method for the new object.

typeof

typeof can be used to determine the type of an object, but it does not always return what you’d expect.  Below is a list of the return values for various types in javascript:

 type typeof 
object ‘object’
 function   ’function’
 array  ‘object’
 number  ‘number’
 string   ’string’
 boolean   ’boolean’
 null   ’object’
 undefined   ’undefined’

'x' things I didn't know about JavaScript

I’ve been watching the Douglas Crockford Javascript Programming Language videos at http://developer.yahoo.com/yui/theater/.  Here’s some bits that I didn’t know.  I recommend these videos to anyone starting out with Javascript and coming from another development language.

 

  1. Javascript has falsy values and truthy values which are used with the boolean operators.
    Falsy values are : false, null, undefined, “” (empty string), 0 (Zero) and NaN (Not a Number) 
    All other values, including objects are truthy (including “0″ and “false” as they are non zero length strings) 
  2. The + operator either adds or concatenates.  if both operands are numbers it will add them else it concatenates them. 
    Note: ‘$’ + 3 + 4 = ‘$34′ not $7
  3. All numbers are stored as 64bit floating point. Bitwise operators convert the number to a 32bit integer apply the bitwise operator and convert back to a floating point number.  Therefore x << 1 is not faster than x * 2. 
  4. Using == and != can use type coercion, so use === and !== for true equality checking of value and type and it’s therefore faster.
  5. The && and || operators don’t return a boolean value.
    && -> If the first operand is Truthy then the result is the second operand else the result is the first operand.
    || -> If the first operand is Truthy then the result is the first operand else the result is the second operand
  6. ! operator -> if the operand is Truthy the result is false else the result is true
  7. Avoid the with statement:
       1: with (o) {
       2:     foo = null;
       3: }

    does the above code set o.foo to null or a global variable foo to null.  By all accounts it depends on the object ‘o’. I guess if o does not have a foo variable then it would set the global foo.  Either way it’s recommended to avoid with.

  8. { } Blocks do not have scope. The scope is at function level.
  9. If you forget to add a var before the variable definition, javascript assumes you meant it to be global. Do this in two places with the same name and they will refer to the same global variable!
  10. Items can be removed from an array by using delete myArray[index], however this leaves sets the item at index to undefined.  To physically remove it splice(index,count) is used:
       1: myArray = ['a', 'b', 'c', 'd'];
       2: delete myArray[1];
       3: // myArray is now ['a', undefined, 'c', 'd']
       4: myArray.splice(1, 1);
       5: // myArray is now ['a', 'c', 'd']
  11. How do you determine if a variable is an array or an object ?
       1: value.constructor === Array
       2: // or
       3: value instanceof Array
  12. If you re concatenating more than 10 string elements, due a compound string being created at every stage of concatenation, add the strings to an array, then call .join to concatenate the strings in one go (by all accounts this concatenation causes less string allocations).

Various getting started with JavaScript resources (relevant to Ext)

A must view for the programmer starting out with JavaScript : http://developer.yahoo.com/yui/theater/

Have a look at the  Douglas Crockford — “The JavaScript Programming Language” 4 part video.

Private or Public ? the in’s and out’s of  declaring private and public methods and properties in JavaScript: http://phrogz.net/JS/Classes/OOPinJS.html

Inheritance in JavaScript : http://kevlindev.com/tutorials/javascript/inherita…

Ext – Creating a simple Project Template

What are the key files needed to get a project up and running using Ext?  The following lists the bare requirements to get ext running.

  1. Download and extract Ext to a folder :[Ext Download].
  2. Create a folder to store your project in.
  3. From the [Ext Download] folder, copy ext-all-debug.js (or ext-all.js if you want the release version) to the project folder.
  4. Ext can run with *YUI (Yahoo UI), Prototype/scriptaculous, or JQuery.  Copy all the files found in the [Ext Download]\adapter\[your lib choice] folder to the project folder. 
  5. Finally copy to the project folder CSS and images folders found in the [Ext Download]\resources folder.

* My first misconception about Ext was that I needed to install the appropriate library (prototype / scriptaculous / YUI / JQuery) as well as Ext to get it to run.  The Ext distribution has all the files and source from those libraries that it needs to run. E.g. for prototype, it’s all wrapped up in the one file ext-prototype-adapter.js.

* Actually as efege commented Ext includes all the necessary files from YUI.  To run with prototype or jQuery you need to download and include these in your script block as specified by the respective library.  (I would expect that these need to be included before the ext and ext adapter script files)

You now have the basic libraries ready for use, add a html file and add the following script sections to the <head>.  Note the order, it is important.  In this case I have opted for the YUI adapter.  (replace the two YUI script includes with the appropriate file name for the other libraries)

        <script src="yui-utilities.js" type="text/javascript"></script>
        <script src="ext-yui-adapter.js" type="text/javascript"></script>
        <script src="ext-all-debug.js" type="text/javascript"></script>
        <link href="./css/ext-all.css" media="screen" rel="Stylesheet" type="text/css" />