Меню как в Oracle BI


Сегодня, в день знаний, захотелось с вами поделится опытом создания контекстного меню в приложении реализованном на Oracle APEX.

C начала года мы участвуем в проекте по разработке витрины данных для отчетности НБУ, на основе хранилища данных. В рамках проекта, кроме всего прочего, было реализовано несколько приложений на Oracle APEX и у меня в какой-то момент возникла идея связать их в одно информационное пространство с помощью контекстного меню на подобие того что есть в Oracle BI и из которого можно перейти в BI Publisher, Answers и другие приложения.

Чтобы не изобретать велосипед “отдолжим” у Oracle BI java скрипты которые отвечают за отрисовку и работу меню, это такие файлы:

•    browserdom.js
•    common.js
•    menu.js

В первозданном виде они не подошли, поэтому пришлось с ними поработать и за комментировать “лишние” части кода.

Также для меню понадобится несколько картинок и таблиц стилей

•    sdw_corner.png
•    sdw_horz.png
•    sdw_vert.png
•    menu.css
•    portalbanner.css
•    inject_menu.js

Все эти файлы качать от сюда …

Копируем все файлы в предварительно созданную папку popup_menu на сервере где установлен APEX в папку с темами

Теперь, для теста, можно попробовать на странице добавить такой HTML код

<table>
<tr>

<td>
<a href="void(null)"> Інші програми   </a>
</td>

</tr>
</table>

<div align="left" class="NQWMenu" id="MainBarProductMenu" style="position:absolute;top:66px;left:777px;visibility:hiden;">
<table cellspacing="0px" class="menuShadowWrapper">
   <tr>
       <td class="shadowMenuCell" colspan="2" rowspan="2">
          <a href="http://borlas.com.ua" name="orabiee" class="NQWMenuItem"> Oracle BI EE </a>
          <div class="NQWMenuItemSeparator"></div>
          <a href="http://www.pib.com.ua" name="ods" class="NQWMenuItem"> ODS (Operation Data Store) </a>
      </td>
      <td class="shadowOffsetCellRight"></td>
   </tr>
  <tr>
     <td class="shadowRight"> </td>
  </tr>
  <tr>
     <td class="shadowOffsetCellBottom"></td>
     <td class="shadowBottom"> </td>
     <td class="shadowCorner"></td>
  </tr>
</table>
</div>

В результате у нас должно появиться такое вот меню

Теперь переходим к задаче номер два, создать настроечную таблицу в которой можно было бы вести пункты контекстного меню и разместить меню в области Navigation Bar Entries.

Начнем с таблицы:

create table ODS$APPLICATION_LIST
(
  appl_name         VARCHAR2(255),
  appl_url          VARCHAR2(1000),
  appl_html_name    VARCHAR2(255),
  appl_order        NUMBER,
  appl_is_separator CHAR(1) default 'N'
)
-- Add comments to the table
comment on table ODS$APPLICATION_LIST
  is 'Список інших додатків';
-- Add comments to the columns
comment on column ODS$APPLICATION_LIST.appl_id
  is 'Id запису';
comment on column ODS$APPLICATION_LIST.appl_name
  is 'Назва додатку';
comment on column ODS$APPLICATION_LIST.appl_url
  is 'URL для переходу к додатку';
comment on column ODS$APPLICATION_LIST.appl_html_name
  is 'Назва HTML елементу в меню';
comment on column ODS$APPLICATION_LIST.appl_order
  is 'Порядок сортування';
comment on column ODS$APPLICATION_LIST.appl_is_separator
  is 'Ознака - строка являе собою роздільник чи ні';

Реализовываем под эту таблицу простой интерфейс ввода данных

Теперь создадим процедуру которая на основании данных в таблице со списком ссылок будет формировать нужный нам HTML код:

create or replace package ODS$GUI_PKG is

  -- Author  : Алексей Мовчанюк
  -- Created : 12.08.2011 11:31:06
  -- Purpose : Містить процедури і функції для графічного інтерфейсу APEX

  -- Public function and procedure declarations

  -- Функція генерує HTML код для меню переходу до інших програм
  function Get_Main_Bar_Product_Menu_F return varchar2;

end ODS$GUI_PKG;
create or replace package body ODS$GUI_PKG is

  -- Функція генерує HTML код для меню переходу до інших програм
  function Get_Main_Bar_Product_Menu_F return varchar2 is

    v_HTML_Code varchar2(10000);

    cursor c_Apps is
       select apps.appl_name, apps.appl_html_name, apps.appl_url, apps.appl_is_separator
       from application_list apps
       order by apps.appl_order;

  begin

    -- Ініциалізуємо змінні

    -- Генеруемо заголовок меню
    v_HTML_Code := v_HTML_Code || '<table cellspacing="0px" class="menuShadowWrapper">';
    v_HTML_Code := v_HTML_Code || '   <tr>';
    v_HTML_Code := v_HTML_Code || '       <td class="shadowMenuCell" colspan="2" rowspan="2">';

    -- Додаемо ссилки на інші програми
    FOR a IN c_Apps LOOP
      IF a.appl_is_separator = 'Y' THEN
        v_HTML_Code := v_HTML_Code || '          <div class="NQWMenuItemSeparator"></div>';
      ELSE
        v_HTML_Code := v_HTML_Code || '          <a href="' || a.appl_url || '" target="_blank" name="' || a.appl_html_name || '" class="NQWMenuItem"> ' || a.appl_name || ' </a>';
      END IF;

    END LOOP;
    -- Генеруемо кінець заголовку меню
    v_HTML_Code := v_HTML_Code || '      </td>';
    v_HTML_Code := v_HTML_Code || '      <td class="shadowOffsetCellRight"></td>';
    v_HTML_Code := v_HTML_Code || '   </tr>';
    v_HTML_Code := v_HTML_Code || '  <tr>';
    v_HTML_Code := v_HTML_Code || '     <td class="shadowRight">;</td>';
    v_HTML_Code := v_HTML_Code || '  </tr>';
    v_HTML_Code := v_HTML_Code || '  <tr>';
    v_HTML_Code := v_HTML_Code || '     <td class="shadowOffsetCellBottom"></td>';
    v_HTML_Code := v_HTML_Code || '     <td class="shadowBottom">;</td>';
    v_HTML_Code := v_HTML_Code || '     <td class="shadowCorner"></td>';
    v_HTML_Code := v_HTML_Code || '  </tr>';
    v_HTML_Code := v_HTML_Code || '</table>';

    return v_HTML_Code;
  end;

end ODS$GUI_PKG;

Теперь необходимо внести необходимые правки в APEX
Во первых вносим изменения в template страниц, который стоит по умолчанию для приложения. Во всех наших приложениях используется template с названием One Level Tabs.
В раздел Header, этого template добавляем ссылки на javascript и таблицы стилей,в результате раздел должен выглядеть так:


#TITLE#

<!--[if IE]><![endif]-->

#HEAD#

#FORM_OPEN#

В разделе Body изменяемого template, тоже вносим изменения, в конце добавляем элемент div с названием MainBarProductMenu, HTML код раздела, после редактирования, должен выглядит так:

<div id="t20PageHeader">
<table border="0" cellpadding="0" cellspacing="0" summary="">
<tr>
<td valign="top">#LOGO#<br />#REGION_POSITION_06#</td>
<td valign="top" width="100%">#REGION_POSITION_07#<br /></td>
<td valign="top">#NAVIGATION_BAR#<br />#REGION_POSITION_08#</td>
</tr>
</table>
<div id="t20Tabs" class="tablight">#TAB_CELLS#</div>
</div>
<div id="t20BreadCrumbsLeft">#REGION_POSITION_01#</div>
<table border="0" cellpadding="0" cellspacing="0" summary="" id="t20PageBody" width="100%">
<td width="100%" valign="top">
<div id="t20Messages">#GLOBAL_NOTIFICATION##SUCCESS_MESSAGE##NOTIFICATION_MESSAGE#</div>
<div id="t20ContentMiddle">#BOX_BODY##REGION_POSITION_02##REGION_POSITION_04#</div>
</td>
<td valign="top" width="200">#REGION_POSITION_03#<br /></td>
</tr>
</table>

<div align="left" class="NQWMenu" id="MainBarProductMenu" style="position:absolute;top:66px;left:777px;visibility:hiden;"></div>

Если вы посмотрите на HTML код элемента MainBarProductMenu то вы увидите что у меню нет строк, за формирование этих строк отвечаем PL/SQL функция Get_Main_Bar_Product_Menu_F которую мы создали ранее.
Чтобы подключить эту функция нам нужно создать процесс на уровне приложения который будет вызывать функцию Get_Main_Bar_Product_Menu_F. Для этого в редакторе приложения идем в раздел Shared Components > Application Processes и создаем On Demand процесс с названием Get_Main_Bar_Product_Menu_HTML и таким кодом:

declare
  v_result varchar2(10000);
begin

  v_result := ODS$GUI_PKG.Get_Main_Bar_Product_Menu_F;

  htp.p(v_result);  

end;

Ну и последний шаг создаем новый Navigation Bar Entrie,
1.    Target Type указываем URL
2.    URL Target пишем такой Javascript

javascript:void(null);" onclick="injectMenu();popupMenu(event,'MainBarProductMenu');return false;

Этот Javascript сначала вызывает функцию injectMenu которая добавляет строки в меню используя для этого On Demand процесс Get_Main_Bar_Product_Menu_HTML и дальше идет вызов второй функция popupMenu которая отображает меню.

После всех этих шагов получаем симпатичный интерфейс который достаточно удобен при навигации из одного приложения в другое.

 

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s