As of December 1, 2020, Focal Point is retired and repurposed as a reference repository. We value the wealth of knowledge that's been shared here over the years. You'll continue to have access to this treasure trove of knowledge, for search purposes only.
Join the TIBCO Community TIBCO Community is a collaborative space for users to share knowledge and support one another in making the best use of TIBCO products and services. There are several TIBCO WebFOCUS resources in the community.
From the Home page, select Predict: WebFOCUS to view articles, questions, and trending articles.
Select Products from the top navigation bar, scroll, and then select the TIBCO WebFOCUS product page to view product overview, articles, and discussions.
Request access to the private WebFOCUS User Group (login required) to network with fellow members.
Former myibi community members should have received an email on 8/3/22 to activate their user accounts to join the community. Check your Spam folder for the email. Please get in touch with us at community@tibco.com for further assistance. Reference the community FAQ to learn more about the community.
We currently have a HTML page we developed for a Self Service Guided Report. We have quite a few parameters that we have split up in a Tab Panel amongst multiple tabs.
When this page loads it loads for every tab on the page not just the tab that is showing at the time. What we feel would work is have the page open and load only what is shown and then when you click on each tab, that is when the values load for the parameters on that particular tab(page).
I have worked with IBI and no one can come up with a solution to have the page NOT load all at once. I talked with our .net developer and he mentioned Lazy Loading as an option maybe? Anyone have any idea how to implement this type of option using App Studio and HTML Page. We are unsuccessful on figuring it out through the GUI. I am sure it may be able to be done through Java Script and JQuery etc.. but I am not an expert in those areas.
Any help or suggestions would be much appreciated.This message has been edited. Last edited by: <Emily McAllister>,
So is the loading time for all those parameters not acceptable? How long does it take to populate the parameter controls?
It may be possible to tweak your data source so that the loading time improves. I created a Self Service Guided Report a year ago and it has 30 parameters; the load time is only a few seconds.
Do some of your controls load large amounts of data? For example, if you are developing for an automotive supplier you could create a control that loads thousands of part numbers. I can see how that could slow things down.
App Studio WebFOCUS 8.1.05M Windows, All Outputs
Posts: 594 | Location: Michigan | Registered: September 04, 2015
Lazy loading is what you might see in a web page with loads of images (most common implementation?) where, as you scroll down, the images coming into view are loaded and displayed.
When you develop via the GUI and introduce "Requests and Data Sources" you are essentially offloading the pre-processing to WebFOCUS load processes. This means, as you have found, that all the requests used to populate the controls are triggered on initial page load - even for multiple tabbed documents.
What you could do is to remove those processes and write some jQuery ajax processes that make those calls and load the control when necessary, say on focus of the tab in question?
I would add that I've not done this but, providing you can capture the tab focus event, it should be possible to trigger the population processes as necessary.
Good luck
T
In FOCUS since 1986
WebFOCUS Server 8.2.01M, thru 8.2.07 on Windows Svr 2008 R2
WebFOCUS App Studio 8.2.06 standalone on Windows 10
Posts: 5694 | Location: United Kingdom | Registered: April 08, 2004
Building on what Tony said, here's some JavaScript code I developed to detect when a tab has been clicked on:
if(typeof(bRuntime) != 'undefined') {
// TODO: Add your inline runtime code here
}
//Begin function window_onload
function window_onload() {
UpdateData();
// * * * Listen for mouse clicks * * *
// Tabs are named "Tab 1" and "Tab 2"
document.addEventListener('click', function(e) {
// Get event object for IE or non-IE browsers
e = e || window.event;
var target = e.target || e.srcElement;
// Get contents of HTML element that was clicked on
var text = target.textContent || text.innerText;
// Make AJAX call if tab has been clicked on
switch(text) {
case "Tab 1": // *** AJAX code to populate controls goes here ***
break;
case "Tab 2": // *** AJAX code to populate controls goes here ***
break;
}
}, false);
}
This sets up a JavaScript click event that will execute for every click on the HTML page. In App Studio, you can change the name of each tab. I created two tabs named "Tab 1" and "Tab 2". The tab names are just text inside an HTML DIV tag. The code above retrieves any text inside whatever was clicked on and checks to see if the text is "Tab 1" or "Tab 2".
If "Tab 1" or "Tab 2" text is found inside the DIV that was clicked on, AJAX code can then trigger the population process, as Tony has suggested.
App Studio WebFOCUS 8.1.05M Windows, All Outputs
Posts: 594 | Location: Michigan | Registered: September 04, 2015
Thanks for the suggestion. I have taken your Javascript code and added to my HTML page, however it still seems to be loading everything n the initial load.
Not sure on what I am missing in the steps. I did change my Tab names to match what is in the code. I copied your code and pasted in the JavaScript area and replaced what was currently there.
Is there another piece I need to do to make this happen?
You would need to place code where it is marked "AJAX code to populate controls goes here".
Perhaps Tony can help you out with that. My App Studio broke so I can't work up an example right now. For some reason I cannot see any files under the Content area; I know they exist because I can see them in the WebFOCUS portal page.
App Studio WebFOCUS 8.1.05M Windows, All Outputs
Posts: 594 | Location: Michigan | Registered: September 04, 2015
Create a new HTML file in App Studio. Name it "wf_forum_populate_tab_controls.htm".
Create a new tab window with two tabs. Go to the Properties panel for each tab and change the corresponding "Selected Page: Title" property to either "Tab 1" or "Tab 2".
In "Tab 1", create two Drop Down controls. Give them Unique Identifier names in the Property panel. Make them "combobox1" and "combobox2".
In "Tab 2", create a List Box. Make its Unique Identifier name "listbox1".
Create the following three FEX files:
File: wf_forum_populate_tab_controls_country.fex
TABLE FILE ibisamp/car
BY CAR.ORIGIN.COUNTRY
ON TABLE PCHOLD FORMAT XML
-RUN
File: wf_forum_populate_tab_controls_car.fex
TABLE FILE ibisamp/car
BY CAR.COMP.CAR
ON TABLE PCHOLD FORMAT XML
-RUN
File: wf_forum_populate_tab_controls_model.fex
TABLE FILE ibisamp/car
BY CAR.CARREC.MODEL
ON TABLE PCHOLD FORMAT XML
-RUN
These FEX files will produce XML output, which will be used to populate the tab controls.
In the JavaScript code below, change the "url:" line in each AJAX call to point to where you saved the FEX files. The "IBFS_path" you see is my test working directory in WebFOCUS. It won't work for you the way it is.
Replace the code in App Studio's "Embedded JavaScript/CSS" tab with the following:
if(typeof(bRuntime) != 'undefined') {
// TODO: Add your inline runtime code here
}
//Begin function window_onload
function window_onload() {
UpdateData();
// Default is "Tab 1", so populate its controls immediately
populate_country();
populate_car();
tab_1_loaded = true;
// * * * Listen for mouse clicks * * *
// Tabs are named "Tab 1" and "Tab 2"
document.addEventListener('click', function(e) {
// Get event object for IE or non-IE browsers
e = e || window.event;
var target = e.target || e.srcElement;
// Get contents of HTML element that was clicked on
var text = target.textContent || text.innerText;
// Make AJAX call if tab has been clicked on.
// Global variables below will record whether the control is already loaded or not
switch(text) {
case "Tab 1": if (!tab_1_loaded) {
populate_country();
populate_car();
tab_1_loaded = true;
}
break;
case "Tab 2": if (!tab_2_loaded) {
populate_model();
tab_2_loaded = true;
}
break;
}
}, false);
}
//End function window_onload
// Global variables to make sure controls are only populated one time
var tab_1_loaded = false;
var tab_2_loaded = false;
function populate_country() {
// Use jQuery to make the AJAX call and populate the Country control
$.ajax({
type: "GET",
url: "/ibi_apps/WFServlet.ibfs?IBFS1_action=RUNFEX&IBFS_path=/WFC/Repository/BIDEV/~sharpet/wf_forum_populate_tab_controls_country.fex",
cache: false,
dataType: "xml",
error: function(jqXHR, textStatus, errorThrown) {
alert(textStatus + ": " + errorThrown);
},
success: function(xml) {
$(xml).find("tr").each(function(index){
$(this).find("td").each(function(index) {
var name = $(this).text();
switch(index) {
case 0: $("select[id=combobox1]").append("<option value=\"" + name + "\">" + name);
break;
}
});
});
}
});
}
function populate_car() {
// Use jQuery to make the AJAX call and populate the Car control
$.ajax({
type: "GET",
url: "/ibi_apps/WFServlet.ibfs?IBFS1_action=RUNFEX&IBFS_path=/WFC/Repository/BIDEV/~sharpet/wf_forum_populate_tab_controls_car.fex",
cache: false,
dataType: "xml",
error: function(jqXHR, textStatus, errorThrown) {
alert(textStatus + ": " + errorThrown);
},
success: function(xml) {
$(xml).find("tr").each(function(index){
$(this).find("td").each(function(index) {
var name = $(this).text();
switch(index) {
case 0: $("select[id=combobox2]").append("<option value=\"" + name + "\">" + name);
break;
}
});
});
}
});
}
function populate_model() {
// Use jQuery to make the AJAX call and populate the Model control
$.ajax({
type: "GET",
url: "/ibi_apps/WFServlet.ibfs?IBFS1_action=RUNFEX&IBFS_path=/WFC/Repository/BIDEV/~sharpet/wf_forum_populate_tab_controls_model.fex",
cache: false,
dataType: "xml",
error: function(jqXHR, textStatus, errorThrown) {
alert(textStatus + ": " + errorThrown);
},
success: function(xml) {
$(xml).find("tr").each(function(index){
$(this).find("td").each(function(index) {
var name = $(this).text();
switch(index) {
case 0: $("select[id=listbox1]").append("<option value=\"" + name + "\">" + name);
break;
}
});
});
}
});
}
"Tab 1" should be the default tab. It needs to populate its controls immediately. "Tab 2" will not populate its control until "Tab 2" has been clicked on.
The global variables ensure that each tab only populates its control(s) one time.
App Studio WebFOCUS 8.1.05M Windows, All Outputs
Posts: 594 | Location: Michigan | Registered: September 04, 2015
This is great information. I was able to produce your sample, however I need this to go one more step.
On each of my tabs I have some parameters with chaining options. How do I incorporate the same fex file to populate the controls and give the specific field needed to populate the controls.
From what I can tell on this I am only allowed to have one field per fex file which would not allow chaining to happen. Right?
You can have more than one field per FEX file, but I don't think you need to.
Add a third drop down control to Tab 1 and call it "combobox3". We will add body type from the CAR sample file to this control.
Create a FEX file called "wf_forum_populate_tab_controls_bodytype.fex". Put the following code in it:
TABLE FILE ibisamp/car
BY CAR.BODY.BODYTYPE
WHERE CAR.COMP.CAR EQ '&CAR';
ON TABLE PCHOLD FORMAT XML
-RUN
To chain all three controls together, we need to retrieve data for controls 2 & 3 from controls 1 & 2, respectively. To do that we need to add amper variables to the FEX files that load data into controls 2 & 3. The code above handles control #3 (body type), but control #2 (car) is dependent on control #1 (country), so we need to change FEX file "wf_forum_populate_tab_controls_car.fex".
Here is the code for that:
TABLE FILE ibisamp/car
BY CAR.COMP.CAR
WHERE CAR.ORIGIN.COUNTRY EQ '&COUNTRY';
ON TABLE PCHOLD FORMAT XML
-RUN
When the JavaScript code runs, it will load Tab 1 and chain it properly. But whenever the user changes control #1 or control #2, we need to be notified about it so we can refresh the control chain. That is done by creating two event functions. To do that, click on control #1, then go to the Properties panel. Click the yellow lightning bolt to see the events available for the control.
For the "Value Changed" event, type in "combobox1_onchange". Now click on control #2 and type in "combobox2_onchange" for its "Value Changed" event.
I've left comments in the code to explain the rest.
if(typeof(bRuntime) != 'undefined') {
// TODO: Add your inline runtime code here
}
//Begin function window_onload
function window_onload() {
UpdateData();
// * * * Listen for mouse clicks * * *
// Tabs are named "Tab 1" and "Tab 2"
document.addEventListener('click', function(e) {
// Get event object for IE or non-IE browsers
e = e || window.event;
var target = e.target || e.srcElement;
// Get contents of HTML element that was clicked on
var text = target.textContent || text.innerText;
// Remove any trailing carriage return and/or line feed from string
text = text.replace(/\n$/, "");
// Make AJAX call if tab has been clicked on.
switch(text) {
case "Tab 1": if (!tab_1_loaded) {
populate_country();
populate_car();
populate_bodytype();
tab_1_loaded = true;
}
break;
case "Tab 2": if (!tab_2_loaded) {
populate_model();
tab_2_loaded = true;
}
break;
}
}, false);
// *** CHAINING CONTROLS on Tab 1 ***
// Default is "Tab 1", so populate the first control only.
// The second control will populate after the first has finished loading,
// and the third after the second is done. This is done inside the AJAX calls.
populate_country();
}
//End function window_onload
// Global variables to make sure controls are only populated one time
var tab_1_loaded = false;
var tab_2_loaded = false;
function populate_country() {
// Use jQuery to make the AJAX call and populate the Country control
$.ajax({
type: "GET",
url: "/ibi_apps/WFServlet.ibfs?IBFS1_action=RUNFEX&IBFS_path=/WFC/Repository/BIDEV/~sharpet/wf_forum_populate_tab_controls_country.fex",
cache: false,
dataType: "xml",
error: function(jqXHR, textStatus, errorThrown) {
alert(textStatus + ": " + errorThrown);
},
success: function(xml) {
// Remove all selections from control
$("#combobox1").empty();
// Load new selections into control
$(xml).find("tr").each(function(index){
$(this).find("td").each(function(index) {
var name = $(this).text();
switch(index) {
case 0: $("select[id=combobox1]").append("<option value=\"" + name + "\">" + name);
break;
}
});
});
// Country control has loaded, now populate Car control
populate_car();
}
});
}
function populate_car() {
// Use IBI function to retrieve user-selected Country
var country = IbComposer_getCurrentSelection("combobox1");
// Use jQuery to make the AJAX call and populate the Car control
$.ajax({
type: "GET",
url: "/ibi_apps/WFServlet.ibfs?IBFS1_action=RUNFEX&IBFS_path=/WFC/Repository/BIDEV/~sharpet/wf_forum_populate_tab_controls_car.fex&COUNTRY=" + country,
cache: false,
dataType: "xml",
error: function(jqXHR, textStatus, errorThrown) {
alert(textStatus + ": " + errorThrown);
},
success: function(xml) {
// Remove all selections from control
$("#combobox2").empty();
// Load new selections into control
$(xml).find("tr").each(function(index){
$(this).find("td").each(function(index) {
var name = $(this).text();
switch(index) {
case 0: $("select[id=combobox2]").append("<option value=\"" + name + "\">" + name);
break;
}
});
});
// Car control has loaded, now populate Bodytype control
populate_bodytype();
}
});
}
function populate_bodytype() {
// Use IBI function to retrieve user-selected Car
var car = IbComposer_getCurrentSelection("combobox2");
// Use jQuery to make the AJAX call and populate the Model control
$.ajax({
type: "GET",
url: "/ibi_apps/WFServlet.ibfs?IBFS1_action=RUNFEX&IBFS_path=/WFC/Repository/BIDEV/~sharpet/wf_forum_populate_tab_controls_bodytype.fex&CAR=" + car,
cache: false,
dataType: "xml",
error: function(jqXHR, textStatus, errorThrown) {
alert(textStatus + ": " + errorThrown);
},
success: function(xml) {
// Remove all selections from control
$("#combobox3").empty();
// Load new selections into control
$(xml).find("tr").each(function(index){
$(this).find("td").each(function(index) {
var name = $(this).text();
switch(index) {
case 0: $("select[id=combobox3]").append("<option value=\"" + name + "\">" + name);
break;
}
});
});
// Bodytype control has loaded, set flag indicating tab 1 has finished loading.
tab_1_loaded = true;
}
});
}
function populate_model() {
// Use jQuery to make the AJAX call and populate the Model control on Tab 2
$.ajax({
type: "GET",
url: "/ibi_apps/WFServlet.ibfs?IBFS1_action=RUNFEX&IBFS_path=/WFC/Repository/BIDEV/~sharpet/wf_forum_populate_tab_controls_model.fex",
cache: false,
dataType: "xml",
error: function(jqXHR, textStatus, errorThrown) {
alert(textStatus + ": " + errorThrown);
},
success: function(xml) {
$(xml).find("tr").each(function(index){
$(this).find("td").each(function(index) {
var name = $(this).text();
switch(index) {
case 0: $("select[id=listbox1]").append("<option value=\"" + name + "\">" + name);
break;
}
});
});
}
});
}
//Begin function combobox1_onchange (Country control has been changed by the user)
function combobox1_onchange(event) {
// The populate_car function will call on the populate_bodytype function
populate_car();
}
//Begin function combobox2_onchange (Car control has been changed by the user)
function combobox2_onchange(event) {
populate_bodytype();
}
App Studio WebFOCUS 8.1.05M Windows, All Outputs
Posts: 594 | Location: Michigan | Registered: September 04, 2015
This is coming along great with the information you have provided. I have a couple of more things to incorporate. Can you help?
1. When passing parameters for chaining, I will need to send multiple parameters as they go through the chaining to get the appropriate selection in each list. Example: When you send just &CAR to the BODYTYPE list won't it only just send what was in the CAR option, shouldn't it also be sending &COUNTRY as well? I get if we do this I would have to add the parameter to the fex files, but how do I add it in the JQuery/Jscript code?
2. How do we pass and include options to select more than one parameters. When I selected 'Multiple' on the control it did not work with this code. The way that this seems to be coded now it will only allow one option to select in each dropdown??
3. How do we pass 'All' so when the page first loads it loads all options for each dropdown. Then it needs to include the chaining option for each. For example, they may not want to filter Country but want to start filtering on Car.
Hope I explained these well. Any additional help would be greatly appreciated. We are truly grateful already to get to the point we are at with your information.
1. Yes, my example was too simplified. For body type you would add &COUNTRY to the FEX and modify the URL in body type's AJAX call like this:
function populate_bodytype() {
// Use IBI function to retrieve user-selected Car
var country = IbComposer_getCurrentSelection("combobox1");
var car = IbComposer_getCurrentSelection("combobox2");
// Use jQuery to make the AJAX call and populate the Model control
$.ajax({
type: "GET",
url: "/ibi_apps/WFServlet.ibfs?IBFS1_action=RUNFEX&IBFS_path=/WFC/Repository/BIDEV/~sharpet/wf_forum_populate_tab_controls_bodytype.fex&CAR=" + car + "&COUNTRY=" + country,
2. So if I'm understanding you correctly, you want to be able to, say, select both ENGLAND and FRANCE for country and have ENGLAND and FRANCE cars populate the car control?
3. This question is related to point #2 above.
App Studio WebFOCUS 8.1.05M Windows, All Outputs
Posts: 594 | Location: Michigan | Registered: September 04, 2015
TABLE FILE ibisamp/car
BY CAR.BODY.BODYTYPE
WHERE CAR.COMP.CAR EQ '&CAR';
WHERE CAR.ORIGIN.COUNTRY EQ '&COUNTRY';
ON TABLE PCHOLD FORMAT XML
-RUN
Updated JavaScript:
if(typeof(bRuntime) != 'undefined') {
// TODO: Add your inline runtime code here
}
//Begin function window_onload
function window_onload() {
UpdateData();
// * * * Listen for mouse clicks * * *
// Tabs are named "Tab 1" and "Tab 2"
document.addEventListener('click', function(e) {
// Get event object for IE or non-IE browsers
e = e || window.event;
var target = e.target || e.srcElement;
// Get contents of HTML element that was clicked on
var text = target.textContent || text.innerText;
// Remove any trailing carriage return and/or line feed from string
//text = text.replace(/\n$/, "");
text = text.trim("\r");
// Make AJAX call if tab has been clicked on.
switch(text) {
case "Tab 1": if (!tab_1_loaded) {
populate_country();
tab_1_loaded = true;
}
break;
case "Tab 2": if (!tab_2_loaded) {
populate_model();
tab_2_loaded = true;
}
break;
}
}, false);
// *** CHAINING CONTROLS on Tab 1 ***
// Default is "Tab 1", so populate the first control only.
// The second control will populate after the first has finished loading,
// and the third after the second is done. This is done inside the AJAX calls.
populate_country();
}
//End function window_onload
// Global variables to make sure controls are only populated one time
var tab_1_loaded = false;
var tab_2_loaded = false;
var page_loaded = false;
function populate_country() {
// Use jQuery to make the AJAX call and populate the Country control
$.ajax({
type: "GET",
url: "/ibi_apps/WFServlet.ibfs?IBFS1_action=RUNFEX&IBFS_path=/WFC/Repository/BIDEV/~sharpet/wf_forum_populate_tab_controls_country.fex",
cache: false,
dataType: "xml",
error: function(jqXHR, textStatus, errorThrown) {
alert(textStatus + ": " + errorThrown);
},
success: function(xml) {
// Remove all selections from control
$("#combobox1").empty();
// Load new selections into control
$(xml).find("tr").each(function(index){
$(this).find("td").each(function(index) {
var name = $(this).text();
switch(index) {
case 0: $("select[id=combobox1]").append("<option value=\"" + name + "\">" + name);
break;
}
});
});
// Country control has loaded, now populate Car control
populate_car();
}
});
}
function populate_car() {
// Use IBI function to retrieve user-selected Country
var country = IbComposer_getCurrentSelection("combobox1");
if (!page_loaded) {
country = "_FOC_NULL";
}
// Use jQuery to make the AJAX call and populate the Car control
$.ajax({
type: "GET",
url: "/ibi_apps/WFServlet.ibfs?IBFS1_action=RUNFEX&IBFS_path=/WFC/Repository/BIDEV/~sharpet/wf_forum_populate_tab_controls_car.fex&COUNTRY=" + country,
cache: false,
dataType: "xml",
error: function(jqXHR, textStatus, errorThrown) {
alert(textStatus + ": " + errorThrown);
},
success: function(xml) {
// Remove all selections from control
$("#combobox2").empty();
// Load new selections into control
$(xml).find("tr").each(function(index){
$(this).find("td").each(function(index) {
var name = $(this).text();
switch(index) {
case 0: $("select[id=combobox2]").append("<option value=\"" + name + "\">" + name);
break;
}
});
});
// Car control has loaded, now populate Bodytype control
populate_bodytype();
}
});
}
function populate_bodytype() {
// Use IBI function to retrieve user-selected Car
var country = IbComposer_getCurrentSelection("combobox1");
var car = IbComposer_getCurrentSelection("combobox2");
if (!page_loaded) {
country = "_FOC_NULL";
car = "_FOC_NULL";
}
// Use jQuery to make the AJAX call and populate the Model control
$.ajax({
type: "GET",
url: "/ibi_apps/WFServlet.ibfs?IBFS1_action=RUNFEX&IBFS_path=/WFC/Repository/BIDEV/~sharpet/wf_forum_populate_tab_controls_bodytype.fex&CAR=" + car + "&COUNTRY=" + country,
cache: false,
dataType: "xml",
error: function(jqXHR, textStatus, errorThrown) {
alert(textStatus + ": " + errorThrown);
},
success: function(xml) {
// Remove all selections from control
$("#combobox3").empty();
// Load new selections into control
$(xml).find("tr").each(function(index){
$(this).find("td").each(function(index) {
var name = $(this).text();
switch(index) {
case 0: $("select[id=combobox3]").append("<option value=\"" + name + "\">" + name);
break;
}
});
});
// Bodytype control has loaded, set flag indicating tab 1 has finished loading.
tab_1_loaded = true;
page_loaded = true;
}
});
}
function populate_model() {
// Use jQuery to make the AJAX call and populate the Model control on Tab 2
$.ajax({
type: "GET",
url: "/ibi_apps/WFServlet.ibfs?IBFS1_action=RUNFEX&IBFS_path=/WFC/Repository/BIDEV/~sharpet/wf_forum_populate_tab_controls_model.fex",
cache: false,
dataType: "xml",
error: function(jqXHR, textStatus, errorThrown) {
alert(textStatus + ": " + errorThrown);
},
success: function(xml) {
$(xml).find("tr").each(function(index){
$(this).find("td").each(function(index) {
var name = $(this).text();
switch(index) {
case 0: $("select[id=listbox1]").append("<option value=\"" + name + "\">" + name);
break;
}
});
});
}
});
}
//Begin function combobox1_onchange (Country control has been changed by the user)
function combobox1_onchange(event) {
// The populate_car function will call on the populate_bodytype function
populate_car();
}
//Begin function combobox2_onchange (Car control has been changed by the user)
function combobox2_onchange(event) {
populate_bodytype();
}
App Studio WebFOCUS 8.1.05M Windows, All Outputs
Posts: 594 | Location: Michigan | Registered: September 04, 2015
I got your code in and it will bring up the choices in each list now, however for combobox2 and combobox3 it does not have an 'ALL' option like it is showing for combobox1.
When it comes to being able to do multiple options can I just change the parameter to an 'AND' or 'OR' in the fex file, or do we have to add JQuery/Jscript code as well to account for it?
My example was meant to show how you could delay populating a control on a second tab. It sounds like what you are trying to do is much more than that.
Are all these parameters populating dynamically from a data source? Could any of these be static with the values keyed in manually in App Studio? That might help with the load time.
Multiple choices in user controls can be handled easily using App Studio's tool set. Trying to handle this in JavaScript/jQuery is not an easy thing to do.
App Studio WebFOCUS 8.1.05M Windows, All Outputs
Posts: 594 | Location: Michigan | Registered: September 04, 2015
It seems like we are on the right track. Our main purpose is to delay the load for each tab but unfortunately we also need other functionality to be available:
1. Multiple select option (I know how to incorporate using App Studio, however with the JavaScript/jQuery code we are adding, I was not sure if it would break the functionality or anything)
2. Load all dropdowns in a tab with all the dynamic values (Including an 'All' option)
3. Chaining
You have already gotten us further than IBI could in a short amount of time and without charging a large price. Do you still think we are headed down the right path to make this all happen even though it can be harder to handle in JavaScript/jQuery?
Originally posted by Kristi Carter: Yes the chaining works great using App Studio. Our only issue is everything loading all at once.
Thanks, Kristi
Then I would recommend that you try to speed up your data source, if speed is the problem. I'm assuming it is a database. There are tweaks that can sometimes be made that can result in faster data retrieval times.
Another option would be to create static controls. The values would then be part of the HTML page itself, which should speed things up (I actually do this for part of the Self Service Guided report I created a year ago). This is probably not an option if the data that goes into the controls changes frequently.
If App Studio's chaining works well for you, I would not sacrifice using it to get the controls on each tab to load separately. I would try to find a way to speed up the data source(s).
App Studio WebFOCUS 8.1.05M Windows, All Outputs
Posts: 594 | Location: Michigan | Registered: September 04, 2015
Thanks for the advice. We have actually been that route already and have limited some options and we have it the fast as it can get. Which is pretty quick when you run the fex files used to populate the controls.
However when it tries to load (Dealer information for example) it could have up to 500 + records to populate on a tab. We were hoping we could go one step further and then split each tab up to load as they click on them to make it even better instead of waiting in the initial run.
We are starting with a smaller data set, but we are also working on a larger sample where on each tab there can be about 10 parameters to populate in each tab. So this option would really help on that one since currently without this option it takes about 1.5 minutes to open and load initially.
Are you sure this is a data amount issue? That's an awfully long time to load up, even with controls having 500+ records.
You could try running this in Google Chrome and hitting the F12 key to open up the browser's developer tools. In the "Console" section there may be errors highlighted in red.
Also, if you have a networking person handy, they could run a program called "Wireshark" on your machine to watch the network traffic. It almost sounds to me like something is stalling.
App Studio WebFOCUS 8.1.05M Windows, All Outputs
Posts: 594 | Location: Michigan | Registered: September 04, 2015
We have done the F12 in Google Chrome in the beginning and found that each tab took time to load, then to load all at once was the issue.
We then chopped off quite a few parameters and it got better. I just ran again using F12 and what is crazy is it is down to less than 30 seconds to load.
the two thing we have done to our test environment where this resides today since I last ran it was we Upgraded to 8105M with the July version and we also upgraded our Oracle to 12c. I don't know if any of that has anything to do with the performance or not, but that is the difference.
So we are now back to feeling better about what we have but it is not perfect.
The concern I have is if they need us to put some of the parameter options back and we end up back in this same spot trying to come up with a way to load the page differently.
Also - I did run the F12 and I am not getting any red errors in the console area. I am really getting two message. One that goes over and over again.
'//@ sourceURL' and '//@ sourceMappingURL' are deprecated, please use '//# sourceURL=' and '//# sourceMappingURL=' instead.
Then this message is in the list once: Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience. For more help, check https://xhr.spec.whatwg.org/.
At my previous job, I worked with Oracle 10g a lot. There was an issue sometimes linking a very large table of records to a very small table. Oracle would optimize the query in the worst possible way, and the result would be that the query would run slowly. The solution was to set a session variable to tell it to optimize the way it did in Oracle 9i.
If you know SQL and you are set up to access Oracle 12c directly, you could try writing SQL queries to simulate what WebFOCUS is doing when it populates the controls. You could start with the parameters you removed, since they seem to be taking a lot of time.
App Studio WebFOCUS 8.1.05M Windows, All Outputs
Posts: 594 | Location: Michigan | Registered: September 04, 2015
We have definitely done everything we can at the SQL level to make each list run quickly.
We are still to the point where we would like to be able to load the page and just the tabs showing only, but of course we need to be able to accommodate all the pieces.
I'm guessing you're not in the mood to completely rewrite your application, but here are a couple items to think about:
1) Have you considered using ReportCaster for your data captures? Using ReportCaster you can pre-execute your SQL and store the results in hold files for future use. At runtime, accessing a hold file is going to be much faster than executing the SQL.
2) Rather than building a tab driven HTML page, consider building each tab as it's own HTML page, and reference each page using the Portal. The portal by default will only load each tab when selected, and you can style the tab/menu bar to your liking using CSS. You can then use this JavaScript function to pass your parameters to all tabs of your portal.
function refreshReports(){
var name = this.window.name;
parent.BipIframeInterface.setAllAmpersValues(name, IbComposer_getAllAmpersValues());
parent.BipIframeInterface.refresh(parent.BipIframeInterface.REFRESH_ALL_BUT_SELF , name);
}
Thanks for the information Joel. This is actually another route we were wanting to try but I was unsure how to get the parameters passed from each page and IBI did not supply me with how to accomplish this.
I have set up a sample using the car data. I have two pages in a portal. the first page has three parameters, the second has the fourth parameter and the run button to run the report.
Based on your logic for the function, I assume I would need to put this on the HTML for page 1 and HTML for page 2. Is that correct?
I am not an expert in this type of code. So I have some silly questions. So within your code you show for a sample which pieces do I populate with specific names. for example:
var name - what piece is the 'name' to be? The parameter name, page name or ????
You don't need change anything within the JavaScript I provided, it should work exactly as is. This bit of code will force a "refresh" of any tab within your portal. Any matching parameter on tab1 will be refreshed/passed to any tab with the SAME parameter name.
In answering your question about the parameters, yes, any parameter you want passed back and forth will need to be on each HTML page. After you're done with development they can be hidden if you'd like.
HTML1: * Include your 3 parameters within the page * Copy/Paste the JavaScript function above into the embedded JavaScript section * Create a new Task/Animation that will trigger the JavaScript function. e.g. a Button
HTML2: * Include your 3 parameters from HTML1 within the page. The 4th parameter you mentioned will not get refreshed, since it doesn't exist on HTML1 * (optional) Include the same JavaScript function above and Task/Animation if you want parameters passed from HTML2 back to HTML1. If you only want parameters passed from HTML1 to HTML2 and not the other way around, then skip this step.
Originally posted by Kristi Carter: . . . I have worked with IBI and no one can come up with a solution to have the page NOT load all at once. . . . Any help or suggestions would be much appreciated.
and later in the thread:
Thanks for the suggestion. I have taken your Javascript code and added to my HTML page, however it still seems to be loading everything n the initial load.
You could give the fex'es that load the values for the controls of the other tabs two modes of operation. When &MODE EQ 1, they return their normal output; when 0, they return just a place holder value (e.g., Please wait...).
Add MODE as a hidden text control in each tab, initially set to 0; and chain all controls to it. Thus, they will initially load quick-as-a-wink.
Whenever a tab is selected, have that trigger a JS function in the tab, to test its MODE, and (if 0) toggle it to 1 and trigger refreshes cascading from MODE. Thus each tab's controls get populated "for real" only when the tab is first opened.This message has been edited. Last edited by: j.gross,
- Jack Gross WF through 8.1.05
Posts: 1925 | Location: NYC | In FOCUS since 1983 | Registered: January 11, 2005