Table
Of Contents
1. Introduction
2. Topics covered
3. What AJAX says?
4. Explore SmartClient
5. Isomorphic products
6. Comparison with other RIA Frameworks
7. Visual Builder
8. Tune SmartClient
9. Complex UIs using SmartClient for reference only
9.1 Example 1
9.2 Example 2
9.3 Example 3
10. Customizing SmartClient
10.1 Customizing default theme
10.2 Change default Chart engine support
10.3 Download list grid data as CSV without Server trip
11. References
1. Introduction
SmartClient
SmartClient combines the
industry's richest set of cross-browser UI components with a Java server
framework to provide an end-to-end solution for building business web
applications.
SmartClient is an Ajax
framework created by Isomorphic Software. First released in 2001 and since
November 2007, SmartClient has been available free under an open source LGPL
license.
AJAX - Asynchronous JavaScript and XML
In web application
development, an AJAX framework is a framework which leverages AJAX, a
collection of technologies for building dynamic web pages on the client side.
While data is read from and sent to the server by JavaScript requests,
frameworks may include server-side components to process the client's requests.
License
The GNU Lesser General
Public License (formerly the GNU Library General Public License) or LGPL is a
free software license published by the Free Software Foundation (FSF).
GPL – The GPL is the first
copy left license for general use, which means that derived works can only be
distributed under the same license terms.
LGPL – In addition to GPL, it
allows the work to be linked with (in the case of a library, 'used by') a
non-(L)GPLed program, regardless of whether it is free software or proprietary
software
2. Topics covered
1.
What
AJAX says?
2.
Explore
SmartClient
3.
Isomorphic
products
4.
Comparison
with other RIA Frameworks
5.
Visual
Builder
6.
Tune
SmartClient
7.
Complex
UIs using SmartClient
8.
Customizing
SmartClient
9.
References
3. What AJAX says?
You might have been seen/using
Client-Server model in model in most of the Web applications.
In this model, whenever user makes a http
request to the server, complete user view flashes for a second and new view is
rendered via server. This is in general
for thin clients.
Now a days clients are getting thick (high
configuration systems). AJAX works
better with thick client environment.
AJAX
With the help of AJAX (Asynchronous
JavaScript and XML), once the view is rendered, only components (forms &
controls) present in a view can be redrawn instead of drawing complete page
view.
Reverse
AJAX
Reverse AJAX or Comet is a web application
model in which a long-held HTTP request allows a web server to push data to a
browser, without the browser explicitly requesting it.
1. Explore SmartClient
There
are two basic and important structures in SmartClient
1. Class - The Class
object is root of the Isomorphic SmartClient inheritance tree -- it includes
functionality for creating instances, adding methods and properties, getting
prototypes, etc.
2. Canvas - Canvas extends
Class and is the base abstraction for cross-browser DHTML drawing. All DHTML
widgets inherit from the Canvas class.
Basic
layouts
Likewise HTML there is various
structures/layouts/containers corresponding in SmartClient to hold the
different components for drawing a UI.
Like in HTML you have DIV, TABLE, and FORM etc. Below is the comprehension list of basic
layouts to be used in SmartClient:
1. Layout
Mother of all
layouts. It is a subclass of Canvas that
automatically arranges other Canvases according to a layout policy
2. VLayout/HLayout
A subclass of
Layout that applies a sizing policy along the vertical/horizontal axis,
interpreting percent and "*" sizes as proportions of the height/width
of the layout. VLayouts/HLayouts will set any members that do not have explicit
widths/heights to match the layout.
3. VStack/HStack
A subclass of
Layout that simply stacks members on the vertical/horizontal axis without
trying to manage their height/width. On the horizontal/vertical axis, any
members that do not have explicit widths/heights will be sized to match the width/height
of the stack.
Difference between
XStack and XLayout
The XStack layout
has predefined LayoutPolicy as
"none" - Layout does not try to size members
on the axis at all, merely stacking them (length axis) and leaving them at
default breadth.
The XLayout layout
has predefined LayoutPolicy as
"fill"
- Layout sizes members so that they fill the specified size of the layout. The
rules are:
·
Any component given
an initial pixel size, programmatically resized to a specific pixel size, or
drag resized by user action is left at that exact size
·
Any component that
autofits is given exactly the space it needs, never forced to take up more.
·
All other
components split the remaining space equally, or according to their relative
percentages.
4. Toolbar
A Toolbar creates a
vertical or horizontal strip of similar components (typically Buttons) and
provides managed resizing and reordering behavior over those components.
5. ToolStrip
Base class for
creating toolstrips like those found in browsers and office applications: a
mixed set of controls including icon buttons, radio button groups, menus,
comboBoxes, spacers, status displays and drop-down selects.
Other than above
there are other layouts as well like RibbonGroup and SectionStack etc. But these in turn are either of type VLayout
or HLayout and inherits the behavior and layout policies from parent.
Controls
corresponding to HTML
·
For
HTML FORM control, SmartClient has DynamicForm control.
·
For
all HTML FORM controls, like text box in SmartClient there are different
FormItem controls TextItem, RadioItem, CheckboxItem etc.
·
For
HTML TABLE control, SmartClient has ListGrid control.
·
For
HTML alert control, SmartClient has isc.say control.
etc.
There
are many other controls that may fit into your project requirements.
Let’s
have some coding exercise
Preliminary
Before we start our coding session you need
to download SmartClient JS libraries using download link from:
Once you download the SmartClient, you will
find SmartClient specific JS libraries in [ROOT_FOLDER]\smartclientSDK\isomorphic
Either you can copy isomorphic folder to your
application folder or put your examples in parallel to it.
The coding examples we would be using would
have some part of fix/common code to include SmartClient JS libraries and theme
for SmartClient controls. Just for your
information we would be using “EnterpriseBlue”
theme in our examples, you can change it any time:
Here I am considering that we would be
keeping our file in parallel to isomorphic folder mentioned above. Below is the common code we would be
referring in examples for the sake of convenience.
<!-- isomorphic JS
-->
<SCRIPT>var
isomorphicDir = "isomorphic/";</SCRIPT>
<SCRIPT
SRC="isomorphic/system/modules/ISC_Core.js"></SCRIPT>
<SCRIPT
SRC="isomorphic/system/modules/ISC_Foundation.js"></SCRIPT>
<SCRIPT
SRC="isomorphic/system/modules/ISC_Containers.js"></SCRIPT>
<SCRIPT
SRC="isomorphic/system/modules/ISC_Grids.js"></SCRIPT>
<SCRIPT
SRC="isomorphic/system/modules/ISC_Forms.js"></SCRIPT>
<SCRIPT
SRC="isomorphic/system/modules/ISC_DataBinding.js"></SCRIPT>
<SCRIPT
SRC="isomorphic/system/modules/ISC_PluginBridges.js"></SCRIPT>
<!-- Isomorphic Skin
-->
<SCRIPT
SRC="isomorphic/skins/EnterpriseBlue/load_skin.js"></SCRIPT>
|
1. Example - “Hello
World”
<HTML>
<HEAD><TITLE>SmartClient
demo</TITLE></HEAD>
<BODY>
... Common SmartClient code ...
<SCRIPT LANGUAGE="JavaScript">
isc.IButton.create({
title: "Hello",
icon: "<AN_ICON_PATH>",
iconOrientation: "right",
click: "isc.say('Hello
world!')"
})
</SCRIPT>
</BODY>
</HTML>
|
Output:
Explanation:
isc.IButton.create
This line creates
the Isomorphic SmartClient object of type “IButton”
title: "Hello",
This line set the
“title” property of IButton
icon: "<AN_ICON_PATH>",
This line set the
“icon” property of IButton that would be displayed along with title.
iconOrientation: "right",
This line set the
“iconOrientation” property of IButton that decides where to display icon in
alignment with title.
click: "isc.say('Hello world!')"
This line attach
the onclick event with IButton and whenever user takes click action on this
object and isc.say i.e. an alert window would be displayed to user.
Point of
improvements:
As in java there is
concept of inheritance, same applies in SmartClient. For example if you have created 100s of such
IButtons in your project and as per project demand you need to either change
the icon or text color etc then changing all 100s of IButton would be teditious
task. SmartClient allows you to extend
available objects and set default properties.
<HTML>
<HEAD><TITLE>SmartClient
demo</TITLE></HEAD>
<BODY>
... Common SmartClient code ...
<SCRIPT
LANGUAGE="JavaScript">
isc.defineClass("CustomIButton",
"IButton").addMethods({
redrawOnResize: false,
width:
150,
height:
30,
imageType: "normal",
icon:
"<AN_ICON_PATH>",
iconOrientation: "right",
autoDraw:false
});
isc.CustomIButton.create({
title: "Hello",
click: "isc.say('Hello
world!')"
})
</SCRIPT>
</BODY>
</HTML>
|
As you can see that
few of default properties are already set and whenever you will
create
“CustomIButton” these will be applied, so you will save lot of code
replication. Also, this extension
applies to each and every component of SmartClient.
2. Example - “List
Grid”
List Grid is the
most powerful and useful tool introduced by SmartClient. It has many features that we would be
discussing later in this ASL.
Any information
that needs to be displayed in tabular format, list grid can be used. It has many features like grouping, sorting,
filtering, moving columns, formatting, show/hide columns, freezing a column
etc.
The data that would
be using in list grid examples is constant and as below:
countryData = [
{
continent:"North America",
countryName:"United States",
countryCode:"US",
area:9631420,
population:298444215,
gdp:12360.0,
independence:new Date(1776,6,4),
government:"federal republic",
government_desc:2,
capital:"Washington, DC",
member_g8:true,
article:"http://en.wikipedia.org/wiki/United_states"
},
{
continent:"Asia",
countryName:"China",
countryCode:"CH",
area:9596960,
population:1313973713,
gdp:8859.0,
government:"Communist state",
government_desc:0,
capital:"Beijing",
member_g8:false,
article:"http://en.wikipedia.org/wiki/China"
},
{
continent:"Asia",
countryName:"Japan",
countryCode:"JA",
area:377835,
population:127463611,
gdp:4018.0,
government:"constitutional monarchy with parliamentary
government",
government_desc:1,
capital:"Tokyo",
member_g8:true,
article:"http://en.wikipedia.org/wiki/Japan"
},
{
continent:"Asia",
countryName:"India",
countryCode:"IN",
area:3287590,
population:1095351995,
gdp:3611.0,
independence:new Date(1947,7,15),
government:"federal republic",
government_desc:2,
capital:"New Delhi",
member_g8:false,
article:"http://en.wikipedia.org/wiki/India"
},
{
continent:"Europe",
countryName:"Germany",
countryCode:"GM",
area:357021,
population:82422299,
gdp:2504.0,
independence:new Date(1871,0,18),
government:"federal republic",
government_desc:2,
capital:"Berlin",
member_g8:true,
article:"http://en.wikipedia.org/wiki/Germany"
},
{
continent:"Europe",
countryName:"United Kingdom",
countryCode:"UK",
area:244820,
population:60609153,
gdp:1830.0,
independence:new Date(1801,0,1),
government:"constitutional monarchy",
government_desc:1,
capital:"London",
member_g8:true,
article:"http://en.wikipedia.org/wiki/United_kingdom"
},
{
continent:"Europe",
countryName:"France",
countryCode:"FR",
area:547030,
population:60876136,
gdp:1816.0,
government:"republic",
government_desc:5,
capital:"Paris",
member_g8:true,
article:"http://en.wikipedia.org/wiki/France"
},
{
continent:"Europe",
countryName:"Italy",
countryCode:"IT",
area:301230,
population:58133509,
gdp:1698.0,
independence:new Date(1861,2,17),
government:"republic",
government_desc:5,
capital:"Rome",
member_g8:true,
article:"http://en.wikipedia.org/wiki/Italy"
},
{
continent:"Asia",
countryName:"Russia",
countryCode:"RS",
area:17075200,
population:142893540,
gdp:1589.0,
independence:new
Date(1991,7,24),
government:"federation",
government_desc:3,
capital:"Moscow",
member_g8:true,
article:"http://en.wikipedia.org/wiki/Russia"
},
{
continent:"South America",
countryName:"Brazil",
countryCode:"BR",
area:8511965,
population:188078227,
gdp:1556.0,
independence:new Date(1822,8,7),
government:"federative republic",
government_desc:3,
capital:"Brasilia",
member_g8:false,
article:"http://en.wikipedia.org/wiki/Brazil"
},
{
continent:"North America",
countryName:"Canada",
countryCode:"CA",
area:9984670,
population:33098932,
gdp:1114.0,
independence:new Date(1867,6,1),
government:"constitutional monarchy with parliamentary democracy
and federation",
government_desc:1,
capital:"Ottawa",
member_g8:true,
article:"http://en.wikipedia.org/wiki/Canada"
},
{
continent:"North America",
countryName:"Mexico",
countryCode:"MX",
area:1972550,
population:107449525,
gdp:1067.0,
independence:new Date(1810,8,16),
government:"federal republic",
government_desc:2,
capital:"Mexico (Distrito Federal)",
member_g8:false,
article:"http://en.wikipedia.org/wiki/Mexico"
},
{
continent:"Europe",
countryName:"Spain",
countryCode:"SP",
area:504782,
population:40397842,
gdp:1029.0,
independence:new Date(1492,0,1),
government:"parliamentary monarchy",
government_desc:4,
capital:"Madrid",
member_g8:false,
article:"http://en.wikipedia.org/wiki/Spain"
},
{
continent:"Asia",
countryName:"South Korea",
countryCode:"KS",
area:98480,
population:48846823,
gdp:965.3,
independence:new Date(1945,7,15),
government:"republic",
government_desc:5,
capital:"Seoul",
member_g8:false,
article:"http://en.wikipedia.org/wiki/South_korea"
},
{
continent:"Asia",
countryName:"Indonesia",
countryCode:"ID",
area:1919440,
population:245452739,
gdp:865.6,
independence:new Date(1945,7,17),
government:"republic",
government_desc:5,
capital:"Jakarta",
member_g8:false,
article:"http://en.wikipedia.org/wiki/Indonesia"
}
];
|
List grid example:
<HTML>
<HEAD><TITLE>SmartClient
demo</TITLE></HEAD>
<BODY>
... Common SmartClient code ...
<SCRIPT
LANGUAGE="JavaScript">
... PLACE COUNTRYDATA HERE ...
isc.ListGrid.create({
ID:
"countryList",
width:500, height:224, alternateRecordStyles: true, canDragSelect:
true,
sortFieldNum: 1,
data: countryData,
fields:[
{name:"countryCode", title:"Flag", width:50,
type:"image", imageURLPrefix:"flags/16/",
imageURLSuffix:".png"},
{name:"countryName", title:"Country"},
{name:"capital", title:"Capital"},
{name:"population", title:"Population",
type:"number",
formatCellValue:"isc.Format.toUSString(value)"}
],
getCellCSSText: function (record, rowNum, colNum) {
if
(this.getFieldName(colNum) == "population") {
if (record.population > 1000000000) {
return "font-weight:bold; color:red;";
} else if (record.population < 50000000) {
return "font-weight:bold; color:blue;";
}
}
}
}) </SCRIPT>
</BODY>
</HTML>
|
Output:
Explanation:
The data that used
to populate list grid is JSON (java script object notation).
ID - that is used
in example above defines list grid uniquely and can be used to operate on this
object conditionally.
data – is a list
grid property that can have XML or JSON records and used to populate list grid. Later we will learn how to populate this data
from server with the help of data source.
fields – is the set
of columns that would be drawn into list grid.
getCellCSSText - is
a function available for list grid and can be over written to override the
behavior of default functionality.
3. Example - “List
Grid” Sorting
<HTML>
<HEAD><TITLE>SmartClient
demo</TITLE></HEAD>
<BODY>
... Common SmartClient code ...
<SCRIPT
LANGUAGE="JavaScript">
... PLACE COUNTRYDATA HERE ...
isc.ListGrid.create({
ID:
"countryList",
width:500, height:224, alternateRecordStyles:true,
data:
countryData,
fields:[
{name:"countryCode", title:"Flag", width:50,
type:"image", imageURLPrefix:"flags/16/", imageURLSuffix:".png"},
{name:"countryName", title:"Country"},
{name:"population", title:"Population",
formatCellValue:"isc.Format.toUSString(value)"},
{name:"area", title:"Area (km²)",
formatCellValue:"isc.Format.toUSString(value)"}
],
//
initial sort on Population, high-to-low
sortFieldNum: 2,
sortDirection: "descending"
})
</SCRIPT>
</BODY>
</HTML>
|
Output:
4. Example - “List
Grid” Filtering
<HTML>
<HEAD><TITLE>SmartClient
demo</TITLE></HEAD>
<BODY>
... Common SmartClient code ...
<SCRIPT
LANGUAGE="JavaScript">
... PLACE COUNTRYDATA HERE ...
isc.DataSource.create({
ID: "worldDS",
clientOnly: true,
testData: countryData
});
isc.ListGrid.create({
ID:
"countryList",
width:500, height:300, alternateRecordStyles:true,
dataSource: worldDS,
fields:[
{name:"countryCode", title:"Code", width:50},
{name:"countryName", title:"Country"},
{name:"capital", title:"Capital"},
{name:"continent",
title:"Continent"}
],
autoFetchData: true,
showFilterEditor: true
})
</SCRIPT>
</BODY>
</HTML>
|
Output:
Explanation:
A DataSource is data-provider-independent
description of a set of objects that will be loaded, edited and saved within
the user interface of your application.
Each DataSource consists of a list of
fields that make up a DataSource record, along with field types, validation
rules, relationships to other DataSources, and other metadata.
Abstract description:
Isomorphic
SmartClient
|
Relational
Database
|
Enterprise
Java Beans (EJB)
|
Entity/Relationship
Modeling
|
OO/UML
|
XML
Schema/WSDL
|
LDAP
|
DataSource
|
Table
|
EJB
class
|
Entity
|
Class
|
Element
Schema (ComplexType)
|
Objectclass
|
Record
|
Row
|
EJB
instance
|
Entity
instance
|
Class
instance/Object
|
Element
instance (ComplexType)
|
Entry
|
Field
|
Column
|
Property
|
Attribute
|
Property/Attribute
|
Attribute
or Element (SimpleType)
|
Attribute
|
5. Example - “List
Grid” Grouping
<HTML>
<HEAD><TITLE>SmartClient
demo</TITLE></HEAD>
<BODY>
... Common SmartClient code ...
<SCRIPT
LANGUAGE="JavaScript">
... PLACE COUNTRYDATA HERE ...
isc.DataSource.create({
ID: "worldDS",
clientOnly: true,
testData: countryData
});
isc.ListGrid.create({
ID: "countryList",
width:522, height:224,
alternateRecordStyles:true,
cellHeight:22,
dataSource: worldDS,
// display a subset of fields from the
datasource
fields:[
{name:"countryName"},
{name:"government"},
{name:"continent"},
{name:"countryCode",
title:"Flag", width:40, type:"image",
imageURLPrefix:"flags/16/", imageURLSuffix:".png",
canEdit:false}
],
groupStartOpen:"all",
groupByField: 'continent',
autoFetchData: true
}) </SCRIPT>
</BODY>
</HTML>
|
Output:
6. Example - “List
Grid” Editing
<HTML>
<HEAD><TITLE>SmartClient
demo</TITLE></HEAD>
<BODY>
... Common SmartClient code ...
<SCRIPT
LANGUAGE="JavaScript">
... PLACE COUNTRYDATA HERE ...
isc.DataSource.create({
ID: "worldDS",
clientOnly: true,
testData: countryData
});
isc.ListGrid.create({
ID:
"countryList",
width:550, height:224, alternateRecordStyles:true, cellHeight:22,
// use
server-side dataSource so edits are retained across page transitions
dataSource: worldDS,
//
display a subset of fields from the datasource
fields:[
{name:"countryCode", title:"Flag", width:40,
type:"image", imageURLPrefix:"flags/16/", imageURLSuffix:".png",
canEdit:false},
{name:"countryName"},
{name:"continent"},
{name:"member_g8"},
{name:"population",
formatCellValue:"isc.Format.toUSString(value);"},
{name:"independence"}
],
autoFetchData: true,
canEdit:
true,
editEvent: "click"
})
</SCRIPT>
</BODY>
</HTML>
|
Output:
Explanation:
In above example
the data source is not associated to any database or any other data provider
service. Unless this is connected to
some data service provider the changes made in example will not persist.
7. Example - “Layouts
(HLayout and VLayout)”
<HTML>
<HEAD><TITLE>SmartClient
demo</TITLE></HEAD>
<BODY>
... Common SmartClient code ...
<SCRIPT
LANGUAGE="JavaScript">
// There are 3 HLayout examples and 3
VLayout examples
//
// 1. HLayout with
layout.align = 'center'
// 2. HLayout with
member.layoutAlign = 'center' (or layout.defaultLayoutAlign = 'center')
// 3. HLayout with
LayoutSpacers
// 4. VLayout with
layout.align = 'center'
// 5. VLayout with member.layoutAlign
= 'center' (or layout.defaultLayoutAlign = 'center')
// 6. VLayout with
LayoutSpacers
// 1. HLayout with
layout.align = 'center'
//
// This centers the
members along the horizontal axis of the HLayout.
// Note that the members
have a specified width that is less than the
// width of the HLayout
-- otherwise, you would not see the centering
// visually!
isc.HLayout.create({
ID: "hLayoutAlignCenter",
autoDraw: false,
// Specifying the width creates space
within which to
// center the members.
width: "100%",
height: "100%",
layoutMargin: 6,
membersMargin: 6,
border: "1px dashed blue",
align: "center", // As promised!
members: [
isc.Canvas.create({
height: 40,
width: 40,
backgroundColor: "red"
}),
isc.Canvas.create({
height: 40,
width: 40,
backgroundColor:
"green"
}),
isc.Canvas.create({
height: 40,
width: 40,
backgroundColor: "blue"
})
]
});
// 2. HLayout with
member.layoutAlign = 'center' (or layout.defaultLayoutAlign = 'center')
//
// This centers every
member along the vertical axis of the HLayout.
// If you don't want to
center *every* member vertically, you can
// instead specify the
layoutAlign property on individual members.
// Note that the height
of the members is fixed -- if they filled
// the layout, you
wouldn't see the centering.
isc.HLayout.create({
ID: "hLayoutDefaultLayoutAlign",
autoDraw: false,
// Specifying the height creates space
within which to
// center the members.
height: "100%",
width: "100%",
layoutMargin: 6,
membersMargin: 6,
border: "1px dashed blue",
defaultLayoutAlign: "center",
// As promised!
members: [
isc.Canvas.create({
height: 40,
width: 40,
backgroundColor: "red"
}),
isc.Canvas.create({
height: 40,
width: 40,
backgroundColor:
"green"
}),
isc.Canvas.create({
height: 40,
width: 40,
backgroundColor: "blue"
})
]
});
// 3. HLayout with
LayoutSpacers
//
// This example uses
LayoutSpacers as members to center one member in the space
// remaining after the
first member is drawn. Note that it is the positioning
// of the two
LayoutSpacer members that creates the centering ... no alignment
// property is used.
isc.HLayout.create({
ID: "hLayoutLayoutSpacers",
autoDraw: false,
// Specifying the width creates space for
the LayoutSpacers to distribute.
width: "100%",
height: "100%",
layoutMargin: 6,
membersMargin: 6,
border: "1px dashed blue",
// Note no alignment property! It's all done
with LayoutSpacers
members: [
isc.Label.create({
height: 40,
width: "33%",
padding: 10,
backgroundColor: "red",
contents: "<b>No
alignment</b>"
}),
isc.LayoutSpacer.create(), // Note
the use of the LayoutSpacer
isc.Label.create({
height: 40,
width: "33%",
padding: 10,
backgroundColor:
"green",
contents: "<b>Centered
in remaning space</b>"
}),
isc.LayoutSpacer.create() // And
another layout spacer
]
});
// 4. VLayout with
layout.align = 'center'
//
// This centers the
members along the vertical axis of the VLayout.
// Note that the members
have a specified height that is less than the
// height of the VLayout
-- otherwise, you would not see the centering
// visually!
isc.VLayout.create({
ID: "vLayoutAlignCenter",
autoDraw: false,
// Specifying the height creates space
within which to
// center the members.
height: "100%",
width: "100%",
layoutMargin: 6,
membersMargin: 6,
border: "1px dashed blue",
align: "center", // As promised!
members: [
isc.Canvas.create({
height: 40,
width: 40,
backgroundColor: "red"
}),
isc.Canvas.create({
height: 40,
width: 40,
backgroundColor:
"green"
}),
isc.Canvas.create({
height: 40,
width: 40,
backgroundColor: "blue"
})
]
});
// 5. VLayout with
member.layoutAlign = 'center' (or layout.defaultLayoutAlign = 'center')
//
// This centers every
member along the horizontal axis of the VLayout.
// If you don't want to
center *every* member horizontally, you can
// instead specify the
layoutAlign property on individual members.
// Note that the width
of the members is fixed -- if they filled
// the layout, you
wouldn't see the centering.
isc.VLayout.create({
ID:
"vLayoutDefaultLayoutAlign",
autoDraw: false,
// Specifying the width creates space
within which to
// center the members.
width: "100%",
height: "100%",
layoutMargin: 6,
membersMargin: 6,
border: "1px dashed blue",
defaultLayoutAlign: "center",
// As promised!
members: [
isc.Canvas.create({
height: 40,
width: 40,
backgroundColor: "red"
}),
isc.Canvas.create({
height: 40,
width: 40,
backgroundColor:
"green"
}),
isc.Canvas.create({
height: 40,
width: 40,
backgroundColor: "blue"
})
]
});
// 6. VLayout with
LayoutSpacers
//
// This example uses
LayoutSpacers as members to center one member in the space
// remaining after the
first member is drawn. Note that it is the positioning
// of the two
LayoutSpacer members that creates the centering ... no alignment
// property is used.
isc.VLayout.create({
ID: "vLayoutLayoutSpacers",
autoDraw: false,
// Specifying the height creates space
which the LayoutSpacers can distribute.
height: "100%",
width: "100%",
layoutMargin: 6,
membersMargin: 6,
border: "1px dashed blue",
// Note no alignment property! It's all
done with LayoutSpacers.
members: [
isc.Label.create({
width: "100%",
height: "33%",
padding: 10,
backgroundColor: "red",
contents: "<b>No
alignment</b>"
}),
isc.LayoutSpacer.create(), // Note
the use of the LayoutSpacer
isc.Label.create({
width: "100%",
height: "33%",
padding: 10,
backgroundColor:
"green",
contents: "<b>Centered
in remaning space</b>"
}),
isc.LayoutSpacer.create() // And
another LayoutSpacer
]
});
// The rest of the code
is merely to organize the examples visually.
isc.defineClass("LayoutAlignCenterExample",
isc.VLayout).addProperties({
title: "",
example: null,
autoDraw: false,
border:"1px solid #CCCCCC",
layoutMargin: 3,
membersMargin: 2,
initWidget : function() {
this.Super("initWidget",
arguments);
this.addMembers([
isc.Label.create({
autoDraw: false,
width: "100%",
autoFit: true,
padding: 6,
contents: this.title
}),
this.example
]);
}
});
isc.HLayout.create({
width: "100%",
height: "100%",
members: [
isc.VLayout.create({
width: "40%",
autoDraw: false,
members: [
isc.LayoutAlignCenterExample.create({
title: "HLayout with
layout.align = 'center'",
example: hLayoutAlignCenter
}),
isc.LayoutAlignCenterExample.create({
title: "HLayout with
member.layoutAlign = 'center' (or layout.defaultLayoutAlign =
'center')",
example:
hLayoutDefaultLayoutAlign
}),
isc.LayoutAlignCenterExample.create({
title: "HLayout with
LayoutSpacers",
example:
hLayoutLayoutSpacers
})
]
}),
isc.LayoutAlignCenterExample.create({
title: "VLayout with
layout.align = 'center'",
example: vLayoutAlignCenter
}),
isc.LayoutAlignCenterExample.create({
title: "VLayout with
member.layoutAlign = 'center' (or layout.defaultLayoutAlign =
'center')",
example:
vLayoutDefaultLayoutAlign
}),
isc.LayoutAlignCenterExample.create({
title: "VLayout with
LayoutSpacers",
example: vLayoutLayoutSpacers
})
]
});
</SCRIPT>
</BODY>
</HTML>
|
Output:
8. Example - “Menu”
<HTML>
<HEAD><TITLE>SmartClient
demo</TITLE></HEAD>
<BODY>
... Common SmartClient code ...
<SCRIPT
LANGUAGE="JavaScript">
isc.Menu.create({
ID: "menu",
autoDraw: false,
showShadow: true,
shadowDepth: 10,
data: [
{title: "New", keyTitle:
"Ctrl+N", icon: "icons/16/document_plain_new.png"},
{title: "Open", keyTitle:
"Ctrl+O", icon: "icons/16/folder_out.png"},
{isSeparator: true},
{title: "Save", keyTitle:
"Ctrl+S", icon: "icons/16/disk_blue.png"},
{title: "Save As", icon:
"icons/16/save_as.png"},
{isSeparator: true},
{title: "Recent Documents",
icon: "icons/16/folder_document.png", submenu: [
{title: "data.xml",
checked: true},
{title: "Component
Guide.doc"},
{title:
"SmartClient.doc", checked: true},
{title: "AJAX.doc"}
]},
{isSeparator: true},
{title: "Export as...",
icon: "icons/16/export1.png", submenu: [
{title: "XML"},
{title: "CSV"},
{title: "Plain text"}
]},
{isSeparator: true},
{title: "Print", enabled:
false, keyTitle: "Ctrl+P", icon: "icons/16/printer3.png"}
]
});
isc.MenuButton.create({
ID: "menuButton",
title: "File",
width: 100,
menu: menu
});
</SCRIPT>
</BODY>
</HTML>
|
Output:
9. Example - “Dynamic
Form”
<HTML>
<HEAD><TITLE>SmartClient
demo</TITLE></HEAD>
<BODY>
... Common SmartClient code ...
<SCRIPT LANGUAGE="JavaScript">
isc.DynamicForm.create({
ID: "boundForm",
// dataSource: "users",
// not giving the definition of data
source here as you can run the sample without it.
//useAllDataSourceFields: true,
fields: [
{type:"header",
defaultValue:"Registration Form"},
{name: "password"},
{name: "password2", title:
"Password Again", type: "password", required: true,
length: 20, validators: [{
type: "matchesField",
otherField: "password",
errorMessage: "Passwords do
not match"
}]
},
{name: "acceptTerms",
title: "I accept the terms of use.", type: "checkbox",
required: true, width: "150"},
{name: "validateBtn",
title: "Validate", type: "button", click:
"form.validate()"}
],
values : {
firstName: "Bob",
email: "bob@.com",
password: "sekrit",
password2: "fatfinger"
}
});
</SCRIPT>
</BODY>
</HTML>
|
Output:
Explanation:
DynamicForm is corresponding control to
what we have “Form” in html. You can
perform all the html operations on DynamicForm like:
a. Make a required
field distinguishable.
b. Validate fields by
icons, alert messages interactively.
c. Divide your screen
for better look n feel with multiple DynamicForms.
Note: If you have multiple DynamicForms and you
want to process them all as single information then you can use ValueManager.
10. Example - “Section
Stack and Sections”
<HTML>
<HEAD><TITLE>SmartClient
demo</TITLE></HEAD>
<BODY>
... Common SmartClient code ...
<SCRIPT
LANGUAGE="JavaScript">
isc.HTMLFlow.create({
ID: "htmlFlow",
overflow: "auto",
padding:10,
contents: "<b>Severity
1</b> - Critical problem<br>System is unavailable in production
or " +
"is corrupting data, and
the error severely impacts the user's operations." +
"<br><br><b>Severity 2</b> - Major
problem<br>An important function of the system " +
"is not available in
production, and the user's operations are restricted." +
"<br><br><b>Severity 3</b> - Minor
problem<br>Inability to use a function of the " +
"system occurs, but it
does not seriously affect the user's operations."
})
isc.SectionStack.create({
ID: "sectionStack",
visibilityMode: "multiple",
width: 300, height: 350,
border:"1px solid blue",
sections: [
{title: "Blue Pawn",
expanded: true, items: [
isc.Img.create({autoDraw: false,
width: 48, height: 48, src: "pieces/48/pawn_blue.png"})
]},
{title: "HTMLFlow",
expanded: true, canCollapse: true, items: [ htmlFlow ]},
{title: "Green Cube",
expanded: true, canCollapse: false, items: [
isc.Img.create({autoDraw: false,
width: 48, height: 48, src: "pieces/48/cube_green.png"})
]},
{title: "Yellow Piece",
expanded: false, items: [
isc.Img.create({autoDraw: false,
width: 48, height: 48, src: "pieces/48/piece_yellow.png"})
]}
]
});
isc.IButton.create({
left: 325,
width: 150,
title: "Expand Blue",
click:
"sectionStack.expandSection(0)"
});
isc.IButton.create({
left: 325,
top: 30,
width: 150,
title: "Collapse Blue",
click:
"sectionStack.collapseSection(0)"
});
</SCRIPT>
</BODY>
</HTML>
|
Output:
11. Example - “Tabs”
<HTML>
<HEAD><TITLE>SmartClient
demo</TITLE></HEAD>
<BODY>
... Common SmartClient code ...
<SCRIPT
LANGUAGE="JavaScript">
isc.TabSet.create({
ID: "topTabSet",
tabBarPosition: "top",
width: 400,
height: 200,
tabs: [
{title: "Blue", icon:
"pieces/16/pawn_blue.png", iconSize:16,
pane: isc.Img.create({autoDraw:
false, width: 48, height: 48, src: "pieces/48/pawn_blue.png"})},
{title: "Green", icon:
"pieces/16/pawn_green.png", iconSize:16,
pane: isc.Img.create({autoDraw:
false, width: 48, height: 48, src: "pieces/48/pawn_green.png"})}
]
});
isc.TabSet.create({
ID:"leftTabSet",
tabBarPosition: "left",
width: 400,
height: 200,
top: 250,
tabs: [
{icon: "pieces/16/pawn_blue.png", iconSize:16,
pane: isc.Img.create({autoDraw:
false, width: 48, height: 48, src: "pieces/48/pawn_blue.png"})},
{icon:
"pieces/16/pawn_green.png", iconSize:16,
pane: isc.Img.create({autoDraw:
false, width: 48, height: 48, src: "pieces/48/pawn_green.png"})}
]
});
isc.IButton.create({
title: "Select Blue",
top: 215,
click: function () {
topTabSet.selectTab(0);
leftTabSet.selectTab(0);
}
});
isc.IButton.create({
title: "Select Green",
top: 215,
left: 110,
click: function () {
topTabSet.selectTab(1);
leftTabSet.selectTab(1);
}
});
</SCRIPT>
</BODY>
</HTML>
|
Output:
12. Example - “Tool
Strip”
<HTML>
<HEAD><TITLE>SmartClient
demo</TITLE></HEAD>
<BODY>
... Common SmartClient code ...
<SCRIPT
LANGUAGE="JavaScript">
isc.Menu.create({
ID: "menu",
autoDraw: false,
showShadow: true,
shadowDepth: 10,
data: [
{title: "New", keyTitle:
"Ctrl+N", icon: "icons/16/document_plain_new.png"},
{title: "Open", keyTitle:
"Ctrl+O", icon: "icons/16/folder_out.png"},
{isSeparator: true},
{title: "Save", keyTitle:
"Ctrl+S", icon: "icons/16/disk_blue.png"},
{title: "Save As", icon:
"icons/16/save_as.png"},
{isSeparator: true},
{title: "Recent Documents",
icon: "icons/16/folder_document.png", submenu: [
{title: "data.xml",
checked: true},
{title: "Component
Guide.doc"},
{title: "SmartClient.doc",
checked: true},
{title: "AJAX.doc"}
]},
{isSeparator: true},
{title: "Export as...",
icon: "icons/16/export1.png", submenu: [
{title: "XML"},
{title: "CSV"},
{title: "Plain text"}
]},
{isSeparator: true},
{title: "Print", enabled:
false, keyTitle: "Ctrl+P", icon: "icons/16/printer3.png"}
]
});
isc.ToolStripMenuButton.create({
ID: "menuButton",
title: "File",
menu: menu
});
isc.ToolStripButton.create({
ID: "printButton",
icon: "other/printer.png",
title: "print"
});
isc.ToolStripButton.create({
ID: "alignLeft",
icon:
"[SKIN]/RichTextEditor/text_align_left.png",
actionType: "radio",
radioGroup: "textAlign"
});
isc.ToolStripButton.create({
ID: "alignRight",
icon:
"[SKIN]/RichTextEditor/text_align_right.png",
actionType: "radio",
radioGroup: "textAlign"
});
isc.ToolStripButton.create({
ID: "alignCenter",
icon:
"[SKIN]/RichTextEditor/text_align_center.png",
actionType: "radio",
radioGroup: "textAlign"
});
isc.ToolStripButton.create({
ID: "bold",
icon:
"[SKIN]/RichTextEditor/text_bold.png",
actionType: "checkbox"
});
isc.ToolStripButton.create({
ID: "italics",
icon:
"[SKIN]/RichTextEditor/text_italic.png",
actionType: "checkbox"
});
isc.ToolStripButton.create({
ID: "underlined",
icon:
"[SKIN]/RichTextEditor/text_underline.png",
actionType: "checkbox"
});
isc.DynamicForm.create({
ID: "fontSelector",
showResizeBar:true,
width:100, minWidth:50,
numCols:1,
fields: [
{name: "selectFont",
showTitle: false, width:"*",
valueMap: {
"courier":
"<span style='font-family:courier'>Courier</span>",
"verdana":
"<span style='font-family:verdana'>Verdana</span>",
"times": "<span
style='font-family:times'>Times</span>"
}, defaultValue:"courier"
}
]
});
isc.DynamicForm.create({
ID: "zoomSelector",
width:100, minWidth:50,
numCols:1,
fields: [
{name: "selectZoom",
showTitle: false, width:"*",
valueMap: ["50%",
"75%", "100%", "150%", "200%",
"Fit"],
defaultValue:"100%" }
]
});
isc.ToolStrip.create({
width: 450, height:24,
members: [menuButton,
"separator", printButton,
"resizer", bold,
italics, underlined,
"separator",
alignLeft, alignRight,
alignCenter,
"separator",
fontSelector, "resizer",
zoomSelector]
});
</SCRIPT>
</BODY>
</HTML>
|
Output:
13. Example - “Fusion
Chart”
<HTML>
<HEAD><TITLE>SmartClient
demo</TITLE></HEAD>
<BODY>
... Common SmartClient code ...
<SCRIPT
LANGUAGE="JavaScript">
isc.FusionChart.create({
autoDraw: true,
facets:[{ id:"regions" }, {
id:"product" }],
data : [
{product:"cars",
regions:"west", _value:4},
{product:"cars",
regions:"north", _value:2},
{product:"cars", regions:"east",
_value:5},
{product:"trucks",
regions:"west", _value:1},
{product:"trucks",
regions:"north", _value:9},
{product:"trucks",
regions:"east", _value:3}
]
})
</SCRIPT>
</BODY>
</HTML>
|
Output:
Explanation:
Fusion charts
package is be required to run above example.
You can download it from http://www.fusioncharts.com/. After downloading you need to configure the SmartClient
components so that chart resources like flash files for different chart types
is accessible.
2. Isomorphic products
1. SmartGWT
Code in Java, get the power of the
SmartClient framework.
2. SmartClient
Create Enterprise web applications using
JavaScript.
3. Comparison with other RIA Frameworks
For details comparison between Prototype,
Dojo, jQuery, mootools and SmartClient Frameworks please visit my blog using
below link.
4. Visual Builder
Visual
Builder component of SmartClient gives you much of the flexibility, which are:
1. No need to write
code to create UI, simply Drag and Drop Screen Building with Codeless Event
Handling
2. Simple Data binding.
3. No need to scrap
your mock code, use data source as a plug to switch over different data
provider.
4. For more details
visit http://www.smartclient.com/technology/visualbuilder.jsp
Screenshot:
5. Tune SmartClient
There are various tips available for tuning
SmartClient on different websites. What
I am providing here are fine tunings applied in different live projects.
a. Property autoDraw
Every SmartClient
component has a property autoDraw. Keep it false, this is true by default. Suppose you have outermost layout that nests
up to four levels, now when a parent most canvas is drawn then it’s all
children are redrawn, so the innermost will children will be redrawn multiple
times or you can think that the script drawing it would be executed multiple
times.
You can see this
effect in IE explicitly. Example to tune it is given in #c.
b. Property redrawOnResize
Again every
SmartClient component has a property redrawOnResize.
Keep it false, this is true by default.
If browser or any other component SmartClient component resizes then
required members will be redrawn.
Example to tune it
is given in #c.
c. Make Custom
Controls
To support #a and
#b, you need to prepare Custom Controls for most of the required SmartClient in
your project and set their specific properties for fine tune.
Example:
isc.defineClass("CustomListGrid",
"ListGrid").addProperties({
//removeFieldDefaults: {type:
"icon", canEdit: false, canSort: false, canFilter: false,
filterEditorType: "spacer", title: " ",
canGroupBy: false, hoverHTML: function (record, value, rowNum, colNum, grid)
{return "click to remove";}, showHover: true, canHover: true,
width: 20, recordClick: function (viewer, record, recordNum, field, fieldNum,
value, rawValue) {this.Super ("recordClick", arguments);
viewer.removeData (record);}},
//autoFitWidthApproach:
"value",
minFieldWidth: 50,
bodyProperties: { canSelectText:true },
alternateRecordStyles:true,
wrapCells:true,
//cellHeight:50,
//headerHeight:30,
width: "100%",
height: "100%",
showSortArrow: "field",
selectionType: "single",
singleCellValueProperty:
"singleCellValue",
layoutMargin:2,
loadingDataMessage: getGridLoadingMsg(),
loadingMessage: "...",
expansionFieldTrueImage:getImgPath('expand-true.gif'),
expansionFieldFalseImage:getImgPath('expand-false.gif'),
expansionFieldImageWidth: 7,
expansionFieldImageHeight: 9,
/*vPolicy: "scroll",*/
/*bodyOverflow:"scroll-v",*/
overflow:"auto",
redrawOnResize:
false, /* Once the contents are drawn no need to redraw them */
leaveScrollbarGap:false,
showRollOver: false,
showHeaderMenuButton: true,
showHeaderContextMenu: true,
/*canHover: true,*/
/*showHover: true,*/
canAutoFitFields : false,
canReorderFields: false,
canSort: false,
canPickFields: false,
canFreezeFields: false,
canGroupBy: false,
showShadow:false,
autoDraw: false
});
// -----------------------------------------------------------------
isc.defineClass("CustomHSlider",
"Slider").addMethods({
vertical: false,
redrawOnResize: false, /* Once the
contents are drawn no need to redraw them */
showShadow:false,
autoDraw:false
});
// -----------------------------------------------------------------
isc.defineClass("CustomIButton",
"IButton").addMethods({
redrawOnResize: false, /* Once the
contents are drawn no need to redraw them */
width: 150,
height: 30,
imageType: "normal",
autoDraw:false
});
//
-----------------------------------------------------------------
isc.defineClass("CustomHTMLPane",
"HTMLPane").addMethods({
width: "100%",
height: "100%",
overflow:"auto",
contentsType:"page",
redrawOnResize: true, /* Once the
contents are drawn draw them again, its slow but required*/
showShadow:false,
autoDraw:false
});
//
-----------------------------------------------------------------
isc.defineClass("CustomHTMLFlow",
"HTMLFlow").addMethods({
width: "100%",
height: "100%",
vPolicy: "fill",
overflow:"auto",
redrawOnResize: false, /* Once the
contents are drawn no need to redraw them */
showShadow:false,
autoDraw:false
});
//
-----------------------------------------------------------------
isc.defineClass("CustomImgButton",
"ImgButton").addProperties({
size:24,
hoverWidth: 100,
showRollOver: false,
showDown: false,
showFocused: false,
redrawOnResize: false, /* Once the
contents are drawn no need to redraw them */
showShadow:false,
autoDraw:false
});
|
d. Do not try to put
different SmartClient controls to draw final screen, always put your complete
and final screen in VLayout or HLayout so that members inside it would be
adjusted as per parent layout when drawn on screen. This gives you flexibility to hold on
screen.
e. SmartClient
components can be drawn relative to html components position. Try to avoid this approach of mingling
SmartClient and html code; you might face certain components behaving
ambiguously. Also, browsers have
different approach to drawn different types of components like few browsers
first draw HTML components then SmartClient and few does vice versa, so last
drawn component would be visible.
f.
6. Complex UIs using SmartClient for
reference only
6.1 Example 1
Search Results
Screen
Order Detail Screen
Create
Order Screen
6.2 Example 2
Dynamicity showing
complex GUI
Charting
capabilities
6.3 Example 3
Dashboard i.e.
Welcome screen
Suspension Screen
7. Customizing SmartClient
7.1 Customizing default theme
The example skins that come with
SmartClient are in smartclientSDK/isomorphic/skins. To create a
custom skin, copy an existing skin that most closely matches your intended skin
and modify it.
For example, let’s say you wanted to
customize the built-in SmartClient skin and call the
resulting skin BrushedMetal. The procedure is
as follows:
Locate the SmartClient skin under /isomorphic/skins and copy the
contents of that entire directory into a new folder called BrushedMetal
a. Edit the /isomorphic/skins/BrushedMetal/load_skin.js file. Find the
line near the top of the file that reads: isc.Page.setSkinDir("[ISOMORPHIC]/skins/SmartClient/") and change it to: isc.Page.setSkinDir("[ISOMORPHIC]/skins/BrushedMetal/")
b. Delete the /isomorphic/skins/BrushedMetal/load_skin.js.gz and /isomorphic/skins/BrushedMetal/skin_styles.css.gz files.
c. Now you‘re ready to
customize the new skin. You can do so by modifying any of the image/css etc files
in your new skin directory.
7.2 Change default Chart engine support
By default Fusion Chart is the default
chart engine shipped with SmartClient.
To use any other chart engine you need to create the custom
control. I am providing custom control
example for using AMChart engine.
Creating custom control:
/* A shim to AMChart for
charting*/
isc.defineClass("AMChart",
isc.Canvas).addProperties({
redrawOnResize: true,
autoDraw: false,
overflow: "auto",
type: "line",
min: 0,
max: 100,
jsonProps: "",
graph: "",
initWidget: function() {
graph = null;
this.Super("initWidget",
arguments);
},
getCanvasID: function() {
return this.getID() +
"_canvas";
},
getChartDivID: function() {
return this.getCanvasID() +
"_div";
},
getInnerHTML: function() {
return '<div
id="'+this.getCanvasID()+'"><strong>Try
'+applyLinkCSS("Refresh","refreshSCComponent
(\""+this.getID()+"\")") + ' or You need to ' + applyLinkCSS("upgrade","window.open(\"http://www.adobe.com/support/flashplayer/downloads.html\")")+'
your Flash Player</strong></div>';
},
draw: function() {
this.Super("draw",
arguments);
this.drawGraph();
return this;
},
redraw: function() {
this.Super("redraw",
arguments);
/*this.drawGraph();*/
return this;
},
setData: function(data) {
return this;
},
setSettings: function(data) {
return this;
},
appendData: function(data) {
eval(this.getChartDivID()).appendData (data, "0");
/*
document.getElementById(this.getChartDivID()).appendData (data,
"0");*/
},
drawGraph: function() {
var self = this;
graph = new SWFObject(getChartSWFPath(this.type),
this.getChartDivID(),
String(this.getInnerWidth()), String(this.getInnerHeight()),
"8", "#FFFFFF");
/* need to see this line*/
/*g[this.theme]();*/
graph.title = this.title;
graph.addVariable("path",
getChartRootPath(this.type));
graph.addVariable("settings_file",
escape(getChartSettingFile (this.type)));
graph.addVariable('chart_data',
encodeURIComponent(this.data));
graph.addVariable("chart_settings",
encodeURIComponent(getChartSettings(this.type,
eval(getChartJson(this.jsonProps)))));
/*graph.addVariable("preloader_color",
"#999999");*/
/*graph.addParam("wmode",
"opaque");*/
graph.write(this.getCanvasID());
}
});
|
Details:
When the parent component that has above
charting component is resized then some times the chart disappears. I provided a link to refresh only chart
component to redraw the chart. Below is
the code:
/* SmartClient valid ID
should be passed to redraw */
function
refreshSCComponent (id) {
if (hasValue(id)) {
try {
var obj = eval (id);
if (obj != null) {
obj.clear ();
obj.draw ();
}
}
catch (e) {}
}
}
|
Other than above you need to download the
desired charting engine available flash and other files. And integrate it with SmartClient by
configuring the paths and other properties.
7.3 Download list grid data as CSV without
Server trip
Please follow below link from my blog for
this problem.
8. References
- Official site:
http://www.smartclient.com/product/smartclient.jsp
- Forum: http://forums.smartclient.com/
- APIs: http://www.smartclient.com/docs/8.2/a/b/c/go.html
- Showcase: http://www.smartclient.com/docs/8.2/a/system/reference/SmartClient_Explorer.html
- Release notes:
http://www.smartclient.com/docs/8.1/docs/readme.html
- Change logs: http://www.smartclient.com/docs/8.1/docs/changelog.html
* - 8.1
and 8.2 are version. Latest version of
SmartClient is 8.2 as on 14-Feb-2012.