开发人员:Application Express

构建 Ajax 内存树

作者:Scott Spendolini

学习如何在 Oracle Application Express 中逐步创建基于 Ajax 的内存树。

 

到现在为止,您可能听说过 Ajax(Asynchronous JavaScript and XML 的缩写)。如果您使用过 Google Maps、Yahoo Mail 和 Flickr,便会体会到创建丰富的、交互式 UI 的可能性。

Ajax 本身并不是一项技术,而是通过网页实现的多种技术(HTML、CSS、JavaScript 和 XML)的组合。从本质上而言,Ajax 就是将类似客户端-服务器这样的功能扩展到了 Web。

在本文中,您将学习如何基于任何包含层次数据的表在 Oracle Application Express(以前的 HTML DB)中构建一个基于 Ajax 的内存树。(该内存树的代码基于 Application Express 开发小组成员 Carl Backstrom 提供的示例应用程序。)我之所以在此处增加了“内存”一词,是因为与 Carl 的示例不同,该树将“记住”在各个页面视图中展开、折叠以及选定的节点。此外,还有一个搜索功能,用于定位树中的任何节点并相应地将其展开 — 这是一个使用 Application Express 提供的树组件无法实现的功能。当树使用 Ajax 获取展开的节点时,它可以轻松地伸缩以支持一个具有数千或更多行的表。

要求

  • 可以访问 Oracle Application Express 2.0 工作区
    可以通过在 http://apex.oracle.com 上请求一个免费工作区或安装 Oracle 数据库 10g 快捷版 (XE)(只限 Windows 和 Linux)来快速访问这样的工作区。请注意,早期版本(1.5 和 1.6)将不起作用。
  • 一个包含层次数据(ID、父 ID、名称)的表
    如果没有以这种方式对数据进行了格式化的表,则可以使用 EMP 演示表。

第 1 步:创建所需的表、序列和触发器

首先,登录到 Application Express 工作区,并创建树所需的数据库对象。TREE_TEMP 表将跟踪针对每个用户展开的树节点。每当用户单击树中的 + 或 - 图标时,该表将通过 JavaScript 和应用程序级进程自动进行异步填充。

从 SQL Workshop 中:

  1. 使用您的 Workspace NameUsernamePassword 登录(如果使用 Oracle 数据库 XE,则只需使用 UsernamePassword 登录)。
  2. 单击 SQL Workshop
  3. 单击 SQL Commands
  4. 将以下代码复制并粘贴到 SQL 区域:

    create sequence tree_temp_seq start with 1
    

    然后单击 Run

  5. 将以下代码复制并粘贴到 SQL 区域:
    create table tree_temp
       (    temp_id number, 
                app_user varchar2(100), 
                app_session varchar2(100), 
                pid number, 
                id number, 
                name varchar2(100), 
                exp char(1), 
                icon varchar2(10)
       )    
    /
    

    然后单击 Run

  6. 将以下代码复制并粘贴到 SQL 区域:
    create or replace trigger tree_temp_bi
       before insert on tree_temp
       for each row
       declare      
             l_temp_id number;
       begin
             select tree_temp_seq.nextval
              into l_temp_id
              from dual;
             :new.temp_id := l_temp_id;
       end;
    /
    

    然后单击 Run

第 2 步:创建所需的视图

Ajax 内存树基于视图而不是表。例如:

create or replace force view tree_view
 (pid, id, name)
as      
select mgr pid, empno id, ename name from emp
/

所使用的视图必须只有三列并遵循下列指导原则:

  • PID:节点的父 ID
  • ID:节点的唯一标识符
  • Name:要显示的名称

该表还必须只有一个 PID 为空的行。该节点将是树中最高级别的节点。

您在此处开发的树将使用 EMP 表。如果要使用您自己的表,请相应地调节 CREATE VIEW 过程。

从 SQL Workshop 中:

  1. 将 CREATE VIEW 代码复制并粘贴到 SQL 区域,然后单击 Run

第 3 步:安装 Ajax_MEMORY_TREE 程序包

接下来,创建 Ajax_MEMORY_TREE 程序包。该程序包包含所有用于控制树的逻辑。

  1. 将以下代码复制并粘贴到 SQL 区域:
    create or replace package ajax_memory_tree
    is      
       procedure init;
       procedure render;
       procedure find_node (p_id in varchar2);
       procedure process_click;
       procedure contract;
       procedure expand;
    end ajax_memory_tree;
    /
    

    然后单击 Run

  2. 清单 1 中的代码复制并粘贴到 SQL 区域,然后单击 Run

第 4 步:创建 Application Express 应用程序

至此已经创建了所需的数据库对象,下一步将创建 Application Express 应用程序。如果已经有一个现成的 Application Express 应用程序,则可以在其中创建 Ajax 内存树。

  1. 单击 Application Builder
  2. 单击 Create >
  3. 选择 Create Application 并单击 Next >
  4. 输入应用程序的 Name(如 Ajax Memory Tree),然后单击 Next >
  5. 单击 Add Page,然后单击 Next > 添加一个空白页。
  6. 选择 One Level of Tabs 并单击 Next >
  7. Copy Shared Components from Another Application 选择 No 并单击 Next >
  8. 使用 Authentication SchemeLanguageUse Language Preference Derived From 的默认值,然后单击 Next >
  9. 选择 Theme 3,然后单击 Next >
  10. 单击 Create 创建应用程序。

第 5 步:创建区域和项目

然后,创建树所需的区域和项目。Page 1(页面 1)需要三个区域:

  • JavaScript & CSS
    该区域将保存所需的 JavaScript 函数和一个小型的内联 CSS 或样式表定义。
  • Ajax Memory Tree
    该区域只调用 ajax_memory_tree.render 过程,该过程随后将在页面上呈现树。
  • Current Node
    这是一个简单的 SQL 报表,其中突出显示了树中选定节点的详细信息。
  1. 单击 1 - Page 1 编辑应用程序中的第 1 页。
  2. 单击 Add Region 图标创建一个新的 Region

     

    图 1

     

  3. 选择 HTML 并单击 Next >
  4. 再次选择 HTML 并单击 Next >
  5. Title 输入 JavaScript and CSS,为 Region Template 选择 No Template,然后单击 Next >
  6. 对于 HTML Region Text Source,复制并粘贴清单 2 中的代码,然后单击 Create Region

此 JavaScript 包含三个用于控制树的折叠和展开的函数以及一个弹出式 Find 窗口:

  • popupNodeFinder
    该函数将只基于应用程序的第 2 页打开一个新的弹出窗口。
  • html_TooglePlusMinus
    该函数在由 getTreeNode 调用时将切换单击的 + 和 - 图标。此外,它还将 Application Express Item P1_BRANCH 设置为刚刚单击的项目的值。最后,它将异步调用某个应用程序进程(contractTree 或 expandTree),该进程随后将更新 tree_temp 表。
  • getTreeNode
    该函数是 Ajax 内存树的核心。每次单击树中的 + 或 - 图标时将调用该函数。该函数在执行时将首先调用 html_TogglePlusMinus,后者将更改图标设置 P1_BRANCH。然后,它将调用应用程序进程 processClick 并传入 P1_BRANCH 的值。随后,processClick 进程将调用 ajax_memory_tree.process_click 过程,该过程将呈现新展开的节点及其同类。

该区域的嵌入样式表部分用于指示当前选定的节点。选择节点后,selected_node 样式将应用于该节点,从而为其提供一个浅绿色的背景。所有其他节点使用 unselected_node 样式呈现。

接下来,创建树的区域。该区域将只包含一个针对 ajax_memory_tree package.render 过程的 PL/SQL 调用。

  1. 单击 Add Region 图标创建一个新的 Region
  2. 选择 PL/SQL Dynamic Content 并单击 Next >
  3. Title 输入 Ajax Memory Tree,然后单击 Next >
  4. 对于 PL/SQL Source 输入 ajax_memory_tree.render;,然后单击 Create Region

要使树起作用,还必须向该页中添加四个项目。这些项目用于存储信息,如树的根节点、单击的节点以及树的当前节点。

  1. 单击 Add Item 图标创建一个新的 Item
  2. 选择 Hidden 并单击 Next >
  3. 对于 Item Name 输入 P1_TREE_ROOT,选择 Ajax Memory Tree 作为 Region,然后单击 Next >
  4. 单击 Create Item
  5. 单击 Add Item 图标创建一个新的 Item
  6. 选择 Hidden 并单击 Next >
  7. Item Name 输入 P1_SELECTED_NODE,选择 Ajax Memory Tree 作为 Region,后单击 Next >
  8. 单击 Create Item
  9. 单击 Add Item 图标创建一个新的 Item
  10. 选择 Hidden 并单击 Next >
  11. Item Name 输入 P1_MESSAGE,选择 Ajax Memory Tree 作为 Region,然后单击 Next >
  12. 单击 Create Item
  13. 单击 Add Item 图标创建一个新的 Item
  14. 选择 Hidden 并单击 Next >
  15. 对于 Item Name 输入 P1_BRANCH_ID,选择 Ajax Memory Tree 作为 Region,然后单击 Next >
  16. 单击 Create Item
  17. 单击 Add Item 图标创建一个新的 Item
  18. 选择 Display Only 并单击 Next >
  19. 选择 Display as Text (does not save state) 并单击 Next >
  20. 对于 Item Name 输入 P1_FIND,选择 Ajax Memory Tree 作为 Region,然后单击 Next >
  21. 对于 Label,输入:
    <a href="#" onClick="popupNodeFinder ()";><img 
    src="/i/flashlight.gif" title="Find an Employee"></a> 
    
  22. 对于 Label Template 选择 Optional,然后单击 Next >
  23. 单击 Create Item

接下来,您将需要创建一个简单的报表区域。该报表将显示树中当前选定节点中的数据。

  1. 单击 Add Region 图标创建一个新的 Region
  2. 选择 Report 并单击 Next >
  3. 选择 SQL Report 并单击 Next >
  4. 输入 Current Node 作为 Title,选择 2 作为 Column,然后单击 Next >
  5. 对于 SQL Query 输入:
    select * from tree_view where id = :P1_SELECTED_NODE
    
    然后单击 Create Region

第 6 步:创建进程和分支

为简化树的导航和控制,需要创建两个页面级进程、三个应用程序级进程和一个分支。

在每个会话中,一次将只调用一个页面级进程 (Initialize the Tree)。该进程将调用 ajax_memory_tree.init 过程,用于从当前用户的 tree_temp 表中清除过时的会话信息,并设置树的根节点。

另一个页面级进程 (Find Node) 仅当在调用 Find Node 弹出窗口时执行。该进程将调用 ajax_memory_tree.find_node 过程,传入用户选择的节点。然后,它将呈现该树,突出显示指定节点并相应地展开树。

  1. Page Rendering - Processes 下,单击 Add Process 图标添加一个新进程。
  2. 选择 PL/SQL 并单击 Next >
  3. 输入 Initialize the Tree 作为 Name 并单击 Next >
  4. 对于 Enter PL/SQL Page Process,输入: ajax_memory_tree.init;
    并单击 Next >
  5. 保留 Success & Failure Messages 为空并单击 Next >
  6. 对于 Condition Type,选择 Value of Item in Expression 1 is NULL,对于 Expression 1 输入 P1_TREE_ROOT,然后单击 Create Process
  7. Page Processing - Processes 下,单击 Add Process 图标添加一个新进程。
  8. 选择 PL/SQL 并单击 Next >
  9. 输入 Find Node 并单击 Next >
  10. 对于 Enter PL/SQL Page Process,输入: ajax_memory_tree.find_node(:P1_SELECTED_NODE);
    ,然后单击 Next >
  11. 保留 Success & Failure Messages 为空并单击 Next >
  12. 对于 Condition Type,选择 Request = Expression 1,对于 Expression 1 输入 FIND_NODE,然后单击 Create Process

为支持树的异步或 Ajax 部分,您需要创建三个应用程序级进程。这些进程将由先前添加到该页的 JavaScript 函数调用。

例如,JavaScript 函数 getTreeNode 将调用应用程序级进程 processClick,并在应用程序的 Page 0 上运行它:

htmldb_Get(null,&APP_ID.,'APPLICATION_PROCESS=processClick',0);
get.add('P1_BRANCH_ID',pValue);
gReturn = get.get();

此处获得有关 htmldb_Get 函数的更多信息。

  1. 在 Breadcrumb Menu 中,单击 Application X,其中 X 是应用程序的 Application ID。

     

    图 2

     

  2. 单击 Shared Components
  3. Logic 下,单击 Application Processes
  4. 单击 Create >
  5. 对于 Name 输入 contractTree,选择 On Demand:Run this application process when requested by a page process,然后单击 Next >
  6. Process Text 输入: ajax_memory_tree.contract;,然后单击 Next >
  7. 单击 Create Process
  8. 单击 Create >
  9. 对于 Name 输入 expandTree,选择 On Demand:Run this application process when requested by a page process,然后单击 Next >
  10. Process Text 输入: ajax_memory_tree.expand;,然后单击 Next >
  11. 单击 Create Process
  12. 单击 Create >
  13. 对于 Name 输入 processClick,选择 On Demand:Run this application process when requested by a page process,然后单击 Next >
  14. Process Text 输入: ajax_memory_tree.process_click;,然后单击 Next >
  15. 单击 Create Process

最后,您需要构建一个无条件分支。该分支无条件地将应用程序重新定向回 Page 1。

  1. 单击页面右上角的 Edit Page 图标编辑第 1 页。

     

    图 3

     

  2. 单击 Add Branch 图标创建一个新的 Branch
  3. 接受默认值,然后单击 Next >
  4. Page 输入 1,然后单击 Next >
  5. 单击 Create Branch

第 7 步:创建其他页面

Ajax 内存树的所有项目和区域均置于应用程序的第 1 页上。但为使树正常工作,还需要两个页面。

  • Page 0:要使 Ajax 组件正常工作,需要创建第 0 页,该页是 Application Express 中的特殊页面。当应用程序级进程运行时,它们将在第 0 页上运行。由于第 0 页不包含逻辑,并且由于不执行任何其他业务规则,因此应用程序进程可以在该页上安全地运行。
  • Search Page:为使搜索功能正常工作,还需要创建另一个标准页面。该页面可以是 Application Express 中的任何页面编号。本示例使用了第 2 页。
  1. Page Definition 页上,单击 Create > 按钮,该按钮紧靠 Edit Attributes 按钮的右侧。

     

    图 4

     

  2. 选择 New Page 并单击 Next >
  3. 选择 Blank Page 并单击 Next >
  4. 对于 Page 输入 0,然后单击 Next >
  5. 对于 Name 输入 Page Zero,然后单击 Next >
  6. 对于 Would you like to use tabs for this new page? 选择 No,然后单击 Next >。单击 Finish
  7. 单击 Edit Page
  8. Page Definition 页上,单击 Create > 按钮,该按钮紧靠 Edit Attributes 按钮的右侧。
  9. 选择 New Page 并单击 Next >
  10. 选择 Blank Page 并单击 Next >
  11. 对于 Page 输入 2,然后单击 Next >
  12. 对于 Name 输入 Find Node,然后单击 Next >
  13. 对于 Would you like to use tabs for this new page? 选择 No,然后单击 Next >
  14. 单击 Finish
  15. 单击 Edit Page

第 8 步:创建第 2 页区域

需要在第 2 页上创建两个区域:一个区域用于保存将选定节点回传至第 1 页所需的 JavaScript,另一个区域用于保存针对树中所有项目的报告。如果树包含很多项目,则可以以后自定义该报表以包含搜索功能。

  1. 单击 Add Region 图标在第 2 页上创建一个新的 Region
  2. 选择 HTML 并单击 Next >
  3. 再次选择 HTML 并单击 Next >
  4. 对于 Title 输入 JavaScript,对于 Region Template 选择 No Template,然后单击 Next >
  5. 对于 HTML Region Text Source,请复制并粘贴以下代码:
    <script language="JavaScript">
            function passBack(passVal1, passVal2)
            {
            opener.document.getElementById("P1_SELECTED_NODE").value = passVal1;
            opener.document.getElementById("P1_MESSAGE").value = passVal2;
            window.opener.doSubmit('FIND_NODE');
            close();
            }
     </script>
    

    然后单击 Create Region

  6. 单击 Add Region 图标创建一个新的 Region
  7. 选择 Report 并单击 Next >
  8. 选择 SQL Report 并单击 Next >
  9. 输入 Search for a Node 作为 Title,然后单击 Next >
  10. 对于 SQL Query,输入:

     

    select id, name, '[select]' pick from tree_view
    


    然后单击 Create Region

当用户选择一个要查看的节点时,必须调用 JavaScript 的 passBack 函数。该函数将选定 ID 回传至原始页面并提交它。它还将触发要运行的 Find Node 进程。

  1. 单击 Report 区域旁边的单词 Report
  2. 单击相应的 Edit 图标编辑 Pick 列。

     

    图 5

     

  3. 向下滚动到 Column Link 部分。
  4. 对于 Link Text 输入 #PICK#,选择 URL 作为 Target,并对 URL 输入

    javascript:passBack('#ID#','The current node is now #NAME# .')
    
  5. 滚动到页面顶端,然后单击 Apply Changes
  6. 再次单击 Apply Changes

第 9 步:测试 Ajax 内存树

此时,您已经创建了 Ajax 内存树所需的所有组件。余下的操作就是测试应用程序。

  1. 在 Breadcrumb Menu 中,单击 Application X,其中 X 是应用程序的应用程序 ID。
  2. 单击 Run Application
  3. 使用登录到 Application Express 时所使用的同一用户名和密码。
  4. 单击 + 或 - 图标展开和/或折叠每个节点。此外,单击树中的名称并验证 Current Node 报告是否已更改。

您的应用程序应如下所示:

 

图 6

 




恭喜,您已经在 Application Express 中构建了一个基于 Ajax 的树!

要获得另一个有关如何使用 Ajax 扩展 Oracle HTML DB 的简短示例,请参阅我在此处发表的网志条目。

 


Scott Spendolini ( scott@sumnertech.com ) 是 Sumner Technologies, LLC ( www.sumnertech.com) 的总裁和创始人,这是一家专门研究 Oracle Application Express 的咨询公司。

 

将您的意见发送给我们