Using Javascript DOM in Web Applications

Many times while creating the web applications its not always a good idea to store even a
small information in database tables. For Example if you have drop downs in your application and you want to populate the same from the lookup table in database. You web application, possibly written in JSP have to make a database connection, get the value and populate the drop down.

Also there may be the situations, where you have 2 drop downs and depending on the value of first one, you have to populate the second drop down. In this kind of requirement, situation is worst. Here you have to make 2 connections one after the another and in second connection, the value of first drop down needs to be passed. Benefit for using this kind of architecture is simple design but at the expence of performance. To make you application efficient and to achieve good performance it will be good it we go for DOM in javascript. Below, I have given a very simple implementation of our drop down example.

In my case here is the requirement. I have 3 drop downs.

  1. Status
  2. Closing Code
  3. sub-closing Code

Situation is, when first drop down “status” is changed, it should populate the value for 2nd drop down “closing code”. When a value from 2nd drop down is selected, 3rd should get populated.

This is achieved using DOM in javascript. DOM stands for “Document Object Modeling”. Instead of using database table for storing the value, we user XML file for storing the values and XML is stored at server side. We parse the XML and populate the drop down from its values. Below screen shot shows the drop down required.

10.jpg

Here when I change the status drop down it should change the Closing Code values and on changing the closing code value it should change sub-Closing Code values. For this I created a XML file as given below.
================================================================


<?xml version="1.0" encoding="iso-8859-1"?>
<closing_codes>
<status value="11" active="y">
<issue_type value="OPEN ISSUE" active="y">
<sub_issue_type value="OPEN ISSUE" active="y"/>
</issue_type>
</status>
<status value="30" active="y">
<issue_type value="INFORMATION REQUESTED" active="y">
<sub_issue_type value="INFORMATION REQUESTED" active="y"/>
</issue_type>
</status>
<status value="40" active="y">
<issue_type value="BASE BUG NOT A BUG" active="y">
<sub_issue_type value="BASE BUG NOT A BUG" active="y"/>
</issue_type>
<issue_type value="EMS ISSUE" active="y">
<sub_issue_type value="EMS SETUP ISSUE" active="y"/>
<sub_issue_type value="EMS PRODUCT ISSUE" active="y"/>
</issue_type>
<issue_type value="HARDWARE ISSUE" active="y">
<sub_issue_type value="DISPLAY SERVER ISSUE" active="y"/>
<sub_issue_type value="INSUFFICENT DISK SPACE" active="y"/>
<sub_issue_type value="INSUFFICIENT SWAP" active="y"/>
<sub_issue_type value="INSUFFICIENT IO" active="y"/>
<sub_issue_type value="INSUFFICENT MEMORY" active="y"/>
<sub_issue_type value="MEDIA FAILURE" active="y"/>
<sub_issue_type value="HOST NOT REACHABLE" active="y"/>
</issue_type>

================================================================

Having this XML placed at correct location, next step is to load XML and get the contents
from it. Below javascript code shows loading of XMl file.

================================================================


function loadXML(xmlFile){
if (document.implementation &amp;&amp; document.implementation.createDocument)
{
xmlDoc = document.implementation.createDocument("", "", null);
xmlDoc.onload = verify;
}
else if (window.ActiveXObject)
{
xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.onreadystatechange = function () {
if (xmlDoc.readyState == 4) verify()
};
}
xmlDoc.load(xmlFile);
}

================================================================
The function is supplied with an arguement of XML file location and name in the form of URL.
In you main JSP code you can call the function as given below

================================================================


<SCRIPT language="javascript">
xmlfile = "http://mfgops.us.oracle.com:8890/ops/bug_closing/closing_codes.xml";
function populate_closing_code()
{
loadXML(xmlfile);
}
</SCRIPT>

================================================================

The function is mainly meant to work in IE as well as mozilla and netscape. For more explanation on the function please refer to the below URL

http://www.quirksmode.org/dom/importxml.html

Once the XML is loaded and available for accesssing, next step is to use the values in XML and populate the drop down.

Here logic we are using is to populate the “Closing Code” drop down with the “value” attribute of <issue_type> element and based on the value selected for closing code drop down, sub closing code drop down will be populated with “value” attribute of <sub_issue_type> sub elemment present in side the selected <issue_type> element.

To clarify the above point, let me explain by example.

Suppose the users selects the status drop down for status with value as 40 then, closing code drop down should get populated with values available in <issue_type> element inside that <status> element(having value 40) and sub-Closing Code drop down will et populated with values from <sub_issue_type> inside each <issue_type> element when the closing Code drop down is changed.

Below is function for populating closing code drop down.


function verify()
{
var i, n_elems, elems = xmlDoc.getElementsByTagName("issue_type");
var j = 0;
n_elems = elems.length;
document.forms['data'].closing_code.options.length = 0;
for (i = 0; i &lt; n_elems; i++)
{
if(document.forms['data'].status.selectedIndex == 0)
{
if(elems[i].parentNode.getAttribute("value") == 11)
{

document.forms['data'].closing_code.options[j]= new Option(elems[i].getAttribute("value"),elems[i].getAttribute("value"));
j++;
}
}
if(document.forms['data'].status.selectedIndex == 1)
{
if(elems[i].parentNode.getAttribute("value") == 30)
{

document.forms['data'].closing_code.options[j]= new Option(elems[i].getAttribute("value"),elems[i].getAttribute("value"));
j++;
}
}
if(document.forms['data'].status.selectedIndex == 2)
{
if(elems[i].parentNode.getAttribute("value") == 40)
{

document.forms['data'].closing_code.options[j]= new Option(elems[i].getAttribute("value"),elems[i].getAttribute("value"));
j++;
}
}
if(document.forms['data'].status.selectedIndex == 3)
{
if(elems[i].parentNode.getAttribute("value") == 66)
{

document.forms['data'].closing_code.options[j]= new Option(elems[i].getAttribute("value"),elems[i].getAttribute("value"));
j++;
}
}
if(document.forms['data'].status.selectedIndex == 4)
{
if(elems[i].parentNode.getAttribute("value") == 80)
{

document.forms['data'].closing_code.options[j]= new Option(elems[i].getAttribute("value"),elems[i].getAttribute("value"));
j++;
}
}
}

populate_sub_closing_code(document.forms['data'].closing_code.options[document.forms['data'].closing_code.selectedIndex].value);
}

Note here that the name of the function is verify, which should be same as we have in loadMXL function.

“xmlDoc.onload = verify;” | “if (xmlDoc.readyState == 4) verify()”

Here forms[‘data’] is the name of the form I am using in my JSP.

Status is the name of status drop down.

closing_code is the name of closing code drop down.

populate_sub_closing_code is the function we call from verify function to populate the sub-Closing code drop down. Why this is required? I will let you know this later.

Important point here is we are populating the closing code by calling verify function. But who is calling verify fucntion? Its loadXML. Who is calling loadXML? its populate_closing_code function we defined in out JSP. How populate_closing_code function is called? when we change the status. So for the status drop down we can have following fucntion.

onchange=”populate_closing_code(this.value);”

Based on this.value and if loop we can get the values from XML and populate closing code drop down.

Here the status drop down contains 5 values so the indexes will be mapped as given below.

value Index
11 0
30 1
40 2
66 3
80 4

So when index 2 is selected the value to be searched in XML is 40.

We can refer to the XML file elements using following

elems = xmlDoc.getElementsByTagName(“issue_type”);

Here we are getting all the elements of the name “issue_type”

To refer to the parent element of issue type, which is status we have to use

elems[i].parentNode.

To get the attribute of an element we have a method called


getAttribute("Attribute Name").

if(document.forms['data'].status.selectedIndex == 2)        // Checking the index seleced for status drop down
{
if(elems[i].parentNode.getAttribute("value") == 40)   // check for value of 40 in XML file for <status> element
{

document.forms['data'].closing_code.options[j]= new Option(elems[i].getAttribute("value"),elems[i].getAttribute("value"));  // populating closing_code drop down by appending value
j++;
}
}

This loop will run for the whole XML and populate closing_code drop down with “value” attribute of <issue_type> element which comes under the status that we select in status drop down.

Coming to populating the Sub-Closing Code drop down. This drop down is to be populated when there is change in value of closing code drop down. So we have to define a event on Closing Code drop down as given below.

onchange=”populate_sub_closing_code(this.value)”

So when we change the value in closing Code drop down this event will be triggered and it will call the function populate_sub_closing_code(). Below is the code for that.

================================================================


function populate_sub_closing_code(current_value)
{
var i, n_elems, elems = xmlDoc.getElementsByTagName("sub_issue_type");
var j = 0;
n_elems = elems.length;
document.forms['data'].sub_closing_code.options.length = 0;
while(''+current_value.charAt(0)==' ')
current_value=current_value.substring(1,current_value.length);
while(''+current_value.charAt(current_value.length-1)==' ')
current_value=current_value.substring(0,current_value.length-1);
for (i = 0; i &lt; n_elems; i++)
{
while(''+elems[i].parentNode.getAttribute("value").charAt(0)==' ')
elems[i].parentNode.getAttribute("value")=elems[i].parentNode.getAttribute("value").substring(1,elems[i].parentNode.getAttribute("value").length);
while(''+elems[i].parentNode.getAttribute("value").charAt(elems[i].parentNode.getAttribute("value").length - 1)==' ')
elems[i].parentNode.getAttribute("value")=elems[i].parentNode.getAttribute("value").substring(0,elems[i].parentNode.getAttribute("value").length-1);
if(elems[i].parentNode.getAttribute("value") == current_value)
{

document.forms['data'].sub_closing_code.options[j]= new Option(elems[i].getAttribute("value"),elems[i].getAttribute("value"));
j++;
}
}
}

================================================================

Here we are again refering to the XML as

elems = xmlDoc.getElementsByTagName(“sub_issue_type”);

The two while loop are for removing the spaces from the selected values we get from the
closing code drop down. Based on these values we will search the XML for <issue_type> element and get all the <sub_issue_type> elements listed inside that.

For example if the status selected is 40, then closing code will have values

BASE BUG NOT A BUG

EMS ISSUE

HARDWARE ISSUE

If a user select HARDWARE ISSUE from closing code drop down, sub closing code drop down should contain following values

DISPLAY SERVER ISSUE

INSUFFICENT DISK SPACE

INSUFFICIENT SWAP

INSUFFICIENT IO

INSUFFICENT MEMORY

MEDIA FAILURE

HOST NOT REACHABLE

To reach to these values we will search for HARDWARE ISSUE. current_value will give the selected value of drop down we are providing as an arguement.

elems[i].parentNode.getAttribute(“value”) == current_value is the actual comparison.

Note here that we are getting all the elements with <sub_issue_type> and not <issue_type> as in case of closing code. So when we say elems[i].parentNode.getAttribute(“value”), it will get the value attribute of all <issue_type> elements of every <sub_issue_type> element.

So this will populate Sub closing code.

One last thing to mention. As I said populate_sub_closing_code function is also called from verify function. This is because suppose we change the status from lets say 30 to 40. In that case Closing code drop down will get populated with required values. Here we can see that there is change in values, but populate_sub_closing_code function will not get triggered automatically. For this user needs to changes the values of closing code drop down explicitly. What we want is as soon as status is changed, closing drop down should get the required value and first value will get automatically selected. Based on this we
want the Sub Closing Code should get populated with required value (corresponding to first value of closing code drop down).

For this we are calling populate_sub_closing_code function from verify. So changing status drop down will trigger changing value for Closing Code and also Sub Closing Code.

Summarizing:

1) Create XML with the required format

2) In main JSP


<SCRIPT language="javascript">
xmlfile = "http://mfgops.us.oracle.com:8890/ops/bug_closing/closing_codes.xml";
function populate_closing_code()
{
loadXML(xmlfile);
}
</SCRIPT>

loadXML function is present in some other Javascript file. You can include the JS script file in
your main JSP as given below.

<script language=”javascript” src=”/ops/bug_closing/jsxml.js” type=”text/javascript”></script>

3) In the extrnal JS file (jsxml.js), create write below functions

function loadXML(xmlFile)
function verify()
function populate_sub_closing_code(current_value)

4) Include an event for status drop down

onchange=”populate_closing_code(this.value);”

5) Include an event for Closing drop down

onchange=”populate_sub_closing_code(this.value);”

Done !!

Advertisements

Javascript – Hide/Unhide the content

Javascript Development:

Developing a smart tool and a good user interface is really crucial. As a core DBA or Apps DBA we never think of any core programming exercise. But during the journey through database, we may come at a stage where you are required or expected to develop some really cool tools using JSP and Javascript combo.

Off course the language to be used is totally upto the developer to decide, unless there are some constraints enforced by the environment. Here I am describing a simple javascript funda, I used, while I was developing a tool to be used internally by our division.

Requirement:

The tool was basically to see the list of bugs logged by users, to update them and close them. This involves getting the data from database and showing it in UI. User will be entering the information and same has to be updated in database.

Now when a bug information is supposed to be viewed, it will be chunk of information shown to the DBA, which will contain all the details neccessary for DBA to work on. In my tool I used a link which can hide or show this information when a DBA queries the bug. I thought, its not always a good idea to show big information as soon as the bug is opened in the tool.

Below screen shot you can see what exactly I meant.

21.jpg

Here if you see the second label, which is “Bug Description”, it gives a long description of the contents of the bug. Also as and when the users and DBAs are updating the bugs the content get appended to this and it grows big. So better way is to hide the same and show when user wants to see. Below is the screen, when a user click on show/hide link and content is visible.

22.jpg

Now if you see, full content is visible. This simple, but amazing functionality can be implemented using javascript. Also javascript works at client side so no overhead on the application. No additional resource or network traffic utilization. Totaly works on client browser.

How it works?

The code for fetching the details of the bug content and displaying the same is been written in JSP and javascript is added to make this particular functionality work. The code in javascript, which fetches the information and displays the same is as given below.

==============================================================


<tr>

<td width=20%><P ALIGN=Right>Bug Description</P></td>
<td width=80%><P ALIGN=left>&lt;a href="#" <font color="#008000"><strong>onClick="showHide('prevUpdates');</strong></font>">Show/Hide</a></P></td>

</TR>
<tr>
<td width=20%><P ALIGN=left></P></td>
<strong><td id="prevUpdates" style="display:none"></strong>
<font color="#0000ff"><table BGCOLOR=#f2f2f5 align=left >
<% while(results.next()) { %>
<tr>
<td id="lineno" width=80%><P ALIGN=left><font face='Tahoma' size=2 ><%= results.getString("comments")%></font></P></td>
</tr>
<%}%>
</table></font>
<strong></td></strong>
</tr>

==============================================================

The line in the bold is the line which gives the name to the region and the lines in the blue color is the one which fetches the information and shows on JSP page.

As you can see in the green color that on clicking the link “Show/Hide”, it calls for showHide javascript and passes prevUpdates, which is the ID of the region we want to show or hide. Below is the javascript, which can hide or show the content when user clicks in “Hide/show” link.

==============================================================


function showHide(elem){
var el = eval(elem +'.style');
if (el.display == "none"){
el.display = "block";
} else {
el.display = "none";
}
}

==============================================================

Here elem will take the ID prevUpdates, which we supplied while calling the script. So what the script is doing is, when style=”display:none” is set and user clicks “Show/Hide” link its making display property as block, meaning that content will be shown. And when the content is being shown (display property is block), and user clicks the link, our javascript is making display property as none, that means the content will not be shown (hidden).

Such a functionality can be easily implemented using javascript, with not performance hit. In the next post, I will be covering “How to populate drop downs using XML file”.