Category: Interview

JavaScript Custom Image Extension

One of the regular readers of this website was very excited to see that recently, the Custom Extensions were updated to include a Custom Image Extension. Whilst at first glance you might not think it would need much of an extension, or maybe you cannot think of a requirement, there have been many situations where the logic of dynamic images, dynamic sizing, and so forth could not be done with a styling extension or a bit of CSS.

So what is available in this type of extension? In a Custom Image Extension, you can leverage the following Control Methods to customize your image.

getWidth()The width of the control (not just for image controls)
getHeight()The height of the control
getImageSource()The URL representing the source of the image
getLinkUrl()The URL used if the image is clicked
openLinkInNewWindow()Will the link open in a new Window?
getHorizontalAlignment()The alignment of the image
getCaption()The text caption of the image

For a quick demonstration, the following project will create a dynamic QR code according to your chosen URL. The image can resized on the fly using the sliders, and you can set the URL and whether it will open in another window:

The Custom Image Extension will generate a QR code and the user can manipulate the size of the image to see it changing dynamically. You could even then put the dynamic image in your Forms. Or use it to send a link to someone for a GetCheckPoint. Lots of ideas!

Creating a QR Code

There are lots of applications where the ability work with a Custom Image Extension will maker life easier. There is a good example in the Example Projects – it’s called Health Diagnosis and check out the diagnosis page with the dynamic image. The example project contains the JavaScript for the Custom Image Extension in the usual folder.

You can get the example Zip file from the OPA Hub Shop.

JSON Extension File

JSON Extension File

As many, but not all readers are probably aware, the Oracle Policy Automation JavaScript API is restricted in terms of what data it can manipulate in code. The default position is simple. If you plan on working with (accessing, updating or whatever is appropriate given the nature of the data and the type of attribute or entity instance) information from the Data tab of Oracle Policy Modeling then it must be present on the Screen that contains your Extension.

Here is a simple example to illustrate. Suppose you have a project that infers a list of Metro Stations. These stations are inferred in some way by Excel or Word rules. You wish to use a drop-down to allow the user to select one of those stations.

You decide to use the much-downloaded educational example called  Dynamic Options from Instances which you found in the OPA Hub Shop. So far so good. You look at the example Project and you see this:

JSON Extension File - Before

Cool. It’s a demonstration of a dynamic options list (at the bottom) driven by the entity instances (at the top). And the console shows some cool output to highlight the construction of the list. On the left, you can see that the interview is made up of two Screens. Excellent. Then you decide to split the interview into three Screens – separating the Instances from the Selection. Sounds really cool and a better layout. Now you see this in the Debugger:

JSON Extension FileWhich I think you will agree, is sub-optimal. Our extension just fails miserably. But now, it’s opm.extension.data.json to the rescue. We create this file in the resources folder and populate it according to our needs. In this case, we add – and this is required for any entity attributes – the relationship name (the technical name, not the textual name) and then we declare any attributes we want. So our file looks like this:

JSON Extension File Example

We re-debug and everything is back to normal. Re-cool. Obviously we should avoid putting too many elements in there – especially parent – child relationships which can result in masses of JSON being generated by Oracle Policy Automation and made available to your JavaScript, potentially creating performance bottlenecks. But for our little example, it’s perfect.

Importing Data into an Interview : Excel Example

Importing Data into an Interview : Excel Example

Readers will remember a while ago I explained briefly how to use Microsoft Excel to act as a Connection Datasource – in this overview article, followed by this one in a little more detail. Now we look at another challenge : Importing Data into an Interview.

Well, here comes another example of the ubiquitous nature of Microsoft Excel. The customer requirement was as follows:

Using a simple mechanism, let the user upload an existing Excel spreadsheet into the Interview. Parse the spreadsheet, read the data in it, create corresponding rows in an Entity. Let the user review the data but do not require any new data entry. There may be up to 250 rows of data to import. So how do you go about about Importing Data into an Interview?

So how can we face up to a challenge like that? We need:

  • An upload that isn’t a standard File Upload Group
  • A parsing mechanism to read Excel and extract the data in a given tab, or wherever
  • A custom Entity Collect to handle the data import / create the rows in a Screen

The shopping list above isn’t that long.

The File Upload is essentially an HTML 5 component to let the user select a file on their computer. We cannot access an arbitrary local path from JavaScript, so we need the user to point to the file they want to upload.

There are a number of JavaScript-based Excel parsers, including the excellent SheetJS js-xlsx which we used. It is capable of converting to and from Excel, which is no easy task when you consider that an Excel file is basically a Zip file with a bunch of complicated stuff inside it. The library can convert to HTML, CSV and magically (for our requirement) JSON. Awesome!

Plus, in a previous post we’ve also looked at the (large amount of) work required to build a Custom Entity Collect Extension. In fact when I was writing that article I was thinking, for goodness sake Richard, when do you think you will actually need to go to the trouble of building that Entity Collect Extension? Well, I’ve finally found a use for it – Importing Data into an Interview!

We need an Entity Collect Extension since we need some way of getting the Excel data into the Entity Collect, which ultimately means we need to do some work behind the scenes between the import of the data and the display of the Entity Collect. We need to rewire the Entity Collect temporarily so that it sucks our Excel data up, before we show it to the user so they can examine the results.

For the purposes of a raw demo, I unplugged all the other functionality (delete buttons, add buttons, etc.) and just concentrated on getting the data into the Entity Collect. There are how ever a few caveats. Once you get into the larger imports, at least in the Debugger, you can expect to see “concurrent record editing” errors. I’m trying to find out what the limit is exactly. But up to a few hundred I think it’s OK.

So let’s look at the items in turn.

File Upload and Data Load

{
					//console.log("Starting customInput Mount");
					var div = document.createElement("input");
					div.id = "myFile";
					div.type = "File";
					//div.value = control.getValue();
					el.appendChild(div);
					
					function handleFile(e) {
						var files = e.target.files,
						f = files[0];
						var reader = new FileReader();
						reader.onload = function (e) {
							var data = new Uint8Array(e.target.result);
							//console.log("In Change");
							var workbook = XLSX.read(data, {
									type: 'array'
								});

							worksheet = workbook.Sheets["YOURWORKSHEET"];
							jsonoutput = XLSX.utils.sheet_to_json(worksheet, {
						raw: true, header : 1
							});
						//console.log("Read " + jsonoutput );
						};
						
						reader.readAsArrayBuffer(f);	
						var completepath = $(':file').val();
							//console.log(completepath);
						interview.setInputValue("rest_filenameandpath", completepath);
					}
					
					
				var filedialog = document.getElementById("myFile");
					filedialog.addEventListener('change', handleFile, false);
					
					var completepath = $(':file').val();
						control.setValue(completepath);
						//console.log("Hello " + completepath);
						//console.log("Ending customInput Mount");
				}

Assuming you have a custom Input framework as your starting point, the above code will be in the mount. This will build an HTML5 file upload control, and attach an event handler. The code regarding Excel depends upon xlsx.full.min.js being in the resources directory. But that’s it. You’ve loaded the Excel file into a JSON object.

Entity Collect

The next step is to include a Custom Entity Collect in your project, and use the jsonoutput object (which you just created from the imported file above) in the mount of the Entity Collect to load the JSON into the Entity Collect. The following is an extract from the mount code

var numEntities = Object.size(jsonoutput);
					//console.log(numEntities);
					// Remove header row if the file has one
					jsonoutput.shift();
					// load records into the Entity Collect

					if (control.getRows() == 0) {
						for (j = 0; j < numEntities - 1; j++) {
							control.addNewRow();
							var mycurrentrecords = control.getRows();
							mycurrentrecords[j][0].setValue(jsonoutput[j][0]);
							mycurrentrecords[j][1].setValue(jsonoutput[j][1]);
							mycurrentrecords[j][2].setValue(jsonoutput[j][2]);
							mycurrentrecords[j][3].setValue(jsonoutput[j][3])
drawrows();

The end result is something like this:

Importing Data into an Interview

The File is loaded into the Entity Collect, and the contents displayed to the user. In my case I unhooked all the code related to modification (the onchange stuff from the original idea) and removed the add / delete buttons, since it was designed to just allow the user to see the loaded result, not modify it.

Importing Data into an Interview

If you want to have a look at the project, just download the very basic example here.

Back to Basics : Seeding from a URL Parameter

Back to Basics : Seeding from a URL Parameter

This topic comes up regularly and it often seems to get mixed up with just plain old “starting the interview from a URL”. So it’s time for a little refresher about Seeding from a URL Parameter. Time for another Back to Basics topic (catch the previous one here) !

First of all : What do we mean by seeding from a URL parameter?

Sometimes you want to start an Interview with certain attributes already populated. But this is not a situation where you are using a Connection, for example, to perform an inbound mapping loaded at start. Perhaps you are embedding Oracle Policy Automation Interviews on a Web site, and the Web site is going to pass some information into the Interview when it starts.

In pseudo-world, you want to do something like this:

https://myinterview.com/startsession/Interview/?myattribute=X

It’s really quite simple and it is becoming more frequent, since lots of Oracle Policy Automation is appearing in modern interfaces driven by JavaScript and other frameworks that support using JavaScript.

But if you try to do something like this with Oracle Policy Automation, you get a nasty surprise. It doesn’t work at all.

Then you read the documentation, and discover two or three important things that must be in place.

  1. You must authorize pre-seeding for the attribute(s) you are interested in

Seeding from a URL Parameter 1

2. You must use the seedData= tag on your URL to introduce the information to the Interview.

Armed with this you come back to your Interview and you try something like this, with impressive results:

Seeding from a URL Parameter 2

What the heck is happening here? It all seemed so simple. Well it is, but you forgot the most important point. Whatever your seeding from a URL requirements, they must be URL encoded. So the “=” character for example, is not going to get through the defences of Oracle Policy Automation. You have to encode it all first. So let’s imagine you have an attribute, whose name is my_seeded_value, and you want to populate that attribute with Richard Napier.

You need to encode part of what you are sending. You do NOT need to encode “seedData=” in fact if you do, there will be yet another error. Your URL needs to look like this :

http://xxx.com/web-determinations/startsession/URL_Seeding?seedData=

And the rest of the URL needs to be something like my_seeded_value=Richard Napier. But that part needs to be encoded. As a simple example, take it to https://www.urlencoder.org/ and put it through the encoder. It probably comes out like my_seeded_value%3DRichard%20Napier. Excellent. Now you can create the complete URL:

http://xxx.com/web-determinations/startsession/URL_Seeding?seedData=my_seeded_value%3DRichard%20Napier

And it comes out just fine:

Seeding from a URL Parameter 3

So there has definitely been an important lesson here : don’t encode seedData=, but do encode the information after it.

There is a lot more to learn about URL-based seeding, and we will continue this after the break. If you want the full online help, it is to be found here.

Have a good Holiday and see you in 2019!

Entity Collect Extension

Entity Collect Extension

Some time ago I wrote about Entity Collect Extension and the challenges of writing a demonstration piece of code. The challenges of Entity Collect Extension are pretty well known, but here is a run down of the most important one:

  • You must build the container and the contents,  and manage them

That means, that if you build an Entity Collect Extension, you cannot use other control extensions inside it :- you must code the entire contents yourself, so you would be looking at

  • Handling all different data types of attribute
  • Handling all the basic events of these attributes
  • Managing instance creation and deletion
  • Handling styling options and look and feel

So when you look at this shopping list, it can be quite daunting. Even so, I said to myself, if Oracle provides such a functionality, then somebody somewhere is going to use it. And so the idea came to create a demonstration Entity Collection Extension. When I started working on it I really did not have much time to look at it, so I wrote a couple of articles about my experiences and left it at that.

Recently I have been revisiting the concept again, and have found  time to work on it a little bit more. I added it to the OPA Hub Shop (on the strict understanding, as usual, that it is completely for educational and amusement purposes only).

That statement is particularly important in this case. I only decided to do this because I am fascinated by other people’s JavaScript frameworks. I find it useful to know what goes on underneath the glossy Oracle Policy Modeling HTML output. And my example is basic to the point of being little more than a sandbox (oh, and by the way, it still has a lot of issues – especially when you are running it in the Debugger rather than the Browser).

Entity Collect Extension in JavaScript

This version tries to cover off the 4 shopping list items shown above, and adds a couple of interesting ideas

  • Dynamic Delete Button (remove the button based on an attribute value). This is one request I have seen many times – the ability to forbid deleting in certain circumstances.
  • Handling Date Time and Value Lists for display and data entry.

I still have to find time to investigate :

  • Handling Inferred attributes that need to be refreshed as you are entering instance attributes.

I’ve just about had enough of this now so I am going to leave it for a while.  It has started to make my head spin.  Nonetheless it is an interesting exercise and helped make clear how cool the out of the box JavaScript really is.

The silent movie below shows where I’m at. All that work, for this rather dull looking thing. Sometimes there is not much to show for efforts. Of course, if I was a real programmer, I would be doing all of this in a much more efficient way (avoiding complete page refreshes at every change and so on) but I found this exercise very interesting. Certainly it gives me a better understanding of the scale of such a task.

Have a nice day!

Interviews, Languages and URL Arguments

Interviews, Languages and URL Arguments

The other day I was part of a discussion regarding the launch of Interviews. A couple of questions arose that formed the basis for an interesting discussion.

The details are not really important, but the basic thread was

  1. How can we be sure to launch an Interview in a specific language?
  2. How can we pass information into an Interview in respect of the language of the user?

Of course these two questions can be synthesised further to :

  1. What are the ways to find out what language the user is using?
  2. How do I pass seed information in the URL?

What language are you using?

You might be tempted to try all the different ways to do this JavaScript,  that you might find people talking about on Stack Exchange . There is basically no reliable method to detect the language of the user. Perhaps I have set the language of my Browser to German, but my Windows is in French. So which is my language? Perhaps I am in France so you can geolocate me, but I am actually a Finnish speaker? Perhaps I am in a country where geolocation is not usable or reliable? And so on…

In Oracle Siebel CRM, we have GetProfileAttr(“org.country”) available to us, for example through the JavaScript API, which will give us the Country in which we are supposed to be based. In Oracle Service Cloud we have the Country and Language in Contacts and no doubt we have other options in other applications. That will probably be the most reliable method, since it is not dependent on what the end user has done to their computer. Fine.

Suppose we want to pass that information to Oracle Policy Automation?

Let’s get down to basics.

In the image above :

  1. Whenever a Project is launched from a button, we can add the correct locale information to the URL to ensure it is launched correctly. So in the silly example above, there are two buttons. One uses”fr-FR”, the other “en-US”.
  2. This information is appended to the root URL via the ClickMe (mypath)  function.

In the third bullet, is illustrated the other part of the question. How can we pass this information into Oracle Policy Automation. using the JavaScript object we pass seedData={} into our Project. And in the seed data you can see our information being passed.

In the Interview itself, we can recover the information using the URL Argument feature in our mapped Project:

Of course the attribute can now be used in our Interview or our rules, should we need to display or leverage this information:

This little set of examples does illustrate that Oracle Policy Modelling could really do with some functions to at least allow the rule designer to capture the locale of the user (which language did they choose to view my interview in, so to speak).

Whats New in Oracle Policy Automation 18A #1

Whats New in Oracle Policy Automation 18A #1

Whats New in Oracle Policy Automation 18A #1

And so the latest and greatest version of Oracle Policy Automation has just hit the shelves, I’m of course talking about version 18A which became available for download from the Oracle Policy Automation Downloads page on the Oracle Technology Network pages. The list of what’s new is quite short this time, although we can imagine that lots of things have been going on behind the scenes given some of the early access info that has been filtering out on the official Oracle Policy Automation Blog these last few weeks. So, on with Whats New in Oracle Policy Automation 18A #1!

Whats New in Oracle Policy Automation 18A #1

Automatically Retrieve List Values from Rules

The biggest addition to the Oracle Policy Modelling experience in this new version is the concept of dynamically (or almost) retrieval of lists of values from rules. I’ll give you an example that you might be familiar with. You have written rules that deal with an attribute, of type Text, and you have referenced it several times with different values, perhaps as a condition to some conclusion. And now you want to add it to an interview. At some point you will find yourself copying and pasting the values in your Word document into a Value List or a plain old List of values in the Interview Screen.

Well, not any more. The video in the next paragraph shows off the new functionality, whereby the modeler can retrieve the values at the click of a button and add them to a screen, or of course use the existing functionality to turn them into a Value List. The video goes on to demonstrate what happens when you go back and edit the rules in the Word document, and what happens when you change the Control type – for example from Drop Down to Fixed List and so on.

The example uses a fictitious restaurant deciding the correct level of spices to be added to their sauce, depending on the customer selection.

video

That concludes our post Whats New in Oracle Policy Automation 18A #1, in the next post we will look at some improvements to the REST API (which we looked at in earlier posts) to enhance user lifecycle management.

Custom JavaScript Extension Places and Custom Options List

Custom JavaScript Extension Places and Custom Options List

This is the last in the series of posts about Google Maps and Oracle Policy Modelling for now. I’m conscious of the fact that there are lots of people out there who have more knowledge in JavaScript than I have, so I don’t pretend to provide anything more than “sketches” or “ideas” or “rough hacks”. But I hope you enjoy them anyway. This last post is all about a Custom JavaScript Extension Places and Custom Options List. We will use the basic principles of the previous examples and extend :

  • Display a Map
  • Geocode and Mark
  • Show an Infowindow
  • Find places in a certain radius
  • Display them in a Custom Options list

And this time we will use the Places API to get a list of information from Google, before displaying it in the Screen and using the information. Here is the scenario:

  1. You have a problem (fire, accident, police or flood or what have you)
  2. You are at a specific location (geolocalised)
  3. You need a list of people who can help (for example, a list of car repair workshops, or fire stations, or whatever).

This might fit into the scenario of an assistance company which wants to help you, by pointing you to the nearest garage or hospital or whatever. This uses the Google Places API. When you search it, you get a list of places – garages, hospitals or whatever. You set the starting location, define the radius in metres, and the type of search. The results come back as a list of places, which you can parse and add to your Oracle Policy Modelling screen as a Custom Options list.

So here is the lowdown.  The key to the Places search is in the request, as shown below:

var latlngnew = {
 lat: interview.getValue("cl_lat"),
 lng: interview.getValue("cl_long")
 };

var request = {
 location: latlngnew,
 radius: '50000',
 type: [interview.getValue("cli_search")]
 };
 var service = new google.maps.places.PlacesService(map);
 service.nearbySearch(request, callback);

In the example above you will note that there is an Oracle Policy Automation attribute value to define the type. For example, the “accident” option in the first screen:

OPA 12 - Custom JavaScript Extension Places and Custom Options List 1

Google Maps API Places Search uses type to distinguish what to look for. The mapping I made is just for fun, but bear in mind you might not find a single type that meets your needs, or you might not find any kind of match at all. The 50,000 is the number of metres for the search radius. You might get that from another attribute in Oracle Policy Automation, of course. Plus of course, there are the two attributes in which we have captured the latitude and longitude sent by the Browser.

In the callback function, we receive (hopefully) some results for our Custom JavaScript Extension Places and Custom Options List. The results are tidied up a bit, since the Oracle Policy Automation Custom Options Extension wants text and value properties (in case you want to have display values that are different from the actual values that will be stored in the receiving attribute). Finally the result is passed to the interview.

Custom JavaScript Extension Places and Custom Options List 2

Over in the Custom Option JavaScript file, we just need to grab the data from the Places API and display it as a searchable combo.

OPA 12 Custom JavaScript Extension Places and Custom Options List 4

So the end result of our Custom JavaScript Extension Places and Custom Options List exploration is that the list of providers displayed is based on the type of problem, and the location of the device. So hopefully the list of suppliers / fire stations / hospitals / police stations or whatever is pertinent.

As usual the very unpretty code, for entertainment purposes only, can be downloaded from the OPA Hub Shop. The next few blog articles are going to be on very different subjects than the JavaScript extensions, but I’m sure we will come back to these concepts often. Have a great day!

NB : Remember to test this using your favourite real Browser, not the embedded Browser : run the Debug with Ctrl+F5.

JavaScript Custom Extension Google Maps for Addresses and Reverse Geocoding

JavaScript Custom Extension Google Maps for Addresses and Reverse Geocoding Input

What is it about Google maps? This little example of a JavaScript Custom Extension Google Maps for Addresses and Reverse Geocoding was often requested by customers and students alike. Whether it be in the Siebel Hub or the OPA Hub Websites, Google Maps always seems to be a popular topic!  When I did a Google maps customlabel in Oracle Policy Modelling a few months ago, it was one of the most downloaded examples we have ever had.

JavaScript Custom Extension Google Maps for Addresses and Reverse Geocoding

And so, all I have decided to revisit the example.  This time however we will create a custom input control, and the user will click on the map to show where they are located.  These might be useful in an emergency situation, or something far more mundane such as simply be able to say what your address is, quickly.

To do this, we’re going to use the Google Maps JavaScript API once again.  We will use the same functionality as before, with new twists:

  • Marker on the map to display their browser-reported location (seen previously)
  • Information window to display text  (seen previously)
  • From the latitude and longitude obtain the Street Address
  • The possibility to drag the marker to another location if incorrect 
  • A button to confirm the selection of the address
  • The chosen the address will be passed to an attribute in the  Project

In this example therefore, we will need to use reverse geocoding.  Specifically, we need to convert the latitude and longitude into an address.  Using this Google service will normally provide us with a close match.  There may be multiple matches, or indeed no match at all.

For simplicity we will only handle the case where at least one match is found, and we will take the first match which is typically the closest.  We will not look at the other cases where there are multiple choices.  We are reserving that for another post in a little  bit!

In the example provided, which is as usual for education and amusement purposes only, the information from Google goes to our interview and is passed into an attribute.  Of course, what happens after that, it’s you that decides!

To keep things simple, the initial part of the script is the same.  We use your location to plant the marker on the map.  The exact icon used, depends entirely on what you chose in the interview : we used a simple example where the user declares an accident or a fire or some other emergency.  The marker is planted on the map. Then we introduce drag and dragend handlers, as well as a click handler.

The first page of the Interview is shown below.

JavaScript Custom Extension Google Maps for Addresses and Reverse Geocoding 1

Then we have a typical page displaying only a single Input Control for our demo.

OPA 12 - JavaScript Custom Extension Google Maps for Addresses and Reverse Geocoding 5

Our code will handle a few events. The marker click handler will display the address of the location in an infowindow. The drag and dragend handlers manage the user dragging the marker to a new location: maybe they didn’t get it right first time, so we let them do it again.

JavaScript Custom Extension Google Maps for Addresses and Reverse Geocoding 2

The two main functions in this code are the confirm_my_address function, which lets the user click a button in the marker and pass the address to Oracle Policy Automation to confirm that the marker is in the correct location, and the geocodeLatLng function, which does exactly what it says.

JavaScript Custom Extension Google Maps for Addresses and Reverse Geocoding 3It takes the latitude and longitude of the marker and queries Google to find the address of the marker before it is pushed to our attribute.

JavaScript Custom Extension Google Maps for Addresses and Reverse Geocoding 4

Because it doesn’t always work, we also have to manage the situations when had no address is returned. In this case we handle it with nothing more than an alert, which is fine for our little test. Regarding geocoding and so on you can find much more information of course on the Google Maps JavaScript API Documentation page.

Enjoy the video and if you are interested, you can download the code example for free, with no warranties and just for fun, from the OPA Hub Shop as usual. Remember to use Ctrl+F5 to run it in a real browser.

video

JavaScript Extension Custom Header as a Timer in Oracle Policy Modelling

JavaScript Extension Custom Header as a Timer in Oracle Policy Modelling

Sometimes I get distracted. I was supposed to be preparing for a workshop last night on an unrelated, Siebel-centric topic. I happened to be reading (again) through some material on our sister site, https://siebelhub.com, and I came across an example – which I have always been impressed by – from Duncan Ford, one of the Siebel Open UI and JavaScript gurus who contributes to the Siebel content on our blog. And it got me thinking about and Oracle Policy Automation JavaScript Extension Custom Header as a Timer.

The basic tenet of the script was building a set of statistics for timing performance : how long did such and such a page take to load and be ready, in a sense. In Siebel-world, this is a constant worry and ongoing process. So I got distracted by this and thought about Oracle Policy Automation and how we might use some of the ideas in our own script. I settled on the basic principle that I would want to know about how long it took people to finish a given Screen (ultimately you could extend it to the Stage concept as well). So not directly about performance, more about user time.

To do this, I figure we already have a bucket-load of exciting charts from the Hub :

JavaScript Extension Custom Header as a Timer

You know the sort of things I mean, available for each project : you can grab a set of information about a Project, change the type of chart, decide how to split the axes, decide which version to look at, filter on Service Cloud criteria and number of days and so forth.

These are great  tools. Of course, you also might have the mindbogglingly powerful In-Memory Policy Analysis with TimesTen and so on.

But you might not have any of that to hand, and you might want to work out how much time, each person spends on each Screen. Of course the navigation paradigm in Oracle Policy Automation is different to a Customer Relationship Management application like Siebel – you can go back and forth between the Screens quite a lot. All I really want to do in this case – because it was useful to me – was to identify the cumulative time spent on each Screen, and display it in the Browser at the end of the Interview:

JavaScript Extension Custom Header as a Timer

It sounds really easy but there are a couple of things that will be interesting to talk about along the way.

JavaScript Extension Custom Header as a Timer in Oracle Policy Modelling  – Data

I decided to choose the customHeader as my starting point. The documentation states that this renders the header for an interview. So by logical extension it probably has the things we might need :

  • Access to the Interview Object
  • Access to the Stages and Screens in the Stage
  • Adding code that does not implement any UI probably won’t cause a problem, since the UI does not have to display a Header (it’s an option in the Styles dialog)

For the second part of the requirement, the display of the results, I decided to use the customLabel approach with jsGrid, similar to the example back in December of last year.

So I knew I would need 2 files, one for the custom Header and one for the custom Label. Since the results would only display on the last page (“Interview Complete”), I wanted to be able to pass the results from the Header to the Label easily. So how did the JavaScript Extension Custom Header as a Timer in Oracle Policy Modelling work out? Well, as usual I was just experimenting so it is rough, ready and not very robust. But it is interesting enough to provide some talking points. Let’s look at the code for the Header first.

First the opening salvo of the customHeader:

JavaScript Extension Custom Header as a Timer

  1. We are going to store results in an array of JavaScript objects. This is similar to how the actual Screens are accessed in the Interview, and also it allows us to plug the data straight into the jsGrid component.
  2. So here is the Array
  3. I’m loading the set of Screens here. Be aware, that the Screens you load will only be those in the current Stage. So our myScreens array will be used to store (as you navigate) all the screens in all the stages, to have only one big array when you have finished.
  4. I’m checking in my Array of Objects to see if the Screen we are on has ever been visited : is it in my Screens array?
  5. If it is in my Array, this is not the first time you have been on the Screen in question. We update the information about the Screen in the Object, calculating the elapsed time using a very rough and ready technique.

JavaScript Extension Custom Header as a Timer

Here is the rest of the script, which I have split out into a second part for readability.

  1. If the Screen is not in myScreens, then it is a new Screen. We add it and set up the basic information.
  2. We hook our myScreens array to the Interview object.

JavaScript Extension Custom Header as a Timer in Oracle Policy Modelling – Label

Over in the Label code, the process is very familiar:

JavaScript Extension Custom Header as a Timer 5

  1. Create a custom DIV on the final Screen using the Custom Property “name” to make sure we only execute on the label we are interested in. Get a reference to our myScreens array.
  2. Spawn a jsGrid from the DIV (which implies of course that jQuery and jsGrid files are in the /resources folder of your Project).
  3. Build the field object, noting that you can format the fields, or add / remove fields as you see fit from your array of Objects.

So if all goes according to plan you might get something like this. Note that the whole thing only works if you navigate normally – that is to say you navigate using the navigation Buttons or stage Buttons. Using the Debugger tree on the left does not have the same effect at the array will be empty. The array will also be empty if you do not reset between each debugging session. Once deployed, there should be none of those issues of course, or you could Ctrl+F5 to debug in Chrome or your favorite browser.

OPA 12 - JavaScript Extension Custom Header as a Timer in Oracle Policy Modelling 6

This being a bit of an experiment, I didn’t go much beyond 5 screens in 4 different stages, nor did I add any events to time the Stages, or to time Controls  – such as “on Focus” and “on Blur” which I thought about doing to be able to get the times in and out of individual controls and which I might do at some point.

JavaScript Extension Custom Header as a Timer – Conclusion

Anyway I hope the ideas, if not the implementation, have given you some pause for thought – namely how to get the Screens and Stages and load them into your own Array, and pass them to other Controls. The experimental code is on the OPA Hub Shop, search for customHeader.

Have a nice day!

Worldwide
Logo by Southpaw Projects LLC