JavaScript Guide - Application Resources
JavaScript Guide - Application Resources
Content
Introduction Performance
Writing JavaScript Preventing Memory Leaks
General Guidelines Useful Utilities
Script Files
Application Resources
The LabVantage API
Objects & Classes
Example
Useful API Functions
Introduction
The LabVantage JavaScript Global API provides developers with enhanced client-side functionality. This document outlines
standards for JavaScript authoring, details performance considerations, and describes LabVantage JavaScript Global API
functionality.
Writing JavaScript
General Guidelines
Follow these guidelines when writing JavaScript for LabVantage:
1. Script Files
Try to use script files rather than writing the script within the JSP or HTML. See Script Files for details.
2. Naming Conventions
Use these JavaScript naming conventions (refer to http://articles.techrepublic.com.com/5100-22-5109485.html):
• Function names should use Camel Notation, i.e., begin with a lowercase letter, and the first letter of each
subsequent new word is upper case with all other letters lower case).
• Class names should begin with a capital letter, and the first letter of each subsequent new word should be
capitalized with all other letters lower case.
• Variable names should use Camel Notation.
• Variable names should use Hungarian Notation and indicate their data type with a consistent prefix (l - boolean; n
- floating point; i - integer; o - object; s - string).
• Variable and Function names should demonstrate their purpose.
file:///Users/aditya_saharay/Desktop/Lab%20Informatics/COTS%20Pro…08.6/Content/javascript/javascript_guide.htm#ApplicationResources Page 1 of 15
JavaScript Guide 15/02/24, 12:09 PM
8. Parentheses
Take advantage of parentheses to ensure that a mathematical result is calculated as expected. For example, are x and
y equal:
var x = 2 * 3 + 2 / 2 + 2
var y = (((2 * 3) + 2)/(2 + 2))
9. Coding style
Use a consistent style when writing JavaScript. This makes it easier to understand from other developers. The coding
style to use is the same as Java code, with curly brackets at the end of the line, and a space after the parentheses:
function MyClass( ){
this.myFunction = new function( sMyString, iMyInt ){
for ( var iIndex = 0; iIndex < 10; iIndex++ ){
alert( iIndex );
}
}
}
10. Semicolons
JavaScript can be written with or without semicolons at the end of a statement. To be consistent throughout
LabVantage, all new JavaScript code should be written with a semicolon at the end of a line or statement.
Script Files
JavaScript in LabVantage has evolved from a few lines of code that changes the color of a button, to thousands of lines of
code that control all aspects of the application. JavaScript development habits must evolve with the language.
For example, placing code directly into a JSP or HTML page rather than into a separate script file causes a big performance
drain, as this code has to be downloaded to the client every time the page loads.
Therefore, new code (or any code encountered during a JSP change) should be placed into a related JS file. This JS file should
then be placed in the "scripts" folder for the context of your item. Or, create an Application Resource. For example, if you
write a new Page Type called "SuperPageType" with a JS class of SuperPageType, all JavaScript code for this page type should
be placed in a "superpagetype.js" (same name but in lower case) file in the "scripts" folder associated with this Page Type.
Alternatively, if you write an Element called "MyElement", create a script file called "myelement.js", and place it in the scripts
folder for this Element. Here are some examples:
Application Resources
Beginning in LabVantage 8.5, you can store javascript and css resources in a dedicated register within LabVantage. This will
be called an Application Resource.
file:///Users/aditya_saharay/Desktop/Lab%20Informatics/COTS%20Pro…08.6/Content/javascript/javascript_guide.htm#ApplicationResources Page 2 of 15
JavaScript Guide 15/02/24, 12:09 PM
Navigate to System Admin > Web Page Designer > Application Resources
From the list page you can add, edit, copy or delete a resource. Other tasks can be performed through the toolbar on the list
page. Below is an example of adding a resource.
The resource source can be either "url" or "attachment". If the source is defined as "url", the source can be set as a path
within the labvantage.war file, i.e. "WEB-CORE/scripts/json.js". If the source is defined as "attachment" the resource needs to
be provided as an attachment of the application resource. The first attachment of type "Application Resource" will be used. In
the standard configuration only one attachment is allowed for per application resource.
Application resource javascripts are supported by:
Maintenance List
DataEntry
DataEntryByQuery
DataChartPage
Prompt
file:///Users/aditya_saharay/Desktop/Lab%20Informatics/COTS%20Pro…08.6/Content/javascript/javascript_guide.htm#ApplicationResources Page 3 of 15
JavaScript Guide 15/02/24, 12:09 PM
Minification
Beginning in LabVantage 8.6, you can use LabVantage to minify your JavaScript or CSS. Minification refers to the process of
removing unnecessary or redundant data without affecting how the resource is processed by the browser. Examples include
code comments, formatting, unused code, shorter variable and function names, and so on. Minification dramatically improves
site speed and accessibility, directly translating into a better user experience. LabVantage now includes the YUI Compressor as
an option for you to minify JavaScript and CSS resources.
Minification of the attached resource is initiated manually on the maintenance page by clicking the Minify button. Minification
of the attached file will be attempted.
Prior to Minification
file:///Users/aditya_saharay/Desktop/Lab%20Informatics/COTS%20Pro…08.6/Content/javascript/javascript_guide.htm#ApplicationResources Page 4 of 15
JavaScript Guide 15/02/24, 12:09 PM
Minification will fail with a warning if no Application Resource attachment is found or if there are errors when running the
minification. Errors are often due to incompatible javascript content.
Minification will succeed, but display a warning if warnings are issued during minification.
After successful minification, the minified JS or CSS will be stored as a second attachment to the application resource with
class "Minified Application Resource". By default, the minified version of the file will be provided by configuration includes,
when the minified attachment exists. This can be overridden by setting the GUIPolicy property "Use Full Un-minified Includes"
to Yes. This is an Advanced property. You can also choose to use the un-minified version of a specific application resource
file:///Users/aditya_saharay/Desktop/Lab%20Informatics/COTS%20Pro…08.6/Content/javascript/javascript_guide.htm#ApplicationResources Page 5 of 15
JavaScript Guide 15/02/24, 12:09 PM
When uploading a new version of the original attachment file, you will first need to delete all previous attachments including
original and minified versions.
function MyElement(){
var myPrivateProperty = 'Hello World Again';
file:///Users/aditya_saharay/Desktop/Lab%20Informatics/COTS%20Pro…08.6/Content/javascript/javascript_guide.htm#ApplicationResources Page 6 of 15
JavaScript Guide 15/02/24, 12:09 PM
}
To declare a public function within the object, use the syntax:
function MyElement(){
this.myPublicFunction = function(){
// function contents
}
}
To declare a private function within the object, use the syntax:
function MyElement(){
function myPrivateFunction(){
// function contents
}
}
Example
This is an example file called "MyElement.js". It is for a new Element called "MyElement". The file should be placed in "WEB-
CORE/elements/scripts/".
function MyElement(){
this.sMyName = 'Steve';
this.sMyEyeColor = 'blue';
var iMyAge = 28;
this.getAge = function( ){
return iMyAge;
}
The JSP that is part of my element can then call the functions from the file once it has been included.
<script src="WEB-CORE/elements/scripts/MyElement.js"></script>
<script>
myelement.setUser( 'Steve', 'Blue', 28 );
alert( myelement.sMyName );
alert( myelement.sMyEyeColor );
alert( myelement.getAge( ) );
</script>
1. Dialogs
The sapphire.ui.dialog object controls and shows new LabVantage dialogs and popups.
This shows an alert box... use it instead of "alert()":
file:///Users/aditya_saharay/Desktop/Lab%20Informatics/COTS%20Pro…08.6/Content/javascript/javascript_guide.htm#ApplicationResources Page 7 of 15
JavaScript Guide 15/02/24, 12:09 PM
2. Ajax
The sapphire.ajax object controls the new Ajax API.
This calls a LabVantage Ajax class with the sent properties:
sapphire.ajax.callClass( 'com.labvantage.sapphire.myAjaxClass', myCallbackFunction,
myProps )
This calls a LabVantage Ajax service with the sent properties:
sapphire.ajax.callService( 'com.labvantage.sapphire.myAjaxService',
myCallbackFunction, myProps )
This calls a LabVantage Ajax command with the sent properties:
sapphire.ajax. callCommand( 'com.labvantage.sapphire.myAjaxCommand',
myCallbackFunction, myProps )
3. Connection Information
Using the sapphire.connection object and sapphire.page object, you can get connection details, user information,
and page information.
To get the connection Id of the LabVantage connection:
sapphire.connection.connectionId
To get the database Id of the LabVantage connection:
sapphire.connection.databaseId
To get the user Id of the current LabVantage user:
sapphire.connection.sysUserId
To get the current page name:
sapphire.page.name
4. Maintenance List and Maintenance Form
You can use the sapphire.page.list and sapphire.page.maint objects to perform public functionality on List pages
and Maintenance pages, respectively. Here are a few examples:
To open the Add Maintenance page:
sapphire.page.list.add( sAPage, sTarget )
To get the selected items in the current page or all pages (and return all default columns or the specified
columns):
sapphire.page.getSelected( '', true )
To open the Add Maintenance page:
sapphire.page.maint.add(sAPage, sTarget )
To obtain keyid1 from the Maintenance page:
sapphire.page.maint.getKeyId1 ( )
5. Animations
R4.6 introduced graphical animations on the user interface. These animations can be switched on and off for each user,
or globally for the application. You can use these animations to show and hide any HTML object.
To show an object using a fade in transition:
sapphire.ui.animation.fadeIn( 'myDiv', 10, 20, 0, 100 )
To hide an object using a fade out transition:
sapphire.ui.animation.fadeOut( 'myDiv', 10, 20, 0, 100 )
To show an object using a resize in vertical transition:
sapphire.ui.animation.showObjectVertical ( 'myDiv', 10, 20 )
file:///Users/aditya_saharay/Desktop/Lab%20Informatics/COTS%20Pro…08.6/Content/javascript/javascript_guide.htm#ApplicationResources Page 8 of 15
JavaScript Guide 15/02/24, 12:09 PM
Performance
Performance is a major factor to consider as client-side functionality grows. JavaScript (unlike Java) is an interpreted
language, and calls its methods and properties through a form of structured referencing. Therefore, code that would normally
perform well in a compiled language can run very slowly in JavaScript. To write more efficient and faster code, these
guidelines should be followed:
file:///Users/aditya_saharay/Desktop/Lab%20Informatics/COTS%20Pro…08.6/Content/javascript/javascript_guide.htm#ApplicationResources Page 9 of 15
JavaScript Guide 15/02/24, 12:09 PM
4. Use "var"
Always declare the function level variables with the "var" keyword. If you declare a new variable in JavaScript without
the "var" keyword then the variable is given a global scope. This not only could lead to clashes in the code from other
variables with the same name, but also will keep the variable or object active in memory until the page is disposed.
Therefore you must always declare local function variables using the "var" keyword.
Bad example:
function myFunction( ){
sMyString = '';
sMyString += 'Hello';
alert( sMyString );
}
Good example:
function myFunction( ){
var sMyString = '';
sMyString += 'Hello';
alert( sMyString );
}
5. Fragment documents
Use document fragments (rather than using the document object directly) when updating the DOM. When you update
the document structure using "createElement" and "appendChild", the document refreshes its structure at every
update. This can be a large performance drain. To prevent this, you should use the
"document.createDocumentFragment" method to return a workable fragment of the document that can then be
appended to the parent document after you are done with it.
Bad example:
var oEl1 = document.createElement('div');
oEl1.id = 'myDiv';
var oEl2 = document.createElement('span');
oEl2.id = 'mySpan';
var oEl3 = document.createElement('font');
oEl3.innerText = 'Hello';
document.body.appendChild(oEl1);
document.body.appendChild(oEl2);
document.body.appendChild(oEl3);
Good example:
var oDoc = document;
var oEl1 = oDoc.createElement('div');
oEl1.id = 'myDiv';
var oEl2 = oDoc.createElement('span');
oEl2.id = 'mySpan';
var oEl3 = oDoc.createElement('font');
oEl3.innerText = 'Hello';
var oFrag = oDoc.createDocumentFragment();
oFrag.appendChild(oEl1);
oFrag.appendChild(oEl2);
oFrag.appendChild(oEl3);
oDoc.body.appendChild(oFrag);
6. Know the performance hits of methods and properties
A few of the fundamental core objects, properties and functions are quite expensive in terms of memory and processing
power. Two of the largest performance drains are "document.getElementById" and "element.innerHTML".
When using "getElementById" it is important to cache the returned object otherwise the JavaScript engine will look up
the document structure and locate the element each time it is called:
Bad example:
if ( document.getElementById( 'myElement' ) != null ){
if (document.getElementById( 'myElement' ).value != 'Hello'){
alert(document.getElementById( 'myElement' ).value );
file:///Users/aditya_saharay/Desktop/Lab%20Informatics/COTS%20Pro…8.6/Content/javascript/javascript_guide.htm#ApplicationResources Page 10 of 15
JavaScript Guide 15/02/24, 12:09 PM
}
}
Good example:
var oElement = document.getElementById( 'myElement' );
if ( oElement != null ){
var sValue = oElement.value;
if ( sValue != 'Hello' ){
alert( sValue );
}
}
When using "innerHTML" always buffer the HTML content before setting it back, otherwise the JavaScript engine will
rebuild the document structure every time the HTML is updated:
Bad example:
for ( var iIndex = 0; iIndex < iANumber; iIndex++){
oMyElement.innerHTML += '<br>' + iIndex + '</br>';
}
Good example:
var sHtml = '';
for ( var iIndex = 0; iIndex < iANumber; iIndex++){
sHtml += '<br>' + iIndex + '</br>';
}
oMyElement.innerHTML = sHtml;
DOM Leaks
DOM leaks occur when a DOM object is removed from the DOM, but stays in memory. This memory is freed when the
page is refreshed, but can lead to the page quickly becoming unresponsive. Two causes are:
• When you create a DOM object dynamically in a method and return it, the JS engine still maintains a link to that
variable.
• When you use removeChild or removeChildNode, the methods remove the object from the DOM, but do not remove
the object from memory.
References:
http://www.hedgerwow.com/360/dhtml/ie6_memory_leak_fix/
http://ajaxian.com/archives/is-finally-the-answer-to-all-ie6-memory-leak-issues
To see if your application contains memory leaks, you can use the free Process Explorer tool from Microsoft. This tool shows
you memory in use by an application. If you examine the JavaScript application, you will notice that when you use the web
page, the memory will increase. Then, after a refresh, not all memory is released:
file:///Users/aditya_saharay/Desktop/Lab%20Informatics/COTS%20Pro…08.6/Content/javascript/javascript_guide.htm#ApplicationResources Page 11 of 15
JavaScript Guide 15/02/24, 12:09 PM
file:///Users/aditya_saharay/Desktop/Lab%20Informatics/COTS%20Pro…8.6/Content/javascript/javascript_guide.htm#ApplicationResources Page 12 of 15
JavaScript Guide 15/02/24, 12:09 PM
such as "time" or any classes that uses behaviors. These offer linked functionality to other COM objects. Therefore,
when a DOM object is disposed with a class name, the COM object still references it. The best course of action is to add
the removal of any complex class names from the object before you send it to the garbage bin in your disposal method.
Once you are managing memory correctly and the garbage collector is in place, you should see patterns where the memory
increases until the garbage bin is full... then, memory is fully released. Also, a refresh should not keep any memory (below).
Here are some examples that cause memory leaks, along with their solutions:
Creation of DOM objects
This will cause two memory leaks... a circular reference and a DOM leak:
function createDiv() {
var oDiv = document.createElement('div');
oDiv.id = 'mydiv';
return oDiv;
}
var oDiv = createDiv();
oDiv.innerHTML = 'some content';
document.body.appendChild(oDiv);
oDiv.parentElement.removeChild(oDiv);
To repair this leak, place a try...finally around the return from the method, and pass the element to be removed to the
garbage collector.
function createDiv() {
var oDiv = document.createElement('div');
oDiv.id = 'mydiv';
try {
return oDiv;
}
finally{
oDiv = null;
}
}
var oDiv = createDiv();
oDiv.innerHTML = 'some content';
document.body.appendChild(oDiv);
sapphire.garbage.add( oDiv );
oDiv = null;
Circular references
This relates two simple DOM objects so if something happens on one, it affects the other. Refreshing the page will leave
all elements in memory:
<div id=oPrimary style="display:block">title</div>
<div id=oSecondary style="display:none">A sub title</div>
<script>
var oPri = document.getElementById( 'oPrimary' );
var oSec = document.getElementById( 'oSecondary' );
if ( oPri != null && oSec != null ) {
oPri.relatedElement = oSec;
file:///Users/aditya_saharay/Desktop/Lab%20Informatics/COTS%20Pro…8.6/Content/javascript/javascript_guide.htm#ApplicationResources Page 13 of 15
JavaScript Guide 15/02/24, 12:09 PM
oSec.relatedElement = oPri;
oPri.onclick = openClose();
oSec.onclick = openClose();
}
function openClose() {
var oEl = event.srcElement;
if ( oEl.style.display == 'block') {
oEl.style.display = 'none';
oEl.relatedElement.style.display = 'block';
}
}
</script>
What we must do is create a dispose function that is called when the page unloads. The dispose function must remove
any circular references, free variables where required, and stop DOM objects being stored globally:
<div id=oPrimary style="display:block">title</div>
<div id=oSecondary style="display:none">A sub title</div>
<script>
function setup() {
var oPri = document.getElementById( 'oPrimary' );
var oSec = document.getElementById( 'oSecondary' );
if ( oPri != null && oSec != null ){
oPri.relatedElement = oSec;
oSec.relatedElement = oPri;
oPri.onclick = openClose();
oSec.onclick = openClose();
oPri = null;
oSec = null;
}
}
function openClose() {
var oEl = event.srcElement;
if ( oEl.style.display == 'block') {
oEl.style.display = 'none';
oEl.relatedElement.style.display = 'block';
}
oEl = null;
}
function dispose() {
var oPri = document.getElementById( 'oPrimary' );
var oSec = document.getElementById( 'oSecondary' );
if ( oPri != null && oSec != null ){
oPri.relatedElement = null;
oSec.relatedElement = null;
oPri.onclick = null;
oSec.onclick = null;
oPri = null;
oSec = null;
}
}
window.addEventListener( 'load', setup );
window.addEventListener( 'unload', dispose );
</script>
For more examples, see:
http://www.bazon.net/mishoo/articles.epl?art_id=824
http://www.hedgerwow.com/360/dhtml/ie6_memory_leak_fix/
http://support.microsoft.com/kb/830555
http://www.javascriptkit.com/javatutors/closuresleak/index.shtml
http://javascript.crockford.com/memory/leak.html
Useful Utilities
As described in LabVantage JavaScript Utilities, LabVantage provides the Code Completion Utility and JavaScript Interrogator.
file:///Users/aditya_saharay/Desktop/Lab%20Informatics/COTS%20Pro…8.6/Content/javascript/javascript_guide.htm#ApplicationResources Page 14 of 15
JavaScript Guide 15/02/24, 12:09 PM
file:///Users/aditya_saharay/Desktop/Lab%20Informatics/COTS%20Pro…8.6/Content/javascript/javascript_guide.htm#ApplicationResources Page 15 of 15