Skip to Main Content
Ted Struik - Oracle
Search For
Home
Home
Ted Struik - Oracle
Search
Site Map
Statistics
Page Errors
Apex
Apex
General
Autocomplete
Conditions
Errors
Items used in PL/SQL
Validations
Dynamic Actions
Logs
Version
App-wide Items
Error Handling
Apex Views
Apex Upgrade 4.2 to 5.1
Apex Upgrade 20.2 to 23.1
Database Dependencies
Show Source Code
URLs
Authorization
Modal Dialogs
Apex Office Print (AOP)
Apex-Sert
Warn on Unsaved Changes
Form Regions
Reports
Checkboxes
Download
Errors
Nowrap Columns
Substitution Strings
Use IR results in pl/sql
Clickable Row
Row Highlight
Translate Filters etc.
Bar Charts
Column Usage
Reset Pagination
Hide IR Actions menu items
Get Classic Report query
Interactive Grid
ORA-20987
ERR-1002
Copying Text
IG Info
Multiple Row Select
Read Only Options
Search
Sort and Search
Images & Fonts
Standard Icons & Fonts
WebDav
Font Awesome
Icons/image popup LOV
Lists
Hierarchy
LOVs
Definition Bug
Set 1-item LOV to Disabled
With Clause Errors
Modal LOV Plugin
HTML / CSS / JavaScript
Vertical Align
Legend CSS
Geolocation
Apex.confirm
Pie Charts
Codemirror
Theme Roller
Catching Key Strokes
Browser Cache
Locale
RequireJS
Collapsible Regions
Find JavaScript
Import / Export
Dynamic Translations
Translated Pages
APEXExport (java)
apex_export (pl/sql)
Component Settings
Charts
Translate Charts
[Reports] Bar Charts
Shuttles
Shuttle Sorting
Disable Shuttle Items
Menus
Accordion-Like
Scroll bug
Authorization
Session State
About Session State
Rollback & Commit
Performance of v()
Apex Clone Session
Request
Session State in Views
Collections
ORA-20101 & ORA-20104
ORA-00001
Max Row Count
(PL)SQL
(PL)SQL
External Tables
SQL Plus
Conditions
Long
ORDImage
Date & Timestamp
CGI environment
Sys_context
Rounding percentages
Apex_string.split in SQL
Dbms_metadata
Instr
Regular Expressions
Rollback to Savepoint
Use table aliases
(Pipelined) Bulk Collect
JSON
Source Code Search (PL/SQL)
Source Code Search (SQL)
Format Models
Pipelined Table Functions
Hint no_unnest
Listagg
DBA
DBA
Backup & Restore
Users
Export & Import
DBMS Jobs
Tablespaces
Table Size
Flush cache
Access Control List (ACL)
Locks
Java
Constraints
Object Dependencies
Package Dependencies 1
Package Dependencies 2
Grants
SQL History
Startup Errors
ORDS
Miscellaneous
Miscellaneous
Holidays
E-mail
NLExtract
Windows
VPN
VMware
Links
Google
Visualization Orgchart
Hide Search Results
Reverse Proxy
To-do List
Cytoscape
Graphics
Upscaling
Amazon Prices
Domoticz
DDoS
Hobbies
Hobbies
Motorcycles
'95 Kawasaki ZZR 600
'94 Kawasaki ZZR 1100
'91 Honda CBR 600 F2
'95 Kawasaki ZZR 1100
'99 Honda CBR 1100 XX
'00 Honda CBR 1100 XX
'02 Kawasaki ZX-12R (NL)
'05 Ducati 999 (NL)
'08 Honda Fireblade
'07 Suzuki Bandit 1250A
'18 Suzuki GSX-S 1000 F
MotoGP
Garfield
Lyrics
Skydive
Woodworking
Pantorouter
16 inch Bandsaw
Introduction
Frame
Wheels
Wheel mounts
Blade guides
Trunions and table
Enclosure
Alignment and more
Box Joint Jig
Foldable Sawhorses
Strip Sander XL
Photography
Sony RX10 IV
Yes Minister
WinAmp
Info
An implementation of the Cytoscape.js javascript library.
The mountain of pl/sql code below tries to create a visualization of all the (menu/page/button/etc.) links in this Apex application. Not complete or perfect but it should give you a nice idea about what is possible with this library in Apex.
More info on the library:
http://js.cytoscape.org//
.
You will need to include the cytoscape library; either host it yourself or use the CDN link provided here:
https://cdnjs.com/libraries/cytoscape
.
Settings
Page
1002 - Apex - Reports - Checkboxes
1003 - Apex - Images & Fonts - Standard Icons & Fonts
1004 - Apex - Reports - Nowrap Columns
1005 - Apex - Images & Fonts - WebDav
1006 - Apex - Reports - Errors
1007 - Apex - Reports - Download
1008 - Apex - General - Conditions
1009 - Apex - Reports - Substitution Strings
1010 - Apex - Images & Fonts - Font Awesome
1011 - Apex - General - Autocomplete
1012 - Apex - General - Errors
1013 - Apex - General - Items used in PL/SQL
1014 - (PL)SQL - External Tables
1015 - DBA - Tablespaces
1016 - DBA - Backup & Restore
1017 - DBA - Table Size
1018 - Apex - Reports - Use IR results in pl/sql
1019 - Apex - General - Validations
1020 - DBA - Users
1021 - Apex - Lists - Hierarchy
1022 - Apex - LOVs - Definition Bug
1023 - (PL)SQL - SQL Plus
1024 - (PL)SQL - Conditions
1025 - Apex - LOVs - Set 1-item LOV to Disabled
1026 - (PL)SQL - Long
1027 - Miscellaneous - Google - Visualization Orgchart
1028 - (PL)SQL - ORDImage
1029 - Apex - Session State - About Session State
1030 - Apex - General - Dynamic Actions
1031 - Apex - General - Logs
1032 - Apex - Reports - Clickable Row
1033 - Miscellaneous - Holidays
1034 - Miscellaneous - E-mail
1035 - (PL)SQL - Date & Timestamp
1036 - Hobbies - Motorcycles - '95 Kawasaki ZZR 600
1037 - Hobbies - Motorcycles - '94 Kawasaki ZZR 1100
1038 - Hobbies - Motorcycles - '91 Honda CBR 600 F2
1039 - Hobbies - Motorcycles - '95 Kawasaki ZZR 1100
1040 - Hobbies - Motorcycles - '99 Honda CBR 1100 XX
1041 - Hobbies - Motorcycles - '00 Honda CBR 1100 XX
1042 - Hobbies - Motorcycles - '02 Kawasaki ZX-12R (NL)
1043 - Hobbies - Motorcycles - '05 Ducati 999 (NL)
1044 - Hobbies - Garfield
1045 - DBA - Export & Import
1046 - DBA - DBMS Jobs
1047 - Apex - Reports - Row Highlight
1048 - Apex - Reports - Translate Filters etc.
1049 - Miscellaneous - NLExtract
1050 - (PL)SQL - CGI environment
1051 - (PL)SQL - Sys_context
1052 - Hobbies - Lyrics
1053 - Apex - HTML / CSS / JavaScript - Vertical Align
1055 - DBA - Flush cache
1056 - Apex - Import / Export - Translated Pages
1057 - Apex - HTML / CSS / JavaScript - Legend CSS
1058 - DBA - Access Control List (ACL)
1059 - Apex - Import / Export - Dynamic Translations
1060 - Apex - HTML / CSS / JavaScript - Geolocation
1061 - (PL)SQL - Rounding percentages
1062 - Hobbies - Motorcycles - '08 Honda Fireblade
1063 - Apex - Charts - Translate Charts
1064 - Miscellaneous - VPN
1065 - Apex - Session State - Rollback & Commit
1066 - Apex - HTML / CSS / JavaScript - Apex.confirm
1067 - DBA - Locks
1068 - Apex - HTML / CSS / JavaScript - Pie Charts
1069 - Apex - Reports - Bar Charts
1070 - Apex - General - Version
1071 - Apex - General - App-wide Items
1073 - Miscellaneous - VMware
1074 - DBA - Java
1075 - (PL)SQL - Apex_string.split in SQL
1076 - (PL)SQL - Use table aliases
1077 - DBA - Constraints
1078 - Miscellaneous - Links
1079 - DBA - Package Dependencies 1
1080 - (PL)SQL - Dbms_metadata
1081 - DBA - Package Dependencies 2
1082 - (PL)SQL - Instr
1083 - Apex - Import / Export - APEXExport (java)
1084 - Miscellaneous - Windows
1085 - DBA - Grants
1086 - Apex - HTML / CSS / JavaScript - Codemirror
1087 - Apex - Shuttles - Shuttle Sorting
1088 - Apex - Shuttles - Disable Shuttle Items
1089 - DBA - SQL History
1090 - Apex - General - Error Handling
1091 - (PL)SQL - Regular Expressions
1092 - (PL)SQL - Rollback to Savepoint
1093 - Hobbies - Skydive
1094 - Apex - Reports - Column Usage
1095 - Miscellaneous - Reverse Proxy
1096 - Apex - Menus - Accordion-Like
1097 - Miscellaneous - To-do List
1098 - Apex - General - Apex Views
1099 - Miscellaneous - Cytoscape
1100 - Hobbies - Motorcycles - MotoGP
1101 - Apex - LOVs - With Clause Errors
1102 - Apex - Reports - Reset Pagination
1103 - Apex - General - Apex Upgrade 4.2 to 5.1
1104 - (PL)SQL - (Pipelined) Bulk Collect
1105 - Apex - HTML / CSS / JavaScript - Theme Roller
1106 - Apex - Session State - Performance of v()
1107 - Apex - General - Database Dependencies
1108 - Apex - Collections - ORA-20101 & ORA-20104
1109 - DBA - Object Dependencies
1110 - Apex - Collections - ORA-00001
1111 - Apex - Menus - Scroll bug
1112 - Miscellaneous - Graphics
1113 - Statistics
1114 - Hobbies - Woodworking - Pantorouter
1115 - Hobbies - Woodworking - 16 inch Bandsaw - Introduction
1116 - Hobbies - Woodworking - 16 inch Bandsaw - Frame
1117 - Hobbies - Woodworking - 16 inch Bandsaw - Wheels
1118 - Hobbies - Motorcycles - '07 Suzuki Bandit 1250A
1119 - DBA - Startup Errors
1120 - Apex - General - Show Source Code
1121 - Hobbies - Woodworking - 16 inch Bandsaw - Wheel mounts
1122 - DBA - ORDS
1123 - Hobbies - Woodworking - 16 inch Bandsaw - Blade guides
1124 - Hobbies - Woodworking - 16 inch Bandsaw - Alignment and more
1125 - Hobbies - Woodworking - 16 inch Bandsaw - Trunions and table
1126 - Hobbies - Woodworking - 16 inch Bandsaw - Enclosure
1127 - (PL)SQL - JSON
1128 - Hobbies - Woodworking - Box Joint Jig
1129 - Apex - General - URLs
1130 - Apex - Import / Export - Component Settings
1131 - Apex - Interactive Grid - ORA-20987
1132 - Apex - General - Authorization
1133 - Apex - General - Modal Dialogs
1134 - Apex - LOVs - Modal LOV Plugin
1135 - (PL)SQL - Source Code Search (PL/SQL)
1136 - Apex - Session State - Apex Clone Session
1137 - Apex - HTML / CSS / JavaScript - Catching Key Strokes
1138 - Apex - Interactive Grid - IG Info
1139 - (PL)SQL - Format Models
1140 - Apex - Interactive Grid - ERR-1002
1141 - (PL)SQL - Pipelined Table Functions
1142 - Apex - Images & Fonts - Icons/image popup LOV
1144 - Hobbies - Woodworking - Foldable Sawhorses
1145 - Miscellaneous - Google - Hide Search Results
1146 - Apex - HTML / CSS / JavaScript - Browser Cache
1147 - Miscellaneous - Amazon Prices
1148 - Apex - HTML / CSS / JavaScript - Locale
1149 - (PL)SQL - Source Code Search (SQL)
1151 - Hobbies - Motorcycles - '18 Suzuki GSX-S 1000 F
1152 - Hobbies - Woodworking - Strip Sander XL
1153 - Apex - HTML / CSS / JavaScript - RequireJS
1154 - Hobbies - Photography - Sony RX10 IV
1156 - Apex - General - Apex Office Print (AOP)
1157 - (PL)SQL - Hint no_unnest
1158 - Miscellaneous - Domoticz
1159 - PL(SQL) - Listagg
1161 - Apex - Interactive Grid - Copying Text
1162 - Miscellaneous - DDoS
1167 - Apex - Reports - Hide IR Actions menu items
1168 - Apex - Session State - Request
1169 - Apex - Collections - Max Row Count
1170 - Apex - General - Apex-Sert
1171 - Apex - Menus - Authorization
1172 - Apex - HTML / CSS / JavaScript - Collapsible Regions
1173 - Apex - Import / Export - apex_export (pl/sql)
1174 - Apex - Reports - Get Classic Report query
1175 - Apex - General - Apex Upgrade 20.2 to 23.1
1176 - Apex - HTML / CSS / JavaScript - Find JavaScript
1177 - Apex - Interactive Grid - Multiple Row Select
1178 - Apex - Interactive Grid - Read Only Options
1179 - Apex - General - Warn on Unsaved Changes
1181 - Hobbies - Yes Minister
1182 - Apex - General - Form Regions
1183 - Apex - Interactive Grid - Search
1184 - Apex - Session State - Session State in Views
1186 - Apex - Interactive Grid - Sort and Search
1187 - Hobbies - WinAmp
Cytoscape
Code
Page
Identification
Page ID
1099
Name
Miscellaneous - Cytoscape
Region
Identification
Sequence
30
Title
Cytoscape
Type
PL/SQL
Source
Source Type
PLSQL_PROCEDURE
Region Source
declare v_clob clob; begin dbms_lob.createtemporary(v_clob, true, dbms_lob.call); v_clob := ted_p1099.menu_structure ( p_highlight_page_id => :P1099_PAGE_ID ) ; ted_p1099.htp_prn( p_clob => v_clob ); end;
Attributes
Static ID
the_div_cytoscape
Region Attributes
style="overflow: scroll; height:800px; width:1200px;"
Package
Package
Name
TED_P1099
Source
package ted_p1099 is type t_number_table is table of number ; type t_varchar_table is table of varchar2(4000) ; function v_nodes_table return t_varchar_table pipelined ; function apex_url ( p_page_id in apex_application_pages.page_id%type ) return varchar2 ; procedure htp_prn ( p_clob in out nocopy clob ) ; function menu_structure ( p_highlight_page_id in number := null , p_app_id in number := v('APP_ID') , p_menu_list_name in varchar2 := 'Navigation Menu' , p_width in number := 1200 , p_height in number := 800 ) return clob ; end ted_p1099;
Package Body
Package Body
Name
TED_P1099
Source
package body ted_p1099 is v_nodes ted_cytoscape.t_cytoscape_node_table := ted_cytoscape.t_cytoscape_node_table(); v_edges ted_cytoscape.t_cytoscape_edge_table := ted_cytoscape.t_cytoscape_edge_table(); v_nodes_rows_n pls_integer := 0; v_edges_rows_n pls_integer := 0; function v_nodes_table return t_varchar_table pipelined is begin -- Example of call: select * from table( ted_p1099.v_nodes_table ) if v_nodes.count > 0 then for i in v_nodes.first .. v_nodes.last loop pipe row(v_nodes(i).id); end loop; end if; return; end v_nodes_table; function apex_url ( p_page_id in apex_application_pages.page_id%type ) return varchar2 is v_result varchar2(1000); begin if nvl(p_page_id, '1') = '1' then return null; end if; -- Apex URL syntax: f?p=App:Page:Session:Request:Debug:ClearCache:itemNames:itemValues:PrinterFriendly v_result := -- App 'f?p=' || v('APP_ID') -- Page || ':' || v('APP_PAGE_ID') -- Session || ':' || v('APP_SESSION') -- Request || ':' -- Debug || ':' -- ClearCache || ':' -- itemNames || ':P1099_PAGE_ID' -- itemValues || ':' || trim(p_page_id) -- PrinterFriendly || ':' ; return v_result; end apex_url; procedure htp_prn ( p_clob in out nocopy clob ) is v_text varchar2(32000); v_clob clob := p_clob; begin while length(v_clob) > 0 loop begin if length(v_clob) > 16000 then v_text := substr(v_clob, 1, 16000); htp.prn(v_text); v_clob := substr(v_clob, length(v_text)+1); else v_text := v_clob; htp.prn(v_text); v_clob := ''; v_text := ''; end if; end; end loop; end; function menu_structure ( p_highlight_page_id in number := null , p_app_id in number := v('APP_ID') , p_menu_list_name in varchar2 := 'Navigation Menu' , p_width in number := 1200 , p_height in number := 800 ) return clob is v_result clob; -- menu hierarchy cursor c1 is select b.r , b.connect_level , 'C' || nvl(b.list_entry_parent_id, 'Menu') as edge_source , nvl(b.parent_entry_text, 'Menu') as edge_source_content , apex_url(p_page_id => b.list_entry_parent_id) as edge_source_href , ( case when nvl(b.list_entry_parent_id, '1') <> '1' then b.list_entry_parent_id else null end ) as edge_source_page_id , 'C' || ( case when nvl(b.list_page_id, '1') = '1' then b.list_entry_id else b.list_page_id end ) as edge_target , ( case when nvl(b.list_page_id, '1') = '1' then b.entry_text else b.list_page_id end ) as edge_target_content , apex_url(p_page_id => b.list_page_id) as edge_target_href , ( case when nvl(b.list_page_id, '1') <> '1' then b.list_page_id else null end ) as edge_target_page_id from ( select rownum as r , level as connect_level , a.display_sequence , trim(a.list_entry_parent_id) as list_entry_parent_id , a.parent_entry_text , trim(a.list_entry_id) as list_entry_id , a.entry_text , regexp_substr(a.entry_target, '[^:]+', 1, 2) as list_page_id from apex_application_list_entries a where a.application_id = p_app_id and a.list_name = p_menu_list_name start with a.list_entry_parent_id is null connect by prior a.list_entry_id = a.list_entry_parent_id order siblings by a.display_sequence ) b order by r ; -- links between pages cursor c2 is select 'C' || trim(b.page_id) as edge_source , trim(b.page_id) as edge_source_content , apex_url(p_page_id => b.page_id) as edge_source_href , ( case when nvl(trim(b.page_id), '1') <> '1' then trim(b.page_id) else null end ) as edge_source_page_id , 'C' || trim(b.link_to_page_id) as edge_target , trim(b.link_to_page_id) as edge_target_content , apex_url(p_page_id => b.link_to_page_id) as edge_target_href , ( case when nvl(trim(b.link_to_page_id), '1') <> '1' then trim(b.link_to_page_id) else null end ) as edge_target_page_id , count(*) over (partition by b.page_id order by b.link_to_page_id rows between unbounded preceding and current row) as node_id_n , vt.r as v_nodes_table_r from ( select to_number(x.application_id) as application_id -- no idea why a to_number is needed here by the way - if you don't use it, ORA-01722: invalid number will occur later on in queries... , to_number(x.page_id) as page_id -- same , x.link_type , x.link_identifier , ( case x.link_to_application_id when '&'||'APP_ID.' then x.application_id when '&'||'FLOW_ID.' then x.application_id else to_number(x.link_to_application_id) end ) as link_to_application_id , to_number(x.link_to_page_id default null on conversion error) as link_to_page_id -- default needed for e.g. &APP_PAGE_ID. from ( select b.application_id , b.page_id , 'button' as link_type , 'button: '||b.button_name as link_identifier , substr(b.redirect_url_clean, instr(b.redirect_url_clean,'=',1,1)+1, instr(b.redirect_url_clean,':',1,1)-instr(b.redirect_url_clean,'=',1,1)-1) as link_to_application_id , substr(b.redirect_url_clean, instr(b.redirect_url_clean,':',1,1)+1, instr(b.redirect_url_clean,':',1,2)-instr(b.redirect_url_clean,':',1,1)-1) as link_to_page_id from ( select a.* , replace(a.redirect_url,'javascript:popupURL(''','') as redirect_url_clean from apex_application_page_buttons a ) b where b.redirect_url_clean like 'f?p=%' union all select h.application_id , h.page_id , 'page branch' as link_type , 'branch sequence: '||trim(h.process_sequence) as link_identifier , substr(h.branch_action, instr(h.branch_action,'=',1,1)+1, instr(h.branch_action,':',1,1)-instr(h.branch_action,'=',1,1)-1) as link_to_application_id , substr(h.branch_action, instr(h.branch_action,':',1,1)+1, instr(h.branch_action,':',1,2)-instr(h.branch_action,':',1,1)-1) as link_to_page_id from apex_application_page_branches h where h.branch_action like 'f?p=%' union all select e.application_id , to_number(null) as page_id , 'list entry' as link_type , 'list: '||e2.list_name as link_identifier , substr(e.entry_target, instr(e.entry_target,'=',1,1)+1, instr(e.entry_target,':',1,1)-instr(e.entry_target,'=',1,1)-1) as link_to_application_id , substr(e.entry_target, instr(e.entry_target,':',1,1)+1, instr(e.entry_target,':',1,2)-instr(e.entry_target,':',1,1)-1) as link_to_page_id from apex_application_list_entries e , apex_application_lists e2 where e.list_id = e2.list_id and e.entry_target like 'f?p=%' union all select c.application_id , c.page_id , 'report column' as link_type , 'region/column: '||c.region_name||'/'||c.column_alias as link_identifier , substr(c.column_link_url, instr(c.column_link_url,'=',1,1)+1, instr(c.column_link_url,':',1,1)-instr(c.column_link_url,'=',1,1)-1) as link_to_application_id , substr(c.column_link_url, instr(c.column_link_url,':',1,1)+1, instr(c.column_link_url,':',1,2)-instr(c.column_link_url,':',1,1)-1) as link_to_page_id from apex_application_page_rpt_cols c where c.column_link_url like 'f?p=%' union all select c2.application_id , c2.page_id , 'report column (IR)' as link_type , 'region/column: '||r2.region_name||'/'||c2.column_alias as link_identifier , substr(c2.column_link, instr(c2.column_link,'=',1,1)+1, instr(c2.column_link,':',1,1)-instr(c2.column_link,'=',1,1)-1) as link_to_application_id , substr(c2.column_link, instr(c2.column_link,':',1,1)+1, instr(c2.column_link,':',1,2)-instr(c2.column_link,':',1,1)-1) as link_to_page_id from apex_application_page_ir_col c2 , apex_application_page_regions r2 where c2.region_id = r2.region_id and c2.column_link like 'f?p=%' union all select t.application_id , to_number(null) as page_id , 'tab' as link_type , 'tab: '||t.tab_label as link_identifier , to_char(t.application_id) as link_to_application_id , to_char(t.tab_page) as link_to_page_id from apex_application_tabs t ) x , apex_application_pages ap where x.application_id = ap.application_id and x.link_to_page_id = trim(ap.page_id) -- make sure we found a real page, and not something like e.g. '&PAGE_ID' and nvl(x.page_id,-1) <> nvl(ap.page_id,-1) -- do not list pages that redirect to themselves, not much point in that... and nvl(x.page_id,-1) <= 1999 -- do not include "test" pages and nvl(x.page_id,-1) not in (101) -- do not include "login" page and ap.application_id = p_app_id ) b , apex_application_pages ap_this , apex_application_pages ap_link , ( select rownum as r, column_value from table( ted_p1099.v_nodes_table ) ) vt where b.application_id = ap_this.application_id and b.page_id = ap_this.page_id and b.link_to_application_id = ap_link.application_id (+) and b.link_to_page_id = ap_link.page_id (+) and 'C' || trim(b.page_id) = vt.column_value (+) and b.link_to_page_id is not null order by vt.r , b.page_id , b.link_to_page_id ; -- lists cursor c3 is select 'C' || trim(b.list_page_id) as edge_target , trim(b.list_page_id) as edge_target_content , apex_url(p_page_id => b.list_page_id) as edge_target_href , trim(b.list_page_id) as edge_target_page_id , 'C' || trim(b.parent_list_page_id) as edge_source , trim(b.parent_list_page_id) as edge_source_content , apex_url(p_page_id => b.parent_list_page_id) as edge_source_href , trim(b.parent_list_page_id) as edge_source_page_id from ( select a2.* , to_number( regexp_substr(a2.parent_entry_target, '[^:]+', 1, 2) ) as parent_list_page_id from ( select a.display_sequence , lag(trim(a.list_entry_id)) over (order by a.display_sequence) as list_entry_parent_id , lag(trim(a.entry_text)) over (order by a.display_sequence) as parent_entry_text , trim(a.list_entry_id) as list_entry_id , a.entry_text , to_number( regexp_substr(a.entry_target, '[^:]+', 1, 2) ) as list_page_id , lag(trim(a.entry_target)) over (order by a.display_sequence) as parent_entry_target from apex_application_list_entries a where a.application_id = p_app_id and a.list_name <> p_menu_list_name -- don't include the menu again ) a2 where a2.list_entry_parent_id is not null ) b order by b.display_sequence ; -- all pages cursor c99 is select 'C' || trim(b.page_id) as edge_source , trim(b.page_id) as edge_source_content , apex_url(p_page_id => b.page_id) as edge_source_href , trim(b.page_id) as edge_source_page_id from apex_application_pages b where b.application_id = p_app_id and b.page_id >= 1000 -- do not include master & menu pages and b.page_id <= 1999 -- do not include "test" pages and b.page_id not in (101) -- do not include "login" page order by b.page_id ; procedure add_node ( p_node_id in varchar2 , p_node_content in varchar2 , p_node_href in varchar2 , p_connect_level in number , p_page_id in number ) is v_found boolean := false; v_connect_sequence pls_integer; v_width pls_integer := 30; v_height pls_integer := 30; v_node_highlight boolean := false; v_node_highlight_color varchar2(10) := null; v_node_highlight_width number := 0; v_authorization_scheme varchar2(1000); begin if v_nodes.count > 0 then for i in v_nodes.first .. v_nodes.last loop if v_nodes(i).id = p_node_id then v_found := true; exit; end if; end loop; end if; -- add p_node_id if needed if v_found = false then if p_highlight_page_id = p_page_id then v_node_highlight := true; v_node_highlight_color := '#00CCFF'; v_node_highlight_width := nvl(round(v_width/5), 5); end if; select max(authorization_scheme) into v_authorization_scheme from apex_application_pages where application_id = p_app_id and page_id = p_page_id ; v_nodes_rows_n := v_nodes_rows_n + 1; v_nodes.extend; v_nodes(v_nodes_rows_n).id := p_node_id; v_nodes(v_nodes_rows_n).href := p_node_href; v_nodes(v_nodes_rows_n).connect_level := p_connect_level; -- v_connect_sequence is determined by the sort order of the cursor -- (for cursor c2 this means it should be determined by referencing the sequence of c1) v_connect_sequence := 0; for j in v_nodes.first .. v_nodes.last loop if v_nodes(j).connect_level = p_connect_level then v_connect_sequence := v_connect_sequence + 1; end if; end loop; v_nodes(v_nodes_rows_n).connect_sequence := v_connect_sequence; -- (ANY) Labels: v_nodes(v_nodes_rows_n).color := null; v_nodes(v_nodes_rows_n).content := p_node_content; v_nodes(v_nodes_rows_n).font_family := null; v_nodes(v_nodes_rows_n).font_size := null; v_nodes(v_nodes_rows_n).font_style := null; v_nodes(v_nodes_rows_n).font_weight := null; v_nodes(v_nodes_rows_n).text_opacity := null; v_nodes(v_nodes_rows_n).text_outline_color := '#FFFFFF'; v_nodes(v_nodes_rows_n).text_outline_opacity := null; v_nodes(v_nodes_rows_n).text_outline_width := 1; v_nodes(v_nodes_rows_n).min_zoomed_font_size := null; -- (ANY) Size & visibility: v_nodes(v_nodes_rows_n).opacity := null; v_nodes(v_nodes_rows_n).visibility := null; v_nodes(v_nodes_rows_n).width := v_width + v_node_highlight_width; v_nodes(v_nodes_rows_n).z_index := null; -- (ANY) Overlays: v_nodes(v_nodes_rows_n).overlay_color := null; v_nodes(v_nodes_rows_n).overlay_padding := null; v_nodes(v_nodes_rows_n).overlay_opacity := null; -- (ANY) Transition animations: v_nodes(v_nodes_rows_n).transition_property := null; v_nodes(v_nodes_rows_n).transition_duration := null; v_nodes(v_nodes_rows_n).transition_delay := null; -- (NODES) Labels: v_nodes(v_nodes_rows_n).text_halign := null; v_nodes(v_nodes_rows_n).text_valign := 'center'; -- (NODES) Body: if p_node_href is null then v_nodes(v_nodes_rows_n).background_color := '#888888'; -- no link else v_nodes(v_nodes_rows_n).background_color := '#88DD88'; -- link end if; v_nodes(v_nodes_rows_n).background_blacken := null; v_nodes(v_nodes_rows_n).background_opacity := null; if v_node_highlight then v_nodes(v_nodes_rows_n).border_color := v_node_highlight_color; else v_nodes(v_nodes_rows_n).border_color := '#000000'; end if; v_nodes(v_nodes_rows_n).border_opacity := null; if v_node_highlight then v_nodes(v_nodes_rows_n).border_width := v_node_highlight_width; else v_nodes(v_nodes_rows_n).border_width := 0; end if; v_nodes(v_nodes_rows_n).height := v_height + v_node_highlight_width; v_nodes(v_nodes_rows_n).shape := null; -- (NODES) Background image: v_nodes(v_nodes_rows_n).background_image := null; v_nodes(v_nodes_rows_n).background_fit := null; v_nodes(v_nodes_rows_n).background_repeat := null; v_nodes(v_nodes_rows_n).background_position_x := null; v_nodes(v_nodes_rows_n).background_position_y := null; v_nodes(v_nodes_rows_n).background_clip := null; -- (PIE) Pie chart background: v_nodes(v_nodes_rows_n).pie_size := null; v_nodes(v_nodes_rows_n).pie_i_background_color := null; v_nodes(v_nodes_rows_n).pie_i_background_size := null; end if; end; procedure position_nodes is v_row_nodes_n number; v_connect_level_max number; v_connect_level_prev number := -999; v_pyramid_factor number := .05; begin if v_nodes.count > 0 then -- determine v_connect_level_max v_connect_level_max := 0; for j in v_nodes.first .. v_nodes.last loop if v_nodes(j).connect_level > v_connect_level_max then v_connect_level_max := v_nodes(j).connect_level; end if; end loop; for i in v_nodes.first .. v_nodes.last loop if v_nodes(i).connect_level <> v_connect_level_prev then -- start new "row" v_connect_level_prev := v_nodes(i).connect_level; -- determine number of items in this "row" v_row_nodes_n := 0; for j in v_nodes.first .. v_nodes.last loop if v_nodes(j).connect_level = v_nodes(i).connect_level then v_row_nodes_n := v_row_nodes_n + 1; end if; end loop; end if; -- calculate positions X if v_row_nodes_n = 1 then -- always center a single node v_nodes(i).position_x := 0; else -- distribute the nodes on the row v_nodes(i).position_x := round ( ( ( v_nodes(i).connect_sequence - 1 ) * ( p_width / (v_row_nodes_n-1) ) -- distribute evenly on the row - ( p_width / 2 ) -- start left of 0 ) * ( 1 - (v_connect_level_max - v_nodes(i).connect_level) * v_pyramid_factor ) -- create a (bit of a) pyramid shape ) ; end if; -- calculate positions Y v_nodes(i).position_y := round ( ( v_nodes(i).connect_level - 1 ) * ( p_height / (v_connect_level_max+1) ) -- distribute evenly -- + cos(v_nodes(i).position_x / p_width * 3.14) * (p_height / 10) * v_nodes(i).connect_level -- slight circle shape ) ; --v_nodes(i).content := v_nodes(i).connect_level || '- ' || v_nodes(i).position_y; -- #### for debugging end loop; end if; end; function edge_exists ( v_source in varchar2 , v_target in varchar2 ) return boolean is v_result boolean := false; begin if v_edges.count > 0 then for i in v_edges.first .. v_edges.last loop if v_edges(i).source = v_source and v_edges(i).target = v_target then v_result := true; exit; end if; end loop; end if; return v_result; end edge_exists; procedure add_edge is begin v_edges_rows_n := v_edges_rows_n + 1; v_edges.extend; -- (ANY) Labels: v_edges(v_edges_rows_n).color := null; v_edges(v_edges_rows_n).content := null; v_edges(v_edges_rows_n).font_family := null; v_edges(v_edges_rows_n).font_size := null; v_edges(v_edges_rows_n).font_style := null; v_edges(v_edges_rows_n).font_weight := null; v_edges(v_edges_rows_n).text_opacity := null; v_edges(v_edges_rows_n).text_outline_color := null; v_edges(v_edges_rows_n).text_outline_opacity := null; v_edges(v_edges_rows_n).text_outline_width := null; v_edges(v_edges_rows_n).min_zoomed_font_size := null; -- (ANY) Size & visibility: v_edges(v_edges_rows_n).opacity := null; v_edges(v_edges_rows_n).visibility := null; v_edges(v_edges_rows_n).width := 2; v_edges(v_edges_rows_n).z_index := null; -- (ANY) Overlays (e.g. used in :active sta v_edges(v_edges_rows_n).overlay_color := null; v_edges(v_edges_rows_n).overlay_padding := null; v_edges(v_edges_rows_n).overlay_opacity := null; -- (ANY) Transition animations: v_edges(v_edges_rows_n).transition_property := null; v_edges(v_edges_rows_n).transition_duration := null; v_edges(v_edges_rows_n).transition_delay := null; -- (EDGE) Edge properties v_edges(v_edges_rows_n).curve_style := null; v_edges(v_edges_rows_n).control_point_step_size := null; v_edges(v_edges_rows_n).control_point_distance := null; v_edges(v_edges_rows_n).control_point_weight := null; v_edges(v_edges_rows_n).line_color := null; v_edges(v_edges_rows_n).line_style := null; v_edges(v_edges_rows_n).source_arrow_color := null; v_edges(v_edges_rows_n).source_arrow_shape := null; v_edges(v_edges_rows_n).source_arrow_fill := null; v_edges(v_edges_rows_n).target_arrow_color := null; v_edges(v_edges_rows_n).target_arrow_shape := 'triangle'; v_edges(v_edges_rows_n).target_arrow_fill := null; end; begin dbms_lob.createtemporary(v_result , true, dbms_lob.call); -- c1 (menu, has to be first to get the correct order) for c1_rec in c1 loop -- add edge if edge_exists ( v_source => c1_rec.edge_source , v_target => c1_rec.edge_target ) = false then add_edge; v_edges(v_edges_rows_n).source := c1_rec.edge_source; v_edges(v_edges_rows_n).target := c1_rec.edge_target; dbms_output.put_line('c1_rec.edge_source=' || c1_rec.edge_source); dbms_output.put_line('c1_rec.edge_target=' || c1_rec.edge_target); end if; -- if either the source or the target are not yet included in v_nodes, include it add_node ( p_node_id => c1_rec.edge_source , p_node_content => c1_rec.edge_source_content , p_node_href => c1_rec.edge_source_href , p_connect_level => c1_rec.connect_level , p_page_id => c1_rec.edge_source_page_id ) ; add_node ( p_node_id => c1_rec.edge_target , p_node_content => c1_rec.edge_target_content , p_node_href => c1_rec.edge_target_href , p_connect_level => c1_rec.connect_level + 1 , p_page_id => c1_rec.edge_target_page_id ) ; end loop; -- c2 (links) for k in 1 .. 2 loop declare v_connect_level_max pls_integer := 0; v_connect_sequence number; begin -- determine v_connect_level_max v_connect_level_max := 0; if v_nodes.count > 0 then for j in v_nodes.first .. v_nodes.last loop if v_nodes(j).connect_level > v_connect_level_max then v_connect_level_max := v_nodes(j).connect_level; end if; end loop; end if; -- loop all hits for c2 (links) for c2_rec in c2 loop if k = 1 and c2_rec.v_nodes_table_r is not null -- pages linked to a source from c1 (the menu) or k = 2 --and c2_rec.v_nodes_table_r is null -- pages not linked to a source from c1 (the menu) then -- add edge if edge_exists ( v_source => c2_rec.edge_source , v_target => c2_rec.edge_target ) = false then add_edge; v_edges(v_edges_rows_n).source := c2_rec.edge_source; v_edges(v_edges_rows_n).target := c2_rec.edge_target; end if; -- if either the source or the target are not yet included in v_nodes, include it add_node ( p_node_id => c2_rec.edge_source , p_node_content => c2_rec.edge_source_content , p_node_href => c2_rec.edge_source_href , p_connect_level => v_connect_level_max + 1 , p_page_id => c2_rec.edge_source_page_id ) ; add_node ( p_node_id => c2_rec.edge_target , p_node_content => c2_rec.edge_target_content , p_node_href => c2_rec.edge_target_href , p_connect_level => v_connect_level_max + 1 , p_page_id => c2_rec.edge_target_page_id ) ; end if; end loop; end; end loop; -- c3 (lists) declare v_connect_level_max pls_integer := 0; begin -- determine v_connect_level_max v_connect_level_max := 0; if v_nodes.count > 0 then for j in v_nodes.first .. v_nodes.last loop if v_nodes(j).connect_level > v_connect_level_max then v_connect_level_max := v_nodes(j).connect_level; end if; end loop; end if; -- loop all hits for c3 (lists) for c3_rec in c3 loop -- add edge if edge_exists ( v_source => c3_rec.edge_source , v_target => c3_rec.edge_target ) = false then add_edge; v_edges(v_edges_rows_n).source := c3_rec.edge_source; v_edges(v_edges_rows_n).target := c3_rec.edge_target; v_edges(v_edges_rows_n).line_style := 'dashed'; -- to show this connection may not always be true end if; -- add edge (return path) if edge_exists ( v_source => c3_rec.edge_target , v_target => c3_rec.edge_source ) = false then add_edge; v_edges(v_edges_rows_n).source := c3_rec.edge_target; v_edges(v_edges_rows_n).target := c3_rec.edge_source; v_edges(v_edges_rows_n).line_style := 'dashed'; -- to show this connection may not always be true end if; -- if either the source or the target are not yet included in v_nodes, include it add_node ( p_node_id => c3_rec.edge_source , p_node_content => c3_rec.edge_source_content , p_node_href => c3_rec.edge_source_href , p_connect_level => v_connect_level_max + 0 , p_page_id => c3_rec.edge_source_page_id ) ; add_node ( p_node_id => c3_rec.edge_target , p_node_content => c3_rec.edge_target_content , p_node_href => c3_rec.edge_target_href , p_connect_level => v_connect_level_max + 0 , p_page_id => c3_rec.edge_target_page_id ) ; end loop; end; -- c99 (all pages) declare v_connect_level_max pls_integer := 0; begin -- determine v_connect_level_max v_connect_level_max := 0; if v_nodes.count > 0 then for j in v_nodes.first .. v_nodes.last loop if v_nodes(j).connect_level > v_connect_level_max then v_connect_level_max := v_nodes(j).connect_level; end if; end loop; end if; -- loop all hits for c99 (pages, needed to get all "non-linked" pages) for c99_rec in c99 loop -- if the source is not yet included in v_nodes, include it add_node ( p_node_id => c99_rec.edge_source , p_node_content => c99_rec.edge_source_content , p_node_href => c99_rec.edge_source_href , p_connect_level => v_connect_level_max + 1 , p_page_id => c99_rec.edge_source_page_id ) ; end loop; end; position_nodes; v_result := ted_cytoscape.cytoscape ( p_nodes => v_nodes , p_edges => v_edges , p_html_element_id => 'the_div_cytoscape' , p_layout => 'preset' --'preset' --'breadthfirst' --'cose' --'cose-bilkent' ) ; return v_result; end menu_structure; end ted_p1099;
Package
Package
Name
TED_CYTOSCAPE
Source
package ted_cytoscape is type t_cytoscape_node_record is record ( id varchar2( 100) , href varchar2(1000) , position_x number , position_y number , connect_level number , connect_sequence number -- (ANY) Labels: , color varchar2( 100) -- The colour of the element's label. , content varchar2(1000) -- The text to display for an element's label. , font_family varchar2( 100) -- A comma_separated list of font names to use on the label text. , font_size varchar2( 100) -- The size of the label text. , font_style varchar2( 100) -- A CSS font style to be applied to the label text. , font_weight varchar2( 100) -- A CSS font weight to be applied to the label text. , text_opacity varchar2( 100) -- The opacity of the label text, including its outline. , text_outline_color varchar2( 100) -- The colour of the outline around the element's label text. , text_outline_opacity varchar2( 100) -- The opacity of the outline on label text. , text_outline_width varchar2( 100) -- The size of the outline on label text. , min_zoomed_font_size varchar2( 100) -- If zooming makes the effective font size of the label smaller than this, then no label is shown. -- (ANY) Size & visibility: , opacity varchar2( 100) -- The opacity of the element. , visibility varchar2( 100) -- Whether the element is visible; can be visible or hidden. , width varchar2( 100) -- The element's width; the line width for edges or the horizontal size of a node. , z_index varchar2( 100) -- A non_negative integer that specifies the z_ordering of the element. An element with a higher z_index is put on top of an element with a lower value. -- (ANY) Overlays (e.g. used in :active state): , overlay_color varchar2( 100) -- The colour of the overlay. , overlay_padding varchar2( 100) -- The area outside of the element within which the overlay is shown. , overlay_opacity varchar2( 100) -- The opacity of the overlay. -- (ANY) Transition animations: , transition_property varchar2( 100) -- A comma separated list of style properties to animate in this state. , transition_duration varchar2( 100) -- The length of the transition in seconds (e.g. 0.5s). , transition_delay varchar2( 100) -- The length of the delay in seconds before the transition occurs (e.g. 0.25s). -- (NODES) Labels: , text_halign varchar2( 100) -- The vertical alignment of a label; may have value left, center, or right. , text_valign varchar2( 100) -- The vertical alignment of a label; may have value top, center, or bottom. -- (NODES) Body: , background_color varchar2( 100) -- The colour of the node's body. , background_blacken varchar2( 100) -- Blackens the node's body for values from 0 to 1; whitens the node's body for values from 0 to _1. , background_opacity varchar2( 100) -- The opacity level of the node's body. , border_color varchar2( 100) -- The colour of the node's border. , border_opacity varchar2( 100) -- The opacity of the node's border. , border_width varchar2( 100) -- The size of the node's border. , height varchar2( 100) -- The height of the node's body. , shape varchar2( 100) -- The shape of the node's body; may be rectangle, roundrectangle, ellipse, triangle, pentagon, hexagon, heptagon, octagon, star. Note that each shape fits within the specified width and height, and so you may have to adjust width and height if you desire an equilateral shape (i.e. width !== height for several equilateral shapes). -- (NODES) Background image: , background_image varchar2( 100) -- The URL that points to the image that should be used as the node's background. PNG, JPG, and SVG are supported formats. , background_fit varchar2( 100) -- How the background image is fit to the node; may be none for original size, contain to fit inside node, or cover to cover the node. , background_repeat varchar2( 100) -- Whether to repeat the background image; may be no_repeat, repeat_x, repeat_y, or repeat. , background_position_x varchar2( 100) -- The x position of the background image, measured in percent (e.g. 50%) or pixels (e.g. 10px). , background_position_y varchar2( 100) -- The y position of the background image, measured in percent (e.g. 50%) or pixels (e.g. 10px). , background_clip varchar2( 100) -- How background image clipping is handled; may be node for clipped to node shape or none for no clipping. -- (PIE) Pie chart background: , pie_size varchar2( 100) -- The diameter of the pie, measured as a percent of node size (e.g. 100%) or an absolute length (e.g. 25px). , pie_i_background_color varchar2( 100) -- The colour of the node's ith pie chart slice. , pie_i_background_size varchar2( 100) -- The size of the node's ith pie chart slice, measured in percent (e.g. 25% or 25). ) ; type t_cytoscape_node_table is table of t_cytoscape_node_record; type t_cytoscape_edge_record is record ( source varchar2( 100) , target varchar2(1000) -- (ANY) Labels: , color varchar2( 100) -- The colour of the element's label. , content varchar2( 100) -- The text to display for an element's label. , font_family varchar2( 100) -- A comma_separated list of font names to use on the label text. , font_size varchar2( 100) -- The size of the label text. , font_style varchar2( 100) -- A CSS font style to be applied to the label text. , font_weight varchar2( 100) -- A CSS font weight to be applied to the label text. , text_opacity varchar2( 100) -- The opacity of the label text, including its outline. , text_outline_color varchar2( 100) -- The colour of the outline around the element's label text. , text_outline_opacity varchar2( 100) -- The opacity of the outline on label text. , text_outline_width varchar2( 100) -- The size of the outline on label text. , min_zoomed_font_size varchar2( 100) -- If zooming makes the effective font size of the label smaller than this, then no label is shown. -- (ANY) Size & visibility: , opacity varchar2( 100) -- The opacity of the element. , visibility varchar2( 100) -- Whether the element is visible; can be visible or hidden. , width varchar2( 100) -- The element's width; the line width for edges or the horizontal size of a node. , z_index varchar2( 100) -- A non_negative integer that specifies the z_ordering of the element. An element with a higher z_index is put on top of an element with a lower value. -- (ANY) Overlays (e.g. used in :active state): , overlay_color varchar2( 100) -- The colour of the overlay. , overlay_padding varchar2( 100) -- The area outside of the element within which the overlay is shown. , overlay_opacity varchar2( 100) -- The opacity of the overlay. -- (ANY) Transition animations: , transition_property varchar2( 100) -- A comma separated list of style properties to animate in this state. , transition_duration varchar2( 100) -- The length of the transition in seconds (e.g. 0.5s). , transition_delay varchar2( 100) -- The length of the delay in seconds before the transition occurs (e.g. 0.25s). -- (EDGE) Edge properties , curve_style varchar2( 100) -- The curving method used to separate two or more edges between two nodes; may be bezier (default) or haystack (for which loops are unsupported). Note that haystack edges work best with ellipse, rectangle, or similar nodes. Smaller node shapes, like triangle, will not be as aesthetically pleasing. Also note that edge arrows are unsupported for haystack edges. , control_point_step_size varchar2( 100) -- From the line perpendicular from source to target, this value specifies the distance between successive bezier edges. , control_point_distance varchar2( 100) -- Overrides control_point_step_size with a manual value. Because it overrides the step size, bezier edges with the same value will overlap. Thus, it's best to use this as a one_off value for particular edges if need be. , control_point_weight varchar2( 100) -- Weights control points along the line from source to target. This value ranges on [0, 1], with 0 towards the source node and 1 towards the target node. , line_color varchar2( 100) -- The colour of the edge's line. , line_style varchar2( 100) -- The style of the edge's line; may be solid, dotted, or dashed. , source_arrow_color varchar2( 100) -- The colour of the edge's arrow on the source side. , source_arrow_shape varchar2( 100) -- The shape of the edge's arrow on the source side; may be tee, triangle, square, circle, diamond, or none. , source_arrow_fill varchar2( 100) -- The fill state of the edge's source arrow; may be filled or hollow. , target_arrow_color varchar2( 100) -- The colour of the edge's arrow on the target side. , target_arrow_shape varchar2( 100) -- The shape of the edge's arrow on the target side; may be tee, triangle, square, circle, diamond, or none. , target_arrow_fill varchar2( 100) -- The fill state of the edge's target arrow; may be filled or hollow. ) ; type t_cytoscape_edge_table is table of t_cytoscape_edge_record; /* -- (COMPOUND NODES) Compound nodes: , padding_left varchar2( 100) -- The size of the area on the left of the compound node that can not be occupied by child nodes. , padding_right varchar2( 100) -- The size of the area on the right of the compound node that can not be occupied by child nodes. , padding_top varchar2( 100) -- The size of the area on the top of the compound node that can not be occupied by child nodes. , padding_bottom varchar2( 100) -- The size of the area on the bottom of the compound node that can not be occupied by child nodes. -- (CORE) Core properties -- You can use the special core selector string to set these properties. , active_bg_color varchar2( 100) -- The colour of the indicator shown when the background is grabbed by the user. , active_bg_opacity varchar2( 100) -- The opacity of the active background indicator. , active_bg_size varchar2( 100) -- The size of the active background indicator. , selection_box_color varchar2( 100) -- The background colour of the selection box used for drag selection. , selection_box_border_color varchar2( 100) -- The colour of the border on the selection box. , selection_box_border_width varchar2( 100) -- The size of the border on the selection box. , selection_box_opacity varchar2( 100) -- The opacity of the selection box. , outside_texture_bg_color varchar2( 100) -- The colour of the area outside the viewport texture when initOptions.textureOnViewport === true. , outside_texture_bg_opacity varchar2( 100) -- The opacity of the area outside the viewport texture. */ function cytoscape ( p_nodes in t_cytoscape_node_table , p_edges in t_cytoscape_edge_table , p_html_element_id in varchar2 , p_layout in varchar2 := null , p_href_open_in_new_window in boolean := false ) return clob ; end ted_cytoscape;
Package Body
Package Body
Name
TED_CYTOSCAPE
Source
package body ted_cytoscape is function add_property ( p_property_name in varchar2 , p_property_value in varchar2 , p_this_is_the_first in boolean := false ) return varchar2 is v_result varchar2(1000); v_check_number number; v_quote varchar2(1); begin begin v_quote := ''; v_check_number := to_number(p_property_value); exception when others then v_quote := '"'; end; if p_property_value is not null then v_result := ( case when p_this_is_the_first = true then '{ ' else ', ' end ) || p_property_name || ': ' || v_quote || p_property_value || v_quote ; end if; return v_result; end; function cytoscape ( p_nodes in t_cytoscape_node_table , p_edges in t_cytoscape_edge_table , p_html_element_id in varchar2 , p_layout in varchar2 := null , p_href_open_in_new_window in boolean := false ) return clob is v_lf varchar2(2) := chr(10); v_c1_count pls_integer; v_result clob; begin dbms_lob.createtemporary(v_result , true, dbms_lob.call); -- init v_result dbms_lob.append(v_result, v_lf); dbms_lob.append(v_result, ' <script src="https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.2.3/cytoscape.min.js"></script>' || v_lf); -- get this link here: https://cdnjs.com/libraries/cytoscape case p_layout when 'cose-bilkent' then dbms_lob.append(v_result, ' <script src="https://cdn.rawgit.com/cytoscape/cytoscape.js-cose-bilkent/1.6.5/cytoscape-cose-bilkent.js"></script>' || v_lf); else null; end case; dbms_lob.append(v_result, ' <script type="text/javascript">' || v_lf); -- build var nodes dbms_lob.append(v_result, ' var nodes = [' || v_lf); -- loop nodes v_c1_count := 0; if p_nodes.count > 0 then for i in p_nodes.first .. p_nodes.last loop v_c1_count := v_c1_count + 1; -- build node row dbms_lob.append(v_result, ' '); if v_c1_count > 1 then dbms_lob.append(v_result, ', '); else dbms_lob.append(v_result, ' '); end if; dbms_lob.append ( v_result , '{ data: ' || add_property('id', p_nodes(i).id, true) || add_property('href', nvl(p_nodes(i).href,'#')) -- (ANY) Labels: || add_property('color', p_nodes(i).color) || add_property('content', p_nodes(i).content) || add_property('font_family', p_nodes(i).font_family) || add_property('font_size', p_nodes(i).font_size) || add_property('font_style', p_nodes(i).font_style) || add_property('font_weight', p_nodes(i).font_weight) || add_property('text_opacity', p_nodes(i).text_opacity) || add_property('text_outline_color', p_nodes(i).text_outline_color) || add_property('text_outline_opacity', p_nodes(i).text_outline_opacity) || add_property('text_outline_width', p_nodes(i).text_outline_width) || add_property('min_zoomed_font_size', p_nodes(i).min_zoomed_font_size) -- (ANY) Size & visibility: || add_property('opacity', p_nodes(i).opacity) || add_property('visibility', p_nodes(i).visibility) || add_property('width', p_nodes(i).width) || add_property('z_index', p_nodes(i).z_index) -- (ANY) Overlays: || add_property('overlay_color', p_nodes(i).overlay_color) || add_property('overlay_padding', p_nodes(i).overlay_padding) || add_property('overlay_opacity', p_nodes(i).overlay_opacity) -- (ANY) Transition animations: || add_property('transition_property', p_nodes(i).transition_property) || add_property('transition_duration', p_nodes(i).transition_duration) || add_property('transition_delay', p_nodes(i).transition_delay) -- (NODES) Labels: || add_property('text_halign', p_nodes(i).text_halign) || add_property('text_valign', p_nodes(i).text_valign) -- (NODES) Body: || add_property('background_color', p_nodes(i).background_color) || add_property('background_blacken', p_nodes(i).background_blacken) || add_property('background_opacity', p_nodes(i).background_opacity) || add_property('border_color', p_nodes(i).border_color) || add_property('border_opacity', p_nodes(i).border_opacity) || add_property('border_width', p_nodes(i).border_width) || add_property('height', p_nodes(i).height) || add_property('shape', p_nodes(i).shape) -- (NODES) Background image: || add_property('background_image', p_nodes(i).background_image) || add_property('background_fit', p_nodes(i).background_fit) || add_property('background_repeat', p_nodes(i).background_repeat) || add_property('background_position_x', p_nodes(i).background_position_x) || add_property('background_position_y', p_nodes(i).background_position_y) || add_property('background_clip', p_nodes(i).background_clip) -- (PIE) Pie chart background: || add_property('pie_size', p_nodes(i).pie_size) || add_property('pie_i_background_color', p_nodes(i).pie_i_background_color) || add_property('pie_i_background_size', p_nodes(i).pie_i_background_size) || ' }' -- Position || case when p_nodes(i).position_x is not null and p_nodes(i).position_y is not null then ', position: ' || add_property('x', p_nodes(i).position_x, true) || add_property('y', p_nodes(i).position_y) || ' }' end -- || ' }' || v_lf ) ; end loop; end if; -- close var nodes dbms_lob.append(v_result, ' ];' || v_lf); -- build var edges dbms_lob.append(v_result, v_lf); dbms_lob.append(v_result, ' var edges = [' || v_lf); -- loop edges if p_edges.count > 0 then for i in p_edges.first .. p_edges.last loop v_c1_count := v_c1_count + 1; -- build edge row dbms_lob.append(v_result, ' '); if v_c1_count > 1 then dbms_lob.append(v_result, ', '); else dbms_lob.append(v_result, ' '); end if; dbms_lob.append ( v_result , '{ data: ' || add_property('source', p_edges(i).source, true) || add_property('target', p_edges(i).target) -- (ANY) Labels: -- || add_property('color', p_edges(i).color) || add_property('content', p_edges(i).content) || add_property('font_family', p_edges(i).font_family) || add_property('font_size', p_edges(i).font_size) || add_property('font_style', p_edges(i).font_style) || add_property('font_weight', p_edges(i).font_weight) || add_property('text_opacity', p_edges(i).text_opacity) || add_property('text_outline_color', p_edges(i).text_outline_color) || add_property('text_outline_opacity', p_edges(i).text_outline_opacity) || add_property('text_outline_width', p_edges(i).text_outline_width) || add_property('min_zoomed_font_size', p_edges(i).min_zoomed_font_size) -- (ANY) Size & visibility: || add_property('opacity', p_edges(i).opacity) || add_property('visibility', p_edges(i).visibility) || add_property('width', p_edges(i).width) || add_property('z_index', p_edges(i).z_index) -- (ANY) Overlays: || add_property('overlay_color', p_edges(i).overlay_color) || add_property('overlay_padding', p_edges(i).overlay_padding) || add_property('overlay_opacity', p_edges(i).overlay_opacity) -- (ANY) Transition animations: || add_property('transition_property', p_edges(i).transition_property) || add_property('transition_duration', p_edges(i).transition_duration) || add_property('transition_delay', p_edges(i).transition_delay) -- (EDGE) Edge properties || add_property('curve_style', p_edges(i).curve_style) || add_property('control_point_step_size', p_edges(i).control_point_step_size) || add_property('control_point_distance', p_edges(i).control_point_distance) || add_property('control_point_weight', p_edges(i).control_point_weight) || add_property('line_color', p_edges(i).line_color) || add_property('line_style', p_edges(i).line_style) || add_property('source_arrow_color', p_edges(i).source_arrow_color) || add_property('source_arrow_shape', p_edges(i).source_arrow_shape) || add_property('source_arrow_fill', p_edges(i).source_arrow_fill) || add_property('target_arrow_color', p_edges(i).target_arrow_color) || add_property('target_arrow_shape', p_edges(i).target_arrow_shape) || add_property('target_arrow_fill', p_edges(i).target_arrow_fill) -- || ' } }' || v_lf ) ; end loop; end if; -- close var edges dbms_lob.append(v_result, ' ];' || v_lf); -- build var positions v_c1_count := 0; if p_nodes.count > 0 then for i in p_nodes.first .. p_nodes.last loop if p_nodes(i).position_x is not null and p_nodes(i).position_y is not null then v_c1_count := v_c1_count + 1; -- start var positions if v_c1_count = 1 then dbms_lob.append(v_result, v_lf); dbms_lob.append(v_result, ' var positions = [ ' || v_lf); end if; -- build position row dbms_lob.append(v_result, ' '); if v_c1_count > 1 then dbms_lob.append(v_result, ', '); else dbms_lob.append(v_result, ' '); end if; dbms_lob.append ( v_result , '{ "' || p_nodes(i).id || '": ' || add_property('x', p_nodes(i).position_x, true) || add_property('y', p_nodes(i).position_y) || ' } }' || v_lf ) ; end if; end loop; end if; -- close var positions if v_c1_count > 0 then dbms_lob.append(v_result, ' ];' || v_lf); end if; -- build cy dbms_lob.append(v_result, v_lf); -- dbms_lob.append(v_result, ' $(function(){ // on dom ready' || v_lf); dbms_lob.append(v_result, ' var cy = cytoscape({' || v_lf); -- dbms_lob.append(v_result, ' container: $("#' || p_html_element_id || '")[0],' || v_lf); dbms_lob.append(v_result, ' container: document.getElementById("' || p_html_element_id || '"),' || v_lf); dbms_lob.append(v_result, ' elements: {' || v_lf); dbms_lob.append(v_result, ' nodes: nodes,' || v_lf); dbms_lob.append(v_result, ' edges: edges' || v_lf); dbms_lob.append(v_result, ' },' || v_lf); -- layout if p_layout = 'null' then -- "The null layout puts all nodes at (0, 0). It's useful for debugging purposes." dbms_lob.append(v_result, ' layout: {' || v_lf); dbms_lob.append(v_result, ' name: "' || p_layout || '",' || v_lf); -- ### to do: options dbms_lob.append(v_result, ' },' || v_lf); elsif p_layout = 'random' then -- "The random layout puts nodes in random positions within the viewport." dbms_lob.append(v_result, ' layout: {' || v_lf); dbms_lob.append(v_result, ' name: "' || p_layout || '",' || v_lf); -- ### to do: options dbms_lob.append(v_result, ' },' || v_lf); elsif p_layout = 'preset' then -- "The preset layout puts nodes in the positions you specify manually." dbms_lob.append(v_result, ' layout: {' || v_lf); dbms_lob.append(v_result, ' name: "' || p_layout || '",' || v_lf); -- ### , too much /* dbms_lob.append(v_result, v_lf); dbms_lob.append(v_result, ' fit: true, // whether to fit to viewport' || v_lf); dbms_lob.append(v_result, ' ready: undefined, // callback on layoutready' || v_lf); dbms_lob.append(v_result, ' stop: undefined, // callback on layoutstop' || v_lf); dbms_lob.append(v_result, ' positions: positions, // map of (node id) => (position obj)' || v_lf); dbms_lob.append(v_result, ' zoom: undefined, // the zoom level to set (prob want fit = false if set)' || v_lf); dbms_lob.append(v_result, ' pan: undefined, // the pan level to set (prob want fit = false if set)' || v_lf); dbms_lob.append(v_result, ' padding: 30 // padding on fit' || v_lf); */ dbms_lob.append(v_result, ' },' || v_lf); elsif p_layout = 'grid' then -- "The grid layout puts nodes in a well-spaced grid." dbms_lob.append(v_result, ' layout: {' || v_lf); dbms_lob.append(v_result, ' name: "' || p_layout || '",' || v_lf); -- ### to do: options dbms_lob.append(v_result, ' },' || v_lf); elsif p_layout = 'circle' then -- "The circle layout puts nodes in a circle." dbms_lob.append(v_result, ' layout: {' || v_lf); dbms_lob.append(v_result, ' name: "' || p_layout || '",' || v_lf); -- ### to do: options dbms_lob.append(v_result, ' },' || v_lf); elsif p_layout = 'concentric' then -- "The concentric layout positions nodes in concentric circles, based on a metric that you specify to segregate the nodes into levels. This layout sets the concentric layout value based on your metric, which can be used with mapLayoutData()." dbms_lob.append(v_result, ' layout: {' || v_lf); dbms_lob.append(v_result, ' name: "' || p_layout || '",' || v_lf); -- ### to do: options dbms_lob.append(v_result, ' },' || v_lf); elsif p_layout = 'breadthfirst' then -- "The breadthfirst layout puts nodes in a hierarchy, based on a breadthfirst traversal of the graph." -- Disabled, works but doesn't look very nice dbms_lob.append(v_result, ' layout: {' || v_lf); dbms_lob.append(v_result, ' name: "' || p_layout || '",' || v_lf); dbms_lob.append(v_result, v_lf); dbms_lob.append(v_result, ' fit: true, // whether to fit the viewport to the graph' || v_lf); dbms_lob.append(v_result, ' ready: undefined, // callback on layoutready' || v_lf); dbms_lob.append(v_result, ' stop: undefined, // callback on layoutstop' || v_lf); dbms_lob.append(v_result, ' directed: false, // whether the tree is directed downwards (or edges can point in any direction if false)' || v_lf); dbms_lob.append(v_result, ' padding: 30, // padding on fit' || v_lf); dbms_lob.append(v_result, ' circle: false, // put depths in concentric circles if true, put depths top down if false' || v_lf); dbms_lob.append(v_result, ' roots: undefined, // the roots of the trees' || v_lf); dbms_lob.append(v_result, ' maximalAdjustments: 0 // how many times to try to position the nodes in a maximal way (i.e. no backtracking)' || v_lf); dbms_lob.append(v_result, ' },' || v_lf); elsif p_layout = 'arbor' then -- "The arbor layout uses a force-directed physics simulation." -- CAUSES ERROR: -- Error: SecurityError: The operation is insecure. -- Source File: http://cytoscape.github.io/cytoscape.js/api/cytoscape.js-latest/arbor.js dbms_lob.append(v_result, ' layout: {' || v_lf); dbms_lob.append(v_result, ' name: "' || p_layout || '",' || v_lf); dbms_lob.append(v_result, v_lf); dbms_lob.append(v_result, ' liveUpdate: true, // whether to show the layout as it is running' || v_lf); dbms_lob.append(v_result, ' ready: undefined, // callback on layoutready ' || v_lf); dbms_lob.append(v_result, ' stop: undefined, // callback on layoutstop' || v_lf); dbms_lob.append(v_result, ' maxSimulationTime: 4000, // max length in ms to run the layout' || v_lf); dbms_lob.append(v_result, ' fit: true, // reset viewport to fit default simulationBounds' || v_lf); dbms_lob.append(v_result, ' padding: [ 50, 50, 50, 50 ], // top, right, bottom, left' || v_lf); dbms_lob.append(v_result, ' simulationBounds: undefined, // [x1, y1, x2, y2]; [0, 0, width, height] by default' || v_lf); dbms_lob.append(v_result, ' ungrabifyWhileSimulating: true, // so you can"t drag nodes during layout' || v_lf); dbms_lob.append(v_result, v_lf); dbms_lob.append(v_result, ' // forces used by arbor (use arbor default on undefined)' || v_lf); dbms_lob.append(v_result, ' repulsion: undefined,' || v_lf); dbms_lob.append(v_result, ' stiffness: undefined,' || v_lf); dbms_lob.append(v_result, ' friction: undefined,' || v_lf); dbms_lob.append(v_result, ' gravity: true,' || v_lf); dbms_lob.append(v_result, ' fps: undefined,' || v_lf); dbms_lob.append(v_result, ' precision: undefined,' || v_lf); dbms_lob.append(v_result, v_lf); dbms_lob.append(v_result, ' // static numbers or functions that dynamically return what these' || v_lf); dbms_lob.append(v_result, ' // values should be for each element' || v_lf); dbms_lob.append(v_result, ' nodeMass: undefined, ' || v_lf); dbms_lob.append(v_result, ' edgeLength: undefined,' || v_lf); dbms_lob.append(v_result, v_lf); dbms_lob.append(v_result, ' stepSize: 1, // size of timestep in simulation' || v_lf); dbms_lob.append(v_result, v_lf); dbms_lob.append(v_result, ' // function that returns true if the system is stable to indicate' || v_lf); dbms_lob.append(v_result, ' // that the layout can be stopped' || v_lf); dbms_lob.append(v_result, ' stableEnergy: function( energy ){' || v_lf); dbms_lob.append(v_result, ' var e = energy; ' || v_lf); dbms_lob.append(v_result, ' return (e.max <= 0.5) || (e.mean <= 0.3);' || v_lf); dbms_lob.append(v_result, ' }' || v_lf); dbms_lob.append(v_result, ' },' || v_lf); elsif p_layout = 'cose' or p_layout ='cose-bilkent' then -- "The cose (Compound Spring Embedder) layout uses a force-directed simulation to lay out compound graphs." -- "The cose-bilkent extension is an evolution of the algorithm that is more computationally expensive but produces near-perfect results." dbms_lob.append(v_result, ' layout: {' || v_lf); dbms_lob.append(v_result, ' name: "' || p_layout || '",' || v_lf); dbms_lob.append(v_result, v_lf); -- dbms_lob.append(v_result, ' ready: function() {}, // Called on layoutready' || v_lf); -- dbms_lob.append(v_result, ' stop: function() {}, // Called on layoutstop' || v_lf); -- dbms_lob.append(v_result, ' refresh: 0, // Number of iterations between consecutive screen positions update (0 -> only updated on the end)' || v_lf); -- dbms_lob.append(v_result, ' fit: true, // Whether to fit the network view after when done' || v_lf); -- dbms_lob.append(v_result, ' padding: 30, // Padding on fit' || v_lf); -- dbms_lob.append(v_result, ' randomize: true, // Whether to randomize node positions on the beginning' || v_lf); -- false causes error (no result) -- dbms_lob.append(v_result, ' debug: false, // Whether to use the JS console to print debug messages' || v_lf); -- dbms_lob.append(v_result, ' nodeRepulsion: 10000, // Node repulsion (non overlapping) multiplier' || v_lf); -- default=10000; 1000000 is nicer? -- dbms_lob.append(v_result, ' nodeOverlap: 10, // Node repulsion (overlapping) multiplier' || v_lf); -- dbms_lob.append(v_result, ' idealEdgeLength: 10, // Ideal edge (non nested) length' || v_lf); -- dbms_lob.append(v_result, ' edgeElasticity: 100, // Divisor to compute edge forces' || v_lf); -- default=100; 10 is nicer? -- dbms_lob.append(v_result, ' nestingFactor: 5, // Nesting factor (multiplier) to compute ideal edge length for nested edges' || v_lf); -- dbms_lob.append(v_result, ' gravity: 250, // Gravity force (constant)' || v_lf); -- dbms_lob.append(v_result, ' numIter: 100, // Maximum number of iterations to perform' || v_lf); -- dbms_lob.append(v_result, ' initialTemp: 200, // Initial temperature (maximum node displacement)' || v_lf); -- dbms_lob.append(v_result, ' coolingFactor: 0.95, // Cooling factor (how the temperature is reduced between consecutive iterations' || v_lf); -- dbms_lob.append(v_result, ' minTemp: 1 // Lower temperature threshold (below this point the layout will end)' || v_lf); dbms_lob.append(v_result, ' },' || v_lf); else null; end if; -- zoom -- dbms_lob.append(v_result, v_lf); -- dbms_lob.append(v_result, ' minZoom: 0.5,' || v_lf); -- dbms_lob.append(v_result, ' maxZoom: 2,' || v_lf); -- style dbms_lob.append(v_result, v_lf); dbms_lob.append(v_result, ' style: cytoscape.stylesheet()' || v_lf); dbms_lob.append(v_result, ' .selector("node")' || v_lf); dbms_lob.append(v_result, ' .css({' || v_lf); -- (ANY) Labels: -- dbms_lob.append(v_result, '"color": "data(color)",' || v_lf); dbms_lob.append(v_result, '"content": "data(content)",' || v_lf); -- dbms_lob.append(v_result, '"font-family": "data(font_family)",' || v_lf); -- dbms_lob.append(v_result, '"font-size": "data(font_size)",' || v_lf); -- dbms_lob.append(v_result, '"font-style": "data(font_style)",' || v_lf); -- dbms_lob.append(v_result, '"font-weight": "data(font_weight)",' || v_lf); -- dbms_lob.append(v_result, '"text-opacity": "data(text_opacity)",' || v_lf); dbms_lob.append(v_result, '"text-outline-color": "data(text_outline_color)",' || v_lf); -- dbms_lob.append(v_result, '"text-outline-opacity": "data(text_outline_opacity)",' || v_lf); dbms_lob.append(v_result, '"text-outline-width": "data(text_outline_width)",' || v_lf); -- dbms_lob.append(v_result, '"min-zoomed-font-size": "data(min_zoomed_font_size)",' || v_lf); -- (ANY) Size & visibility: -- dbms_lob.append(v_result, '"opacity": "data(opacity)",' || v_lf); -- dbms_lob.append(v_result, '"visibility": "data(visibility)",' || v_lf); dbms_lob.append(v_result, '"width": "data(width)",' || v_lf); -- dbms_lob.append(v_result, '"z-index": "data(z_index)",' || v_lf); -- (ANY) Overlays: -- dbms_lob.append(v_result, '"overlay-color": "data(overlay_color)",' || v_lf); -- dbms_lob.append(v_result, '"overlay-padding": "data(overlay_padding)",' || v_lf); -- dbms_lob.append(v_result, '"overlay-opacity": "data(overlay_opacity)",' || v_lf); -- (ANY) Transition animations: -- dbms_lob.append(v_result, '"transition-property": "data(transition_property)",' || v_lf); -- dbms_lob.append(v_result, '"transition-duration": "data(transition_duration)",' || v_lf); -- dbms_lob.append(v_result, '"transition-delay": "data(transition_delay)",' || v_lf); -- (NODES) Labels: -- dbms_lob.append(v_result, '"text-halign": "data(text_halign)",' || v_lf); dbms_lob.append(v_result, '"text-valign": "data(text_valign)",' || v_lf); -- (NODES) Body: dbms_lob.append(v_result, '"background-color": "data(background_color)",' || v_lf); -- dbms_lob.append(v_result, '"background-blacken": "data(background_blacken)",' || v_lf); -- dbms_lob.append(v_result, '"background-opacity": "data(background_opacity)",' || v_lf); dbms_lob.append(v_result, '"border-color": "data(border_color)",' || v_lf); -- dbms_lob.append(v_result, '"border-opacity": "data(border_opacity)",' || v_lf); dbms_lob.append(v_result, '"border-width": "data(border_width)",' || v_lf); dbms_lob.append(v_result, '"height": "data(height)",' || v_lf); -- dbms_lob.append(v_result, '"shape": "data(shape)",' || v_lf); -- (NODES) Background image: -- dbms_lob.append(v_result, '"background-image": "data(background_image)",' || v_lf); -- dbms_lob.append(v_result, '"background-fit": "data(background_fit)",' || v_lf); -- dbms_lob.append(v_result, '"background-repeat": "data(background_repeat)",' || v_lf); -- dbms_lob.append(v_result, '"background-position-x": "data(background_position_x)",' || v_lf); -- dbms_lob.append(v_result, '"background-position-y": "data(background_position_y)",' || v_lf); -- dbms_lob.append(v_result, '"background-clip": "data(background_clip)",' || v_lf); -- (PIE) Pie chart background: -- dbms_lob.append(v_result, '"pie-size": "data(pie_size)",' || v_lf); -- dbms_lob.append(v_result, '"pie-i-background-color": "data(pie_i_background_color)",' || v_lf); -- dbms_lob.append(v_result, '"pie-i-background-size": "data(pie_i_background_size)",' || v_lf); dbms_lob.append(v_result, ' })' || v_lf); dbms_lob.append(v_result, v_lf); -- -- ########################## .selector(":selected"): NOT NICE BUT IT WORKS FOR NOW dbms_lob.append(v_result, ' .selector(":selected")' || v_lf); dbms_lob.append(v_result, ' .css({' || v_lf); dbms_lob.append(v_result, ' "color": "#FFFFFF",' || v_lf); dbms_lob.append(v_result, ' "background-color": "#000000",' || v_lf); dbms_lob.append(v_result, ' "line-color": "#000000",' || v_lf); dbms_lob.append(v_result, ' "target-arrow-color": "#000000",' || v_lf); dbms_lob.append(v_result, ' "text-outline-color": "#000000"' || v_lf); dbms_lob.append(v_result, ' })' || v_lf); dbms_lob.append(v_result, v_lf); dbms_lob.append(v_result, ' .selector("edge")' || v_lf); dbms_lob.append(v_result, ' .css({' || v_lf); -- (ANY) Labels: -- dbms_lob.append(v_result, '"color": "data(color)",' || v_lf); -- dbms_lob.append(v_result, '"content": "data(content)",' || v_lf); -- dbms_lob.append(v_result, '"font-family": "data(font_family)",' || v_lf); -- dbms_lob.append(v_result, '"font-size": "data(font_size)",' || v_lf); -- dbms_lob.append(v_result, '"font-style": "data(font_style)",' || v_lf); -- dbms_lob.append(v_result, '"font-weight": "data(font_weight)",' || v_lf); -- dbms_lob.append(v_result, '"text-opacity": "data(text_opacity)",' || v_lf); -- dbms_lob.append(v_result, '"text-outline-color": "data(text_outline_color)",' || v_lf); -- dbms_lob.append(v_result, '"text-outline-opacity": "data(text_outline_opacity)",' || v_lf); -- dbms_lob.append(v_result, '"text-outline-width": "data(text_outline_width)",' || v_lf); -- dbms_lob.append(v_result, '"min-zoomed-font-size": "data(min_zoomed_font_size)",' || v_lf); -- (ANY) Size & visibility: -- dbms_lob.append(v_result, '"opacity": "data(opacity)",' || v_lf); -- dbms_lob.append(v_result, '"visibility": "data(visibility)",' || v_lf); dbms_lob.append(v_result, '"width": "data(width)",' || v_lf); -- dbms_lob.append(v_result, '"z-index": "data(z_index)",' || v_lf); -- (ANY) Overlays: -- dbms_lob.append(v_result, '"overlay-color": "data(overlay_color)",' || v_lf); -- dbms_lob.append(v_result, '"overlay-padding": "data(overlay_padding)",' || v_lf); -- dbms_lob.append(v_result, '"overlay-opacity": "data(overlay_opacity)",' || v_lf); -- (ANY) Transition animations: -- dbms_lob.append(v_result, '"transition-property": "data(transition_property)",' || v_lf); -- dbms_lob.append(v_result, '"transition-duration": "data(transition_duration)",' || v_lf); -- dbms_lob.append(v_result, '"transition-delay": "data(transition_delay)",' || v_lf); -- (EDGE) Edge properties -- dbms_lob.append(v_result, '"curve-style": "data(curve_style)",' || v_lf); -- dbms_lob.append(v_result, '"control-point-step-size": "data(control_point_step_size)",' || v_lf); -- -- Disabled, gives javascript error when control-point-distance is null: "Error: TypeError: u is undefined - Source File: http://cytoscape.github.io/cytoscape.js/api/cytoscape.js-latest/cytoscape.min.js Line: 18" -- -- dbms_lob.append(v_result, '"control-point-distance": "data(control_point_distance)",' || v_lf); -- dbms_lob.append(v_result, '"control-point-weight": "data(control_point_weight)",' || v_lf); -- dbms_lob.append(v_result, '"line-color": "data(line_color)",' || v_lf); -- dbms_lob.append(v_result, '"line-style": "data(line_style)",' || v_lf); -- dbms_lob.append(v_result, '"source-arrow-color": "data(source_arrow_color)",' || v_lf); -- dbms_lob.append(v_result, '"source-arrow-shape": "data(source_arrow_shape)",' || v_lf); -- dbms_lob.append(v_result, '"source-arrow-fill": "data(source_arrow_fill)",' || v_lf); -- dbms_lob.append(v_result, '"target-arrow-color": "data(target_arrow_color)",' || v_lf); dbms_lob.append(v_result, '"target-arrow-shape": "data(target_arrow_shape)",' || v_lf); -- dbms_lob.append(v_result, '"target-arrow-fill": "data(target_arrow_fill)",' || v_lf); dbms_lob.append(v_result, ' })' || v_lf); -- close var cy dbms_lob.append(v_result, ' });' || v_lf); -- href dbms_lob.append(v_result, ' cy.on("tap", "node", function(){' || v_lf); if p_href_open_in_new_window = true then dbms_lob.append(v_result, ' window.open( this.data("href") );' || v_lf); else dbms_lob.append(v_result, ' window.location.href = this.data("href");' || v_lf); end if; dbms_lob.append(v_result, ' });' || v_lf); -- qtip -- disabled, qtip plugin install needed /* dbms_lob.append(v_result, ' cy.on("mousemove","node", function(event){' || v_lf); dbms_lob.append(v_result, ' var target = event.cyTarget;' || v_lf); dbms_lob.append(v_result, ' var sourceName = target.data("source");' || v_lf); dbms_lob.append(v_result, ' var targetName = target.data("target");' || v_lf); dbms_lob.append(v_result, ' var x=event.cyPosition.x;' || v_lf); dbms_lob.append(v_result, ' var y=event.cyPosition.y;' || v_lf); dbms_lob.append(v_result, ' $("#box").qtip({' || v_lf); dbms_lob.append(v_result, ' content: {' || v_lf); dbms_lob.append(v_result, ' title:targetName,' || v_lf); dbms_lob.append(v_result, ' text: sourceName' || v_lf); dbms_lob.append(v_result, ' },' || v_lf); dbms_lob.append(v_result, ' show: {' || v_lf); dbms_lob.append(v_result, ' delay: 0,' || v_lf); dbms_lob.append(v_result, ' event: false,' || v_lf); dbms_lob.append(v_result, ' ready: true,' || v_lf); dbms_lob.append(v_result, ' effect:false' || v_lf); dbms_lob.append(v_result, ' },' || v_lf); dbms_lob.append(v_result, ' position: {' || v_lf); dbms_lob.append(v_result, ' my: "bottom center",' || v_lf); dbms_lob.append(v_result, ' at: "top center",' || v_lf); dbms_lob.append(v_result, ' target: [x+3, y+3],' || v_lf); dbms_lob.append(v_result, ' adjust: {' || v_lf); dbms_lob.append(v_result, ' x: 7,' || v_lf); dbms_lob.append(v_result, ' y:7' || v_lf); dbms_lob.append(v_result, ' }' || v_lf); dbms_lob.append(v_result, ' },' || v_lf); dbms_lob.append(v_result, ' hide: {' || v_lf); dbms_lob.append(v_result, ' fixed: true,' || v_lf); dbms_lob.append(v_result, ' event: false,' || v_lf); dbms_lob.append(v_result, ' inactive: 2000' || v_lf); dbms_lob.append(v_result, ' },' || v_lf); dbms_lob.append(v_result, ' style: {' || v_lf); dbms_lob.append(v_result, ' classes: "ui-tooltip-shadow ui-tooltip-youtube",' || v_lf); dbms_lob.append(v_result, ' tip:' || v_lf); dbms_lob.append(v_result, ' {' || v_lf); dbms_lob.append(v_result, ' corner: true,' || v_lf); dbms_lob.append(v_result, ' width: 24, // resize the caret' || v_lf); dbms_lob.append(v_result, ' height: 24 // resize the caret' || v_lf); dbms_lob.append(v_result, ' }' || v_lf); dbms_lob.append(v_result, ' }' || v_lf); dbms_lob.append(v_result, ' })' || v_lf); dbms_lob.append(v_result, ' });' || v_lf); */ -- close // on dom ready -- dbms_lob.append(v_result, ' }); // on dom ready' || v_lf); dbms_lob.append(v_result, ' </script>' || v_lf); -- only return a result if it is not empty if v_c1_count > 0 then return v_result; else return null; end if; end cytoscape; end ted_cytoscape;