Skip to content
Viscent edited this page Oct 30, 2013 · 20 revisions

[Startup]

Step 1. Define a decj module.

A decj module is plain Javascript object. This object can be returned from a Module Factory as defined by the AMD(Asynchronous Module Definition) specification. A Module Factory is usually an anonymous function.

For example,write a Javascript file as shown in below code snippet and save it to module/decjExampleModule.js:

define(["decj"],function(decj){
  return {//return the decj module object
    resources:['res/demo-basic','res/demo-explain'],/*Declare resource files required by this module*/
    events:{
      "click@#btnTest":function(){/*Declare an event handler for click event on HTML element whose ID is btnTest */
         //Write your event handling code here
      },
      "click@#chkDemoExpl":function(){
          //Write your event handling code here
      }
      //Other event binding declaration here
    },	
    init:function(data){
      //Write your module initialization code here
      alert('Welcome to decj!');
    },
    finalize:function(){
      //Write your module cleanup code here
    }
    //Declare other attributes...
  };
}

See here for a full list of attributes supported by a decj module.

Step 2. Write the application startup page.

In the startup page, add a script tag to import the RequireJS library to tell it to load the decj framework. See below code snippet:

<html>
<head>
<title>decj Guide</title>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script data-main="../js/lib/decj.js" src="../js/lib/requirejs.js"></script>
</head>
<body>
</body>
</html>

Step 3. Write your application startup code.

The decj application startup code is a function named as decjApp.In this function, you can define the first decj module to be loaded and your AMD configuration, such as shim configuration.Also, you can define your application-specific configuration here.

An application can have multiple modules, hence you need to write the application startup code only once.

Example:

function decjApp(){
  return {
    amd:{
      //Write your AMD configuration here
    },
    initialModule:"module/decjExampleModule" //Declare the initial module to be loaded here
  };
}

The initialModule attribute specifies a module to be loaded when the application startup page is loaded.Here we specify the module we defined at Step 1.

For details about attributes supported by the return value of decjApp,see here.

Add a script tag before the script tag that references to the RequireJS. And, place the decjApp function inside the script tag, as shown in below HTML code. Of course, you can also place decjApp function in a separate JS file and make the script reference to it.

<html>
<head>
<title>decj Guide</title>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
function decjApp(){
  return {
    amd:{
      //Write your AMD configuration here
    },
    initialModule:"module/decjExampleModule" //Declare the initial module to be loaded here
  };
}
</script>
<script data-main="../js/lib/decj.js" src="../js/lib/requirejs.js"></script>
</head>
<body>
</body>
</html>

Now, a simple decj application is ready. When accessing the startup page, you will see an alert box saying "Welcome to decj!".

[Application startup code]

The application startup code is a function named as decjApp. In the return value of this function, developers can define the initial decj module to be loaded, together with AMD configurations and some custom configurations.

For example,

<html>
<head>
<title>decj Guide</title>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<script>
function decjApp(){
  return {
    amd:{
      //Write your AMD configuration here
    },
    initialModule:"module/decjExampleModule" //Declare the initial module to be loaded here
  };
}
</script>
<script data-main="../js/lib/decj.js" src="../js/lib/requirejs.js"></script>
</head>
<body>
</body>
</html>

Attributes supported by the return value of the function decjApp:

Attribute Name Type Usage Memo
initialModule String|Array

Define the first decj module to be loaded when 

the decj app startup page is loaded. See [Load a decj Module] for details.

"module/aSampleModule"
amd PlainObject Define AMD configurations.
Eg.,
{
    baseUrl: './foo/bar'
}
requires Optional,String|Array Specify Javascript dependencies's module IDs for the decj application.

Eg.,

 "someDialog"

 or

["someDialog","jsLogUtil"]

[Create a decj module & Javascript Files On-demand Dynamic Load]

A decj module is a plain Javascript object. It is defined by invoking the define function which is defined by the AMD(Asynchronous Module Definition) specification.

To define a decj module,just create a Javascript file, and define a module in it by using an anonymous function. For example,

define(["decj","sha256"],function(decj,sha256){
 return {//return the decj module object
        resources:['res/demo-basic','res/demo-explain'],/*Declare resource files required by this module*/
        events:{
            "click@#btnTest":function(){/*Declare an event handler for click event on HTML element whose ID is btnTest */
               //Write your event handling code here
            },
            "click@#chkDemoExpl":function(){
                //Write your event handling code here
            }
        },	
        init:function(data){
            //Write your module initialization code here
            alert('Welcome to decj!');
        },
        finalize:function(){
            //Write your module cleanup code here
        }
     //Declare other attributes...
  };
}

The first argument for the define function specifies that the above decj module depends on two other Javascript modules: "decj" and "sha256" respectively. These module dependency Javascript files will be automatically loaded by the framework when the module is loaded.

Attributes supported by a decj module:

Attribute Name Type Usage Memo
screen String

Define the URL for the HTML code to be loaded.

Eg., "page/editMemberInfo.htm"
resources String|Array Define the URL(s) for the resource file(s) to be loaded.
Eg.,
"resources/dialog"
or
["resources/dialog","resources/menu"]
 
For details, refer to [Internationalization (i18n) & Resource Files Automatic Loading]
css String|Array Define the URL(s) for the CSS file(s) to be loaded.

Eg.,

"css/dialog.css"

or

["css/dialog.css","css/menu.css"]

For details, refer to [CSS Files On-demand Dynamic Load].

events PlainOjbect Define event bindings.

Eg.,

{
 "click@#btnTest":function(){
    //Write your event handling code here
 },
            "click@#chkDemoExpl":function(){
  //Write your event handling code here
 }
}

For details, refer to [Event Binding].

init Function Define the logic for module initialization.

Eg.,

function(){

//Write your module initialization code here

}

For details, refer to [Event Binding].

metaData PlainObject Defines the Module Business Object Metadata. For details, refer to [Form Enhancement].
metaDataURL String Defines the URL for the server-side code that provides a Module Business Object Metadata. For details, refer to [Form Enhancement].
finalize Function Define the module cleanup code

Eg.,

function(){

 xDialog.destroy();

}

[Load a decj module]

There two ways of loading a decj module, one is by declaration, the other by API invocation.

A decj application can have multiple decj modules. The decj module to be loaded when the application startup page is loaded is called the Initial Module.

For the Initial Module, you just declare the module ID, the decj will load it for you.

The Initial Module is defined via the initialModule attribute of the decj application configuration.

For example,

function decjApp(){
  return {
    amd:{
      //Write your AMD configuration here
    },
    //The decj module identified by module/decjExampleModule will be automatically loaded when
    //the startup page is loaded
    initialModule:"module/decjExampleModule"
  };
}

Behind the scene. An initial module is loaded via the API:

decj.loadModule(moduleID,loadOptions)

where,

moduleID (String) Specifies the ID of the module to be loaded.

loadOptions (Optional,PlainObject) A module loading options.

If the decj module to be loaded declares an screen attribute, then the HTML code from the URL specified by screen will be loaded into an HTML element. This HTML element is called view target.

The attributes supported by a module loading options are described as below:

 

Attribute Name

Type Usage Default Value Memo
viewTarget String

This is the ID of the HTML element container to which the decj module's UI(HTML code) will be loaded.

"wkspc"  
locale String Allows specifying a locale, zh_CN for example, to use for the decj module to be loaded. "en_US"
For details, refer to [Internationalization (i18n) & Resource Files Automatic Loading]
httpRequest PlainObject Specify an HTTP Request to be made before loading a decj module. This is useful if you want to load some data for the decj module to be loaded.  

Attributes supported are listed at table below.

See also: [Form Auto-fill]

viewRender Optional,Function Specifies a function that is responsible for rendering the UI of the decj module false  

 

Attribute Name

Type Usage Default Value Memo
url String

The URL to which the HTTP request will be made.

   
reqData String|PlainObject The request data to be sent to the server.  
 
type Optional,String Specifies the HTTP method to be used. "POST"  
contentType Optional,String The HTTP Content-Type for the HTTP request to be made.    
timeout Optional,Integer Request timeout. In milliseconds. For details,refer to http://api.jquery.com/jQuery.ajax . No default value.  
success Optional,Function A callback function to be invoked when the HTTP request is made successfully.    
error Optional,Function A callback function to be invoked when the HTTP request failed.    

[Event Binding]

To make HTML elements respond to browser events such as click,change,ect., just declare the binding in the module definition.

The events attribute of a decj module specifies event bindings. The value of events is a plain Javascript object. Each attribute of this object specifies an event binding. The attribute name is in the format of:

"Event Name@HTML Elements Selector"

The HTML Elements Selector conforms to the selectors defined by CSS(For details,refer to:http://api.jquery.com/category/selectors).

The attribute value is a function that handles an event.

For example,

events:{
  "click@#btnDemoExpl":function(){//This function handles the click event triggered by element whose ID is btnDemoExpl
    //Write your event handling code here
  },
  "change@[name=lang]":function(){//This function handles the change event triggered by element whose name attribute is set to lang
    //Write your event handling code here
  }
  //More event bindings go here...
}

[Page Initialization]

Traditionally,page initialization code should be placed in an event handler that listens to the load event of document,namely, window.onload.

For example,using jQuery,these code should be placed in an event handler as shown in below code snippet:

$(document).ready(function(){
  //place your page initialization code here
});

With decj,you do NOT need to write code to listen to the load event of document. Just declare your initilization code, and decj will invoke your code after the document is fully loaded.

The init attribute of a decj module specifies the module initialization code. The attribute value is a function. For example,

init:function(){
  //Write your module initialization code here 
}

The module initialization code will be invoked when Javascript files, CSS files, resource files and HTML file required by the module have been loaded. At this time, the images and other resources,such as Flash, may not have been loaded.

Since the decj loads Javascript files,CSS files, resource files and HTML file required by a module concurrently, the initialization code can be invoked as soon as possible.

[CSS Files On-demand Dynamic Load]

A decj module can declare its required CSS files in its definition. These CSS files will be automatically loaded by the framework when the module is loaded.

The css attribute of a decj module specifies CSS files required by the module. The attribute value is an array of URLs. If there is only one CSS file required, the attribute value can be a string. For example,

css:["css/one.css","css/two.cs","css/three.css"]

decj is locale-aware when loading CSS files for you app.

Suppose the current locale determined by decj for your app is zh_CN,the above CSS declaration will make the following CSS files be automatically loaded by the framework:

one-zh_CN.css,two-zh_CN.css,three-zh_CN.css

decj also supports loading CSS files from other domain. So that your app can take advantages of CDN(Content Delivery Network).

If the CSS files to be loaded come from a different domain,since many browsers do not provide browser events,such as onreadystatechange or onload, capable of notifying completion of CSS file loading, decj needs some special clue to determine whether a CSS is completedly loaded or not. Hence, in this case, you have to add a special CSS rule to your external CSS files. The rule should be named as #Short name of the CSS file to be loaded-Clue, and its declaration should contain display:none.

For example, your page comes from http://www.domain.com, while a CSS file to be loaded comes from http://static.domain.com/css/menu.css, you will have to add a special rule #menu-Clue to menu.css:

#menu-Clue{
  display:none;
}

[Form Ehancement]

The form enhancement features rely on Module Business Object Metadata. To use the form enhancement features, all developer need to do is to define Module Business Object Metadata and make up a normal HTML form.

Module Business Object Metadata(MBOM)

A web page can have multiple HTML forms. From a perspective of the MVC(Model-View-Controller) architecture, each form has its corresponding business object(BO) behind the scence. MBOM is a plain Javascript usded to describe information about BOs involved in a decj module. For each BO,these information include its name, alias and type. A Business Object type describes what fields a business object owns, and information about each field, including its name, alias, type, value validation rules and field value formatting requirements.

An MBOM is in the format of:

{"boMetaData":{
  "BO Type Name":{//BO Type declaration
    //Fields declaration for this BO Type
  }
  //Other BO Type declaration here
  },
  "bo":{"Name of BO":{"type":"Name of BO Type","alias":"Alias Of BO"}}
}

The alias attribute of the bo attribute specifies the name of an HTML form that refers to this BO. A BO's alias defaults to the BO's name.

Field declaration describes information about each field of a BO, it is in the format of:

"Field Name":{
  "stereoType": "Strereo Type",
  "alias":"Field Alias",
  "typeParam":{},//Declare type parameters
  "validation": {
    "Validation Rule Name": {}//Declare validation rules
  }
}

The attributes supported by a field declaration are described as below:

 

Attribute Name

Type Usage Default Value Memo
stereoType Optional,String

Specifies data type of the field value.

"String"

Predefined stereoType include:
   String,Number,Int,Decimal,Boolean,Date.


Developers can define custom Stereo Type. On how to define a custom StereoType,see the source code of the test case page.

alias Optional,String Specifies the name attribute of the HTML form control,such as a TextBox, that is responsible for collecting and displaying data for the field. The default value is owning BO's name.
 
typeParam Optional,PlainObject

Specifies additional information on data type of the field value. For example, for a field of type String, you can specify a typeParam like:


  typeParam:{min:5,max:12}


 This tells the decj that the value of the field is a String of length between 5 and 12.

{}  
validation Optional,PlainObject Specifies validation rules for the field value.  

Eg., value:

{size:{min:5,max:12}}

Details on validation rule are covered in [Automatic Form Field Validation & Formatting]

For example,

{
  "boMetaData":{
    "decj.sample.Article":{
      "title":{
        "stereoType": "String",
        "alias":"txtTitle",
        "typeParam":{min:3,max:25}
        "validation":{
          "size":{}
        }
      },
      "author":{
        "alias":"txtAuthor",
        "typeParam":{min:3,max:10}
      },
      "wordCount":{
        "stereoType":"Int",
        "typeParam":{min:500,max:6000}
      }
    }
  },
  "bo":{"article":{"type":"decj.sample.Article","alias":"frmArticle"}}
}

The above MBOM tells the decj that:

  1. The decj module that refers to this MBOM involves one BO named as article. It is of BO type decj.sample.Article.
  2. The decj module has an HTML form named as frmArticle. This form is responsible for collecting and displaying data for the article BO.
  3. For a BO of type decj.sample.Article, it has three attributes: title, author and wordCount:

title: A string of length between 3 and 25. It corresponds to an HTML form control with name attribute set to txtTitle.

author: A string of length between 3 and 10.It corresponds to an HTML form control with name attribute set to txtAuthor.

wordCount: An integer between 500 and 6000.

MBOM can be bound to a decj module in two ways:

  1. Add a metaData attribute to a decj module in the module definition.For example,
define(['dep1','dep2','dep3'],function(){
  //internal code for the module
  return {
    //...
    metaData:{
    "boMetaData":{
      "decj.sample.Article":{
        "title":{
          "stereoType": "String",
          "alias":"txtTitle",
          "typeParam":{min:3,max:25}
          "validation":{
            "size":{}
          }
        },
        "author":{
          "alias":"txtAuthor",
          "typeParam":{min:3,max:10}
        },
        "wordCount":{
          "stereoType":"Int",
          "typeParam":{min:500,max:6000}
        }
      }
    },
    "bo":{"article":{"type":"decj.sample.Article","alias":"frmArticle"}}
    }
    //...
  };

});
  1. Retrieve MBOM from server-side code.

Actually, the MBOM can be generated by server-side code or even generated automatically, for exmaple, in the Java platform by leveraging the Java Reflection API and Java Annoation.

If you want to supply the MBOM with server code, add the metaDataURL attribute to a decj module in the module definition. The value of metaDataURL is an URL for server code that is capable of providing MBOM.

For example,

define(['dep1','dep2','dep3'],function(){
  //...
  return {
    //...
    metaDataURL:"../services/BMOMGenerator/Article"
  };
  //...
});

[Form Auto-fill]

The decj automatically fills an HTML form with BO data supplied, as long as you provide an MBOM for the decj module.

There are two ways of supplying BO data to the decj.One is to use the data attribute of a decj module.

For example,

define(['dep1','dep2','dep3'],function(){
//...
  return {
    //...
    data:{
      "article":{
        "title":"Simplify the Web Front-end Developement with decj",
        "author":"Viscent",
        "wordCount":7032
      }
    }
    //...
  }; 
});

The other way is to let server-side code supply the data. In this way, you should specify the httpRequest attribute of the module loading options.

For example, in the application startup code, specify the httpRequest attribute.

function decjApp(){
  return {
    //...
    initialModule:{
      httpRequest:{
        url:"moduleGenerator.php?src=userInfoData.json"
      }
    }
    //...
  };
}

[Automatic Form AJAX Submission with JSON Support]

Data collected by an HTML form can be automatically submitted to the server side via AJAX in the format of JSON or the traditional URI-Encode(application/x-www-form-urlencoded). All developers need to do is to provide an MBOM, the decj takes the rest for you.

For example, given a form shown as below code snippet:

<html>
<body>
<form name="frmArticle" action="/registerArticle">
Title:<input type="text" name="txtTitle" value="Simplify the Web Front-end Developement with decj"></input><br>
Author:<input type="text" name="txtAuthor" value="Viscent"></input><br>
Word Count:<input type="text" name="wordCount" value="7032"></input><br>
<input type="submit" name="Submit"></input>
</form>
</body>
</html>

And below BMOM:

metaData:{
  "boMetaData":{
    "decj.sample.Article":{
      "title":{
        "stereoType": "String",
        "alias":"txtTitle",
        "typeParam":{min:3,max:25}
        "validation":{
          "size":{}
        }
      },
      "author":{
        "alias":"txtAuthor",
        "typeParam":{min:3,max:10}
      },
      "wordCount":{
        "stereoType":"Int",
        "typeParam":{min:500,max:6000}
      }
    }
  },
  "bo":{"article":{"type":"decj.sample.Article","alias":"frmArticle"}}
}

After the Submit button being clicked, the decj will send an AJAX request to the server. The requested URL is /registerArticle,the HTTP method is POST.And the HTTP Body is:

{
 "article":{
   "title":"Simplify the Web Front-end Developement with decj",
   "author":"Viscent",
   "wordCount":7032
 }
}

If you want to submit the form data using URI-encoding or other HTTP method(PUT for example), you can use the Form Descriptor, which is the forms attribute of a decj module.

The forms attribute of a decj module allows you define Form Descriptor for each form involved. The value of the forms attribute is in the format:

forms:{
  "Form Name 1":{
    //Form Descriptor for Form 1
  },
  "Form Name 2":{
    //Form Descriptor for Form 2
  }
  //....
}

For example,

forms:{
  "userInfo":{
    method:'PUT',
    filter:function(form,data,originalData){
      var pwd=data.passwd;
      var pwdHash=CryptoJS.SHA256(pwd).toString();
      data.passwd=pwdHash;
    },
    submitSuccess:function(data){
      alert("Server date:"+data.date+"\n"+"res form.submit.ok".val({memberId:data.id}));
    }
  }
}

The attributes supported by a Form Descriptor are shown as below:

			<tr>
				<td>
					filter</td>
				<td>
					Optional,Function</td>
				<td>
					This is a hook function to be invoked after the data collected by a form has been packaged. This allows further adjustment of form data to be submitted. The function will receive, at most, three arguments from the decj.<br />
					&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <em>aFormFilter</em>(eleForm,packagedFormData,formBackingData)<br />
					&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;<br />
					&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <em>eleForm</em> [HTMLElement] The HTML form.<br />
					&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <em>packagedFormData</em> [PlainObject] The form data assembled.<br />
					&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <em>formBackingData</em> [Optional,PlainObject] The original data used to fill in the HTML form, if any.</td>
				<td>
					&nbsp;</td>
				<td>
					&nbsp;</td>
			</tr>
			<tr>
				<td>
					encodingType</td>
				<td>
					Optional,String</td>
				<td>
					It has the same meaning as that of the <em>enctype</em> attribute of an HTML form. The difference is that it allows you specifying values like <em>application/x-json</em>, which is not supported by an HTML form.</td>
				<td>
					&quot;application/json&quot;</td>
				<td>
					&nbsp;</td>
			</tr>
			<tr>
				<td>
					timeout</td>
				<td>
					Optional,Integer</td>
				<td>
					See the <em>timeout</em> attribute in the jQuery doc: http://api.jquery.com/jQuery.ajax/&nbsp;</td>
				<td>
					&nbsp;</td>
				<td>
					&nbsp;</td>
			</tr>
			<tr>
				<td>
					submitSuccess</td>
				<td>
					Optional,Function</td>
				<td>
					A callback function to be invoked after the form being successfully submitted.<br />
					&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <em>aSubmitSuccessCallback</em>(objResponse)<br />
					&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <em>objResponse</em> [String|Object] The response received from the server upon form submission.&nbsp;</td>
				<td>
					&nbsp;</td>
				<td>
					&nbsp;</td>
			</tr>
			<tr>
				<td>
					fail</td>
				<td>
					Optional,Function</td>
				<td>
					A callback function to invoked after the form submission failed.<br />
					&nbsp;&nbsp;&nbsp;&nbsp; <em>ASubmitFailedCallback</em>(jqXHR,textStatus, errorThrown);<br />
					&nbsp;&nbsp;&nbsp;&nbsp; See http://api.jquery.com/jQuery.ajax/ for details.</td>
				<td>
					&nbsp;</td>
				<td>
					&nbsp;</td>
			</tr>

 

Attribute Name

Type Usage Default Value Memo
processor Optional,String

It has the same meaning as that of the action attribute of an HTML form.

   
method Optional,String It has the same meaning as that of the method attribute of an HTML form. The difference is that: an HTML form only supports GET and POST, while this attribute supports any valid HTTP methods, such as PUT and DELETE, as long as the server supports. "POST"
 
By default, the decj submits a form in the format of JSON. If you want to submit form in the format of URI-encode.Just set the _encodingType_ attribute of the corresponding Form Descriptor to _application/x-www-form-urlencoded_. ## [Automatic Form Field Validation & Formatting]

The decj supports two kinds of validation. One is based on Stereotype of a field, the other based on validation rules.

A Stereotype implies some kind of validation. For example, a field with Stereotype declared to Decimal rejects any value that contains non-digit characters(except ".").

Suppose there is field named as mgmtExpr, it represents the Management Experiences of a project manager in hours. Hence, the suitable Stereotype for this field is Decimal. One may declare this field in the MBOM like below:

 "mgmtExpr":{
  "stereoType": "Decimal",
  "typeParam":{"locale":"cn","fraction":2}
  }

When a user types a value like 10OX.02, the decj will automatically rejects the value since it is not a valid Decimal.

The other type of validation is based on validation rule. A validation rule is a name for a specific validation logic. It is declared via the validation attribute of a field declaration. The decj comes with some predefined validation rules you can choose, as shown in table:

 

Rule Name

Meaning Rule Arguments Implied by Stereo Type Example
Size Check the size of a string min,max String {Size:{min:5,max:12}}
NotNull Check that a value cannot be empty     {NotNull:{}}
Min Check the minimum value of an Integer value   {Min:{value:10}}
Max Check the maximum value of an Integer value   {Max:{value:100}}

For example, an MBOM has following field declaration:

"lastName": {
  validation:{
    "size":{min:3,max:10}
  }
}

Hence, the valid value for the field lastName is a String of size between 3 and 10 characters.

A Stereotype can imply some validation rules. For example, a String implies the Size validation rule.

Hence,

"lastName": {
  validation:{
    "size":{min:3,max:10}
  }
}

is equivalent to:

"lastName": {
  "typeParam":{min:3,max:10}
}