於載入頁面時,顯示通知訊息 5 秒後自動消失
1. User Story

2. 原理
在 Oracle Apex 的 page 的 DOM 中新增一個元素, 用來顯示通知訊息。
於載入頁面時, 由 page/application process 輸出 JavaScript code, 要求 browser 執行 JavaScript code, 以顯示通知訊息。
使用 JQuery, 先選擇先前新增的元素, 再使用 JQuery 的方法
show().delay(5000).fadeOut()
來顯示通知訊息。
3. 實作步驟
Step 1: 在 App 的 Navigation Tool Bar 中新增一個 Icon, 做為訊息通知的父元素

在 Image/Class 欄位中, 除了 Icon class name 之外, 還要加上一個自訂的 class name msg-alert
, 以便於 JavaScript code 中選擇此元素。

Step 2: 設定傳訊息通知 CSS
我們會在相對於父元素的某個位置, 顯示訊息通知。
使用 absolute
定位, 並設定 top
, right
的值, 來控制訊息通知的位置。 使用 absolute
定位, 不會佔據父元素的位置, 會浮在父元素的上方。 「訊息通知」 會顯示在父元素下方 30px 的位置, 並靠右對齊。

預設不顯示 (display:none
), 並設定背景顏色, 文字顏色, 邊框等樣式。 之後, 我們會使用 JavaScript code, 來控制「訊息通知」的顯示與消失。
所需的 CSS 如下:
.msg-notification {
display: none;
position: absolute;
top: 60px;
right: 0px;
color: black;
background-color: lightyellow;
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
}
Step 3: 將 CSS 加入到 App 的靜態檔案中, 並將其引入到 App 中
Path: Shared Components > Static Application Files > (B)Create File

輸入 File Name 並按下 Create 按鈕, 可建立一個新的 CSS file 並編輯其內容。
若已在外部編輯好 CSS file, 可直接 Drag & Drop 檔案到此頁面中。
我們在 File Name 中輸入 notification.css
:

接著, 在 CSS file 中貼上上述的 CSS code:

Oracle Apex 會 minify CSS code, 以減少檔案大小。在 File Name 欄位下方有一個 Reference 欄位, 可以看到 minify 後的 CSS 連結。
複制此連結供後續使用。
接著要將 CSS 引入到 App 中。
路徑 Shared Components > User Interface Attributes > CSS
在 File URLs 欄位中, 貼上剛才複制的 minify 後的 CSS 連結。

Step 4: 設定新增「訊息通知」元素的 JavaScript code 及其它輔助 function
在頁面載入時, 會執行以下動作:
選取父元素, 使用
.msg-alert
元素的上兩層元素為父元素。建立一個新的 div 元素, 並設定其內容為
Message Placeholder
設定 div 元素的 class name 為
msg-notification
, 以便套用 CSS 樣式將 div 元素加入到父元素中
此外, 定義一個輔助 function showMessage(message)
, 用來顯示訊息通知。
此 function 會選取 class name 為 msg-notification
的元素, 並設定其內容為 message 引數的值。 最後, 使用 JQuery 的方法 show().delay(5000).fadeOut()
來顯示訊息通知。
message
引數的內容, 除了文字之外, 也可以含有 HTML 元素, 例如 <a href="...">link</a>
, 因為 innerHTML
會將其解析為 HTML 元素。
/**
* Create a new div element and position it relative to the msg-alert element.
*
* The following code will be executed when the page is loaded.
*/
// 1. Get the parent element. In this case, it is the .msg-alert element
let msgAlert = document.querySelector('.msg-alert');
// 不可以直接在msg-alert元素上添加新元素,因为 msg-alert 是 anchor 元素。若在 anchor 元素上添加 anchor 元素, 子元素的 anchor 無法被點擊。
let parent = msgAlert.parentElement.parentElement;
// 2. create a new div element for the message
let msgDiv = document.createElement('div');
msgDiv.innerHTML = 'Message Placeholder';
// 3. set the class name for the div element
// The class name should be the same as the one in the CSS file in the previous step.
msgDiv.classList.add('msg-notification');
// 4. append the div element to the body
parent.appendChild(msgDiv);
// The helper function to show the message
function showMessage(message) {
let msgDiv = document.querySelector('.msg-notification');
msgDiv.innerHTML = message;
$('.msg-notification').show().delay(5000).fadeOut();
}
此 JS 程式會將「訊息通知」元素加下 <li class="t-NavigationBar-item>
元素內, 而不是 <a class="msg-alert">
元素內, 以避免在 anchor 元素內添加 anchor 元素。

Step 5: 將 JavaScript code 加入到 App 的靜態檔案中, 並將其引入到 App 中
此步驟的操作方式和 Step 3 類似。
建立 static JavaScript file 的路徑: Shared Components > Static Application Files > (B)Create File
將前一步驟的 JavaScript code 複制貼上到此檔案中:

複製 minify 後的 JavaScript 連結, 供後續使用。
接著, 將 JavaScript file 引入到 App 中, 路徑: Shared Components > User Interface Attributes > JavaScript

Step 6: 觀察 custom js 及 css file 的載入順序。
Custom CSS file 會在 Apex Page 中的 <head>
中引入

Custom JS file 會在 Apex Page 中的 <body>
的最後引入

我們後續用 PL/SQL code 來輸出的 JavaScript code 會在 custom js file 之後載入。 如此, 我們才能正確的呼叫 showMessage()
function。
Step 7: 在 App 的 Page 中, 新增一個 Application Process, 用來輸出 JavaScript code
我們會去 test_orders
table 中, 查詢是否有狀態 new
的訂單。
如果有一筆以上的訂單, 則輸出文字 You have [n] new orders.
.
這個 App Process 的執行時間點設為 On Load: After Footer (page template footer)
. 這個時間點設定後重要, 因為要確保 先前的 custom js file 已經載入, 才能呼叫 showMessage()
function。
若將 App Process 的執行時間點設為 On Load: After Body Regions
, 則會發生錯誤, 因為 custom js file 尚未載入。
所需要的 PL/SQL code 如下:
declare
v_order_count number;
-- v_js_str varchar2(1000) := '<script> apex.message.alert("#MSG#"); </script>';
-- Call the javascript function showMessage
v_js_str varchar2(1000) := '<script> showMessage("#MSG#") </script>';
v_msg varchar2(1000);
begin
apex_debug.enable(apex_debug.c_log_level_info);
-- Check if any new orders in the test_orders table
select count(*) into v_order_count
from test_orders
where order_status = 'new';
if v_order_count > 0 then
-- show message
v_msg := 'You have ' || v_order_count || ' orders.';
v_js_str := replace(v_js_str, '#MSG#', v_msg);
apex_debug.info('== Notification: %s', v_js_str);
htp.p(v_js_str);
end if;
end;
在上述的 PL/SQL code 中, 使用 htp.p()
來輸出 JavaScript code, 以呼叫 showMessage()
function。 這會在 Page 中輸出一段 JavaScript code, 例如:
<script> showMessage("You have 1 orders.") </script>
如此, 便會呼叫 showMessage()
function, 並顯示訊息通知。
要新增 Application Process, 路徑: App > Shared Components > Application Processes > (B)Create

接著設定 Process 的 Process Point
及 Name:

再設定 Process 的 Source, 將上述的 PL/SQL code 貼上:

若要限制此 Process 的執行範圍, 可以設定 Conditions
:

例如, 只有在特定的 Page 中執行此 Process:

Step 8: 測試
登入 APP 後, 進到首頁或任何頁面, 若 test_orders
table 中有狀態為 new
的訂單, 則會顯示訊息通知。
4. 顯示可點擊的訊息通知
修改前述幾個地方可以讓「訊息通知」內含有可點擊的連結, 例如點擊後查看最新的一筆訂單。

JavaScript 和 CSS 的部分不需要修改, 只需要修改 PL/SQL code。
我們首先將產生「訊息通知」的動作抽取出來, 成為 2 個 local (nested) functions.
showOrderCount
function 回傳有新訂單的訊息字串showNewestOrderURL
function 回傳最新訂單的 URL, user 可以點擊連結查看最新的訂單。
showOrderCount
function 的內容如下:
function showOrderCount(p_order_count in number) return varchar2 is
begin
return '<p> You have ' || p_order_count || ' orders. </p>';
end;
showNewestOrderURL
function 的內容如下:
function showNewestOrderURL(p_page_id number, p_item_name varchar2, p_order_id number) RETURN varchar2 is
l_msg varchar2(2000);
l_url varchar2(2000);
begin
l_url := apex_page.get_url(p_page => p_page_id,
p_items => p_item_name,
p_values => p_order_id);
l_msg := q'[<p><a href=']' || l_url || q'[' aria-hidden='false' >]' || '您有最新訂單 ID ' || p_order_id || '</a> </p>';
return l_msg;
end;
此程式中的重點:
使用
apex_page.get_url()
來取得 URL.p_page
是目的頁面編號,p_items
是目的頁面的 item name 同時也是 primary key item,p_values
是 primary key 的值。l_msg
是產生的 anchor 元素. 組合 URL 字串時, 屬性值要用單引號包住, 而不是雙引號。因為 PL/SQL 的htp.p
產生字串內容時是使用雙引號。
所以, 修改後的 PL/SQL code 如下:
declare
v_order_count number;
v_order_id number;
-- v_js_str varchar2(1000) := '<script> apex.message.alert("#MSG#"); </script>';
-- Call the javascript function showMessage
v_js_str varchar2(1000) := '<script> showMessage("#MSG#") </script>';
v_msg varchar2(1000);
function showOrderCount(p_order_count in number) return varchar2 is
begin
return '<p> You have ' || p_order_count || ' orders. </p>';
end;
function showNewestOrderURL(p_page_id number, p_item_name varchar2, p_order_id number) RETURN varchar2 is
l_msg varchar2(2000);
l_url varchar2(2000);
begin
l_url := apex_page.get_url(p_page => p_page_id,
p_items => p_item_name,
p_values => p_order_id);
l_msg := q'[<p><a href=']' || l_url || q'[' aria-hidden='false' >]' || '您有最新訂單 ID ' || p_order_id || '</a> </p>';
return l_msg;
end;
begin
apex_debug.enable(apex_debug.c_log_level_info);
-- Check if any new orders in the test_orders table
-- Select the total number of new orders
select count(*) into v_order_count
from test_orders
where order_status = 'new';
-- Select the newest order id
select order_id into v_order_id
from test_orders
where order_status = 'new'
order by order_datetime desc
fetch first 1 row only;
if v_order_count > 0 then
-- show message
v_msg := showOrderCount(v_order_count);
-- Assume the page 2 display the order detail
v_msg := v_msg || showNewestOrderURL(2, 'P2_ORDER_ID', v_order_id);
v_js_str := replace(v_js_str, '#MSG#', v_msg);
apex_debug.info('== Notification: %s', v_js_str);
htp.p(v_js_str);
end if;
end;
5. 總結
透過 JavaScript code, 我們在 Navigation Tool Bar 的某個元素下,新增一個元素,用來顯示訊息通知。
這些需要的 JavaScript code 和 CSS code, 上傳到 App 的靜態檔案中, 並引入到 App 中。
App 中的每個頁面都會載入這些靜態檔案。
使用 PL/SQL code, 在 App Process 中輸出 JavaScript code, 以呼叫 JavaScript function, 來顯示訊息通知。
若要產生可點擊的訊息通知, 可以在 PL/SQL code 中, 產生包含 anchor 元素的 HTML 字串。
使用
apex_page.get_url()
來產生 URL 字串, 以便使用者點擊連結查看最新的訂單。
Last updated
Was this helpful?