Tuesday, January 22, 2008

Zapatec AJAX tree in APEX

In this post, I would like to demonstrate the way of using Zapatec AJAX tree in Apex.
From http://www.zapatec.com/ I downloaded the DHTML tree files.

After this, I applied some of them into my application. I decided to store them in my database, for maintainability.

There is the list of files that I used:
  • Java Script files
    • .. \zptree\src\tree.js
    • .. \utils\zapatec.js
  • CSS file
    • .. \zptree\themes\kde1.css
    • .. \zptree\themes\default.css
    • .. \zptree\themes\empty.css
    • .. \website\css\zpcal.css
    • .. \website\css\template.css
  • Images
    • Tree icons
      • .. \zptree\themes\kde1\folder_open.png
      • .. \zptree\themes\kde1\folder.png
      • .. \zptree\themes\kde1\document.png
    • Tree structure
      • .. \zptree\themes\img\fetching.gif
      • .. \zptree\themes\img\lines-b.gif
      • .. \zptree\themes\img\lines-c.gif
      • .. \zptree\themes\img\lines-s.gif
      • .. \zptree\themes\img\lines-t.gif
      • .. \zptree\themes\img\lines-v.gif
      • .. \zptree\themes\img\minus.gif
      • .. \zptree\themes\img\plus.gif
      • .. \zptree\themes\img\zpempty.gif

I imported it using Shred Documents -> Static Files -> Create
Next step, was adding css and javascript files to HTML Header of my page:
After that I changed all paths, that is used in css and javascripts to APEX ‘paths’, for example:
Original kde1.css

div.tree-item td.customIcon {
background: url("kde1/document.png") no-repeat 0 50%;
}

div.tree-item-expanded td.customIcon {
background: url("kde1/folder_open.png") no-repeat 0 50%;
}

div.tree-item-collapsed td.customIcon {
background: url("kde1/folder.png") no-repeat 0 50%;
}

APEX compatible:

div.tree-item td.customIcon {
background: url("wwv_flow_file_mgr.get_file?p_security_group_id=948527760686885&p_flow_id=100&p_fname=document.png") no-repeat 0 50%;
}

div.tree-item-expanded td.customIcon {
background: url("wwv_flow_file_mgr.get_file?p_security_group_id=948527760686885&p_flow_id=100&p_fname=folder_open.png") no-repeat 0 50%;
}

div.tree-item-collapsed td.customIcon {
background: url("wwv_flow_file_mgr.get_file?p_security_group_id=948527760686885&p_flow_id=100&p_fname=folder.png") no-repeat 0 50%;
}

After that I was ready to create a dynamical content for my tree. There is the needed structure for tree content:

<ul id="tree_defaults">
<li>Group 1
<ul>
<li>Sub Group 1
<ul>
<li>Document 1</li>
<
li>Document 2</li>
</ul>
</li>
<
li>Sub Group 2
<ul>
<
li>Document 3</li>
</ul>
<
/li>
</ul>
<
/li>
<
/ul>

<script type="text/javascript">
var tree_defaults = new
Zapatec.Tree({
tree: "tree_defaults",
defaultIcons: "customIcon",
saveState: true,
saveId: "saveState",
expandOnLabelClick: true,
highlightSelectedNode: true
});

</script>

In my case, I have to create content from two tables. One is the table of ‘groups’, another is the table of ‘documents’.


There is the source code of tree generating procedure:

function enum_documnet_tree (v_session integer) return varchar2
is
res varchar2(32000);

procedure add_str(v_str varchar2) is
begin
res := res || v_str || chr(10);
end;


procedure add_group(v_nid integer) is
v_name varchar2(256);
begin
select cname into v_name from group_table where nid = v_nid;
add_str('
<li>'||v_name);
add_str('<ul>');
for rec in (select nid, cname from group_table
where nparent_group = v_nid
order by 2) loop
add_group(rec.nid);
end loop;
for o_rec in (select o.cname, o.nid from documents o where ngroup = v_nid) loop

add_str('<li><a href="f?p=100:19:'||v_session||'::NO::P19_DOCUMENT_ID:'||o_rec.nid||'">'||o_rec.cname||'</a></li>');
end loop;
add_str('
</ul>');
add_str('
</li>');
end;
begin
res := '
<ul id="tree_defaults">';

for m_rec in (select nid from group_table where nparent _group is null) loop
add_group(m_rec.nid);
end loop;
for o_rec in (select o.cname, o.nid from documents o where ngroup is null) loop
add_str('
<li><a href="f?p=100:19:'||v_session||'::NO::P19_DOCUMENT_ID:'||o_rec.nid||'">'||o_rec.cname||'</a></li>');
end loop;
add_str('
</ul>');
add_str('
<script type="text/javascript">
var tree_defaults = new Zapatec.Tree({
tree: "tree_defaults",
defaultIcons: "customIcon",
saveState: true,
saveId: "saveState",
expandOnLabelClick: true,
highlightSelectedNode: true
});

<
/script>');
return res;
end;


Finaly I created a hidden item :P19_TREE. HTML region with source:
htp.p(:P19_TREE);

And process PL/SQL anonymous block (On Load – Before Header):
:P19_TREE:= enum_documnet_tree(:SESSION);

That’s it!

P.S. If you want to use this AJAX component, you have to read a Zapatec tree license agreement on http://www.zapatec.com/website/main/products/prod3/license.jsp

Google