Welcome to the OPA Hub!

Tag Archives: JavaScript

Custom Entity Collect Extension in Oracle Policy Automation #2

Custom Entity Collect Extension in Oracle Policy Automation

In this second part of the series, we continue to investigate building a Custom Entity Collect Extension in Oracle Policy Automation, and complete the basic example of a working collector. The code is once again focused on pointing out big ideas, traps, suggestions and the details are left to you, dear readers. Everything you see here is free and you can use it anywhere but it is for educational and entertainment purposes only. The PDF version of the code is available in the OPA Hub Shop for free.

Building the User Interface

The next big chunk of code is all about continuing the work begun previously, specifically building the User Interface by adding input boxes and other User Interface elements to the page. We switch according to data type, and as before we add a number of valuable extra HTML attributes to our elements.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
//GET KEY INFORMATION
									var theinstancename = myrecords[i][j].instance.toString();
									var theentityname = myrecords[i][j].entity.toString();
									var theattributename = myrecords[i][j]._source.config.attributeId;
 
									var myname = myrecords[i][j].id.toString();
 
									attrInput.setAttribute('id', myId);
									attrInput.setAttribute('data-entityname', theentityname);
									attrInput.setAttribute('data-instancename', theinstancename);
									attrInput.setAttribute('data-attributename', theattributename);
									attrInput.setAttribute('data-rownumber', j.toString());
									attrInput.setAttribute('name', myname);
 
									// CONVERT ATTRIBUTES OBJECT TO ARRAY
									var myAttributeObject = myrecords[i][j]._source.screen.clientState[theentityname];
									myAttributeObject = myAttributeObject[theinstancename];
									var myAttributeArray = $.map(myAttributeObject, function (value, index) {
											return [value];
										});
 
									//DISPLAY THE CORRECT VALUE IN THE INPUT BOX
 
									switch (myattributedatatype) {
									case "boolean":
										var response;
										switch (myAttributeArray[j].toString()) {
 
										case "true":
											response = true;
											break;
										default:
											response = false;
										}
										attrInput.checked = response;
										rowdiv.appendChild(attrLabel);
										$(attrLabel).after(attrInput);
 
										break;
 
									case "number":
										attrInput.setAttribute('value', Number(myAttributeArray[j]));
										rowdiv.appendChild(attrLabel);
										$(attrLabel).after(attrInput);
										break;
 
									case "text":
										attrInput.setAttribute('value', myAttributeArray[j].toString());
										rowdiv.appendChild(attrLabel);
										$(attrLabel).after(attrInput);
										break;
									case "date":
										if ($(attrInput).attr("data-datepicker") === 'true') {
											$(attrInput).datepicker();
											$(attrInput).datepicker("option", "dateFormat", "yy-mm-dd");
											$(attrInput).val( myAttributeArray[j]);
											rowdiv.appendChild(attrLabel);
											$(attrLabel).after(attrInput);
 
 
 
										}
										break;
 
									}

Whoa, easy there! So what is all of that about? The different kinds of data (Boolean, text, numbers, dates) need to be handled slightly differently, to display correctly.

Error Display

What happens if the Interview cannot continue (note that this example Entity Collect only handles errors on navigate, the default for Oracle Policy Automation Interviews) because of an issue? The user needs to know what they have done wrong, so they can correct it. Thankfully the errors are available to us (if they exist).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//HANDLE DATA ENTRY ERRORS AND ERROR DISPLAY
var myerrorobject = myrecords[i][j]._source.screen.errors[theentityname]
if (myerrorobject) {
var myerrorinstance = myerrorobject[theinstancename];
if (myerrorinstance) {
var myerrorattribute = myerrorinstance[theattributename]
if (myerrorattribute) {
var errorrow = document.createElement("div");
errorrow.id = "rowcontainer" + i.toString();
errorrow.setAttribute('data-entityname', theentityname);
errorrow.setAttribute('data-instancename', theinstancename);
errorrow.setAttribute('data-attributename', theattributename);
$("#errordiv").append(errorrow);
 
$(errorrow).append("Attribute : " + myerrorattribute.attributeId.toString() + " - " + myerrorattribute.message);
$("input[data-entityname='" + theentityname + "'][data-instancename='" + theinstancename + "'][data-attributename='" + theattributename + "']").css("border", "3px solid red");
}
}
}

In this section we build a small DIV for the errors, and add any errors that exist as rows within it. At the same time, the relevant attribute is highlighted with a red border.

Updating the User Interface

When the user makes changes, we need to handle them and ensure they are passed on. The last part of the code for today concentrates on handling each of the data types, and making sure the data is correctly passed to Oracle Policy Automation. This is quite tricky, and can necessitate quite a bit of review of the Investigate JSON to try and understand what it does not like, as the error in the Browser will most likely be a generic 500 error.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
var inputtype = $(attrInput).attr("type");
var datepicker = $(attrInput).attr("data-datepicker")
 
switch (inputtype) {
case "checkbox":
$(attrInput).change(function () {
interview.setInputValue(event.target.attributes["data-attributename"].value, this.checked, event.target.attributes["data-entityname"].value, event.target.attributes["data-instancename"].value);
 
interview.saveData();
event.stopImmediatePropagation();
 
});
break;
case "input":
 
if (datepicker === 'true') {
$(attrInput).change(function () {
var mydate = $(this).datepicker('getDate');
mydate = new Date(mydate);
var mydateinstance = $(this).attr("data-instancename");
var mydateattribute = $(this).attr("data-attributename");
var mydateentity = $(this).attr("data-entityname");
var myisodate = mydate.toString();
function formatDate(mydate) {
var d = new Date(mydate),
month = '' + (d.getMonth() + 1),
day = '' + d.getDate(),
year = d.getFullYear();
 
if (month.length < 2)
month = '0' + month;
if (day.length < 2)
day = '0' + day;
 
return [year, month, day].join('-');
}
interview.setInputValue(mydateattribute, formatDate(mydate), mydateentity, mydateinstance);
 
interview.saveData();
event.stopImmediatePropagation();
 
});
 
} else {
$(attrInput).change(function () {
interview.setInputValue(event.target.attributes["data-attributename"].value, event.target.value.toString(), event.target.attributes["data-entityname"].value, event.target.attributes["data-instancename"].value);
 
interview.saveData();
event.stopImmediatePropagation();
 
});
 
}
 
break;
case "number":
$(attrInput).change(function () {
interview.setInputValue(event.target.attributes["data-attributename"].value, Number(event.target.value), event.target.attributes["data-entityname"].value, event.target.attributes["data-instancename"].value);
 
interview.saveData();
event.stopImmediatePropagation();
 
});
break;
}
 
}

And so this pretty much leaves us with a row builder, and an error builder. But the final part of the code is very important, specifically the Delete Button to delete the row you don’t want any more.

Delete Rows

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//ADD A DELETE ROW BUTTON  AFTER EACH ROW
								var deletebutton = document.createElement("button");
								deletebutton.setAttribute("type", "button");
								var deletebuttontext = document.createTextNode(control.getRemoveButtonText());
								deletebutton.appendChild(deletebuttontext);
								//SET UP THE CLICK EVENT OF THE DELETE BUTTON
								$(deletebutton).click(function () {
									var myliveinstances = control._source.instances.slice();
									// FIND THE ROW THAT CONTAINS THE DELETED INSTANCE
									var found = myliveinstances.indexOf(event.target.parentElement.getAttribute("data-instancename"));
									control.removeRow(found);
 
									drawrows();
								});
								rowdiv.appendChild(deletebutton);

Delete the Right Row

The delete row feature needs to find the row in the live set of instances (the _source.instances) using the HTML element that is the parent of the button. So if you click the Button, which is on the third row of the HTML User Interface, then using the instance name we can find the correct row and remove it. This is because the control.removeRow() uses the zero-indexed array in control._source.instances, not the user interface you are building. For example, if you have four instances on screen, then you delete one, the HTML will show that instance 1, instance 3 and instance 4 remain for example. But the Array members are now marked as rows 0,1 and 2.

The code closes out with the standard stuff :

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
update: function (el) {$("#errordiv").empty();	drawrows();},
				unmount: function (el) {
 
					if (control.getProperty("name") == "xEntity") {
 
						$("#entitycollector").remove();
					}
				}
			}
		}
	}
})
 
 

And so, what remains to be done? Well, of course, reorganize all that code written as a stream of consciousness!

But seriously, the obvious ones are

  • Ensure that when an instance is created, but the user has not yet entered any data, that the error checking is fired ( you can actually advance to the next page and come back to see the errors, because of the way the error object is handled only on the mount , not on the update.
  • Ensure that errors are removed from the page when they relate to an instance that was deleted by the user.
  • Ensure that the HTML building includes CSS class information to facilitate a new look
  • Build out date-time input and currency input and saving

But I’m sure you will find time for that. Have a nice day and enjoy building your own Custom Entity Collect Extension in Oracle Policy Automation!

We’ll leave you with a short video.

Custom Entity Collect Extension in Oracle Policy Automation #1

Custom Entity Collect Extension in Oracle Policy Automation

The idea behind this post, as is often the case, came from a conversation with a customer about something unrelated to the actual result. Suffice to say we were discussing data collection in Oracle Policy Automation and the idea of Custom Entity Collect Extension in Oracle Policy Automation came up, vaguely. The difficulty with demonstrating such an Extension is that every situation will be different, and every extension will have lots of styling to “make it look like something different”.

Perhaps the most important thing therefore is to demonstrate a Custom Entity Collect Extension in Oracle Policy Automation without any custom functionality and without any styling, so you can use it as the basis for your own discovery sessions. Of course, as always (and in particular in this case, as the example is necessarily longer than most), the code is totally for prototype and demonstration purposes only, and I will leave it to you to take the ideas and run with them.

Custom Entity Collect Extension in Oracle Policy Automation Result Final

Alright let’s get started. The Project looks like the following screenshot; namely a single entity called the accident and a variety of input attributes. There are no rules in this Project at the moment.

Custom Entity Collect Extension in Oracle Policy Automation Result 1

The screenshot shows a number of things we will need to think about:

  1. The code will try to be generic
  2. The code needs to read Screen items like the text here
  3. The code needs to offer deletion of instances as well
  4. The code needs to display Boolean data as well as text or numbers
  5. The code needs to display dates with a date picker

The Project also has, for completeness’ sake, an entity container on the final Screen to review the data to make sure that what the user has done has been saved correctly. Of course, you can also check the Data tab in the debugger.

The basic principle of the code is common to all the different examples seen around the Web, namely the Entity Collect has a custom Property whose name identifies it to the JavaScript extension code. I won’t include it here but you can find it in the PDF version at the end of this series.

NOTE : The Code Viewer on this website eats some characters, so be careful (especially less than and greater than symbols)

Getting Started : Make a Container

The first part of our mouncode will build the infrastructure for our container. Fittingly enough, it will be a DIV.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
return {
				mount: function (el) {
 
					// ADD ROW BUTTON THE TOP OF THE ELEMENT
					var button = document.createElement("BUTTON");
					button.setAttribute("type", "button");
					var buttontext = document.createTextNode(control.getAddButtonText());
					button.appendChild(buttontext);
					$(button).click(function () {
						control.addNewRow();
						drawrows();
					});
					el.appendChild(button);
 
					//CREATE DIV CONTAINER FOR ENTITY COLLECT
					var div = document.createElement("div");
					div.id = "entitycollector";
					el.appendChild(div);

As you can see, there was a little more than just a DIV. The code added an “Add Row” Button to the top of the Container, add set a click event to add a row to the Control with control.addNewRow(). The rest of the code adds the button to the page, and then adds an empty DIV.

1
2
3
4
5
6
7
8
9
10
11
12
var myattributelist = control._source.config.templateControl.controls
					function drawrows() {
						$('#entitycollector').empty();
						// CREATE AN ARRAY OF LABELS FROM THE ATTRIBUTES
						var mylabels = [];
 
						for (i = 0; i < myattributelist.length; i++) {
							mylabels.push({
								caption: myattributelist[i].caption.toString(),
								name: myattributelist[i].attributeId.toString()
							});
						}

The code above gets a reference to the list of attributes that are on the Control (essentially, what the designer has added to the Screen in Oracle Policy Modelling. Then it creates an array of label texts for each attribute. This set of labels will be used in the next part of the code. The function drawrows() will perform almost all of the setup of the control.

1
2
3
4
5
6
7
8
9
10
11
12
var myrecords = control.getRows();
 
						if (myrecords.length > 0) {
							for (i = 0; i < myrecords.length; i++) {
								// CREATE A CONTAINING DIV FOR EACH ROW
 
								var rowdiv = document.createElement("div");
								rowdiv.id = "rowcontainer" + i.toString();
								rowdiv.setAttribute('data-rownumber', i.toString());
								rowdiv.setAttribute('style', 'background-color: lightblue;');
								rowdiv.setAttribute('data-instancename', myrecords[i][0].instance.toString());
								$("#entitycollector").append(rowdiv);

This section creates a new DIV for each row of the “records” or instances of the entity. The rowdiv also uses HTML attributes to store useful information about the row such as the instance name, which makes it easy to find things later on either in the HTML source or in jQuery.

Drawing the Inputs

The final part of the code for today looks at drawing the input boxes, check-boxes and other data entry items.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
var attrLabel = document.createElement('label');
// FOR EACH LABEL
for (j = 0; j < mylabels.length; j++) {
var myId = myrecords[i][j].id.toString();
var attrLabel = document.createElement('label');
attrLabel.setAttribute('for', myId)
var attrLabelTextNode = document.createTextNode(mylabels[j].caption);
attrLabel.appendChild(attrLabelTextNode);
 
//ADD PROPERTIES TO THE HTML INPUT
var myattributedatatype = myrecords[i][j]._source.config.dataType;
 
switch (myattributedatatype) {
 
case "boolean":
var attrInput = document.createElement('input');
attrInput.setAttribute('type', 'checkbox');
break;
 
case "number":
var attrInput = document.createElement('input');
attrInput.setAttribute('type', 'number');
break;
 
case "text":
var attrInput = document.createElement('input');
attrInput.setAttribute('type', 'input');
attrInput.setAttribute('data-datepicker', 'false');
break;
 
case "date":
var attrInput = document.createElement('input');
attrInput.setAttribute('type', 'input');
attrInput.setAttribute('data-datepicker', 'true');
break;
 
}

So what is happening here? In the first part of the code, we are setting up the labels by adding the text node to build the appropriate UI. Then we switch through a variety of different data types – note that we have not covered them all, just the core types – and how they will be built in HTML. The date type, for example, is going to use jQuery UI date picker so the type is set to input not date as you might have thought (to take advantage of modern browser support for that input type) but the support is patchy and the limitations many. So it is going to be a simple input but with a jQuery UI element bound to it.

The Boolean uses a check-box and the Number uses number : so we can experiment with that UI experience.

Continues in part two of our Custom Entity Collect Extension in Oracle Policy Automation investigation. If you are looking for more information, the official documentation is to be found here.

The OPA Hub Snap Poll Results

The OPA Hub Snap Poll Results

The OPA Hub Snap Poll Results

As you know, the OPA Hub Website runs short-term polls or “Snap Polls” in an effort to collect and share information about Oracle Policy Automation that may hopefully be of value to the Community. The OPA Hub Snap Poll Results concern the question we asked in March 2018, specifically “Are you going to be using the new JavaScript Extension in your OPA Interviews?”.

The most recent versions of Oracle Policy Automation have pretty much consolidated JavaScript as the client-side platform for delivering just about any visual changes you might wish for. Many of us are also pretty hopeful that the JavaScript library in interviews.js is a forerunner of a future REST client, and hopefully the basis for some sophisticated integrations as well.

Of course there are other avenues of development of Oracle Policy Automation, notably the experimental RuleScript, based on the output of the Oracle Labs and the graal library. Anyway, The OPA Hub Snap Poll Results were quite definitely in favour of the JavaScript extensions. You can find the results below, and I have included a link to a dynamic version of the graphic hosted by our friends at easel.ly.

 New OPA Snap Poll

As the Snap Poll on the subject of JavaScript has now closed, a new Snap Poll has been opened, this time in an effort to get more information about the needs of the Community in respect of training and advanced workshops. Please take a moment to answer the OPA Hub Snap Poll on this subject.

You’ve got to be in it, to win it

A reminder : when we close this Snap Poll, one lucky voter will get a free copy of Getting Started with Oracle Policy Automation 2018 Edition, so don’t hesitate to vote today. The Snap Poll will close on the 31st April 2018, and results will be published on this website soon afterwards.

 

Getting Started with Oracle Policy Automation 20018 Edition

Snap Poll : Training – 1 Question, 30 Seconds and a Chance to Win

Snap Poll : Training – 1 Question, 30 Seconds and a Chance to Win

As you all know, the OPA Hub Website tries to provide content and services that meet the needs of all of us who are working with Oracle Policy Automation, and probably Oracle Service Cloud or Oracle Siebel CRM on a day-to-day basis. One of the areas we have been looking at with our partners and content providers is the subject of training. We have a number of different training projects in the pipeline. But read on to find out about our Snap Poll : Training – 1 Question, 30 Seconds and a Chance to Win…

Some of the training we already provide has met with good feedback and seems to fill a gap left by the official training provider. However, we are always eager to find out more. That is why this post contains a snap poll : it is so easy to answer the question it will take you all of 30 seconds. You can register your vote using either an anonymous vote or if you use your OPA Hub Website login you will automatically be entered into a draw to receive a free copy of the Getting Started with Oracle Policy Automation 2018 Edition.

Snap Poll : Training - 1 Question, 30 Seconds and a Chance to Win

This book is so new it is not even in the shops yet, I have just received the first copy from the printers so it is fresh as fresh can be. The book can therefore be yours just for entering our Snap Poll : Training – 1 Question, 30 Seconds and a Chance to Win!

Thank you to everyone who takes part in the spirit of sharing your opinion. The data will be reviewed on the OPA Hub and will be completely anonymised. The name of the voters will only be used to ascertain the winner of the free copy of the book!

What kind of advanced OPA training would you be interested in attending?

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.

Custom Entity Container JavaScript Extension Example #2

Custom Entity Container JavaScript Extension Example #2

Note : this JavaScript is part of a series. Please start with part one,  continue reading here then visit the final example in part three. You can also watch a quick video of the final example on  our YouTube Channel.

Following on from the previous post, we now have a working example that let’s us access an array of data in our inferred entity from the JavaScript extension code we write to manage our Control extension(s). But what about when we want to use this code outside of Debug mode? And why does it only work in Debug mode? What are the additional caveats we are going to find? Let’s make Custom Entity Container JavaScript Extension Example #2!

Debug Mode

The Oracle PolicyAutomation object in your JavaScript  has EnableDebugMode tucked away deep in the interview.js static resource file. This produces the beloved Debug Console window you see when you are working the Debug in your browser or in the embedded browser, which pipes the console output into this dinky pink box:

Custom Entity Container JavaScript Extension Example #2

When working in Debug mode, you have also noticed (and this is not a surprise) that some interesting objects and functions are available that do not show up when the project is deployed. This is not a surprise really. But in our case, we would like to have access to our array of data for our (perhaps twisted and even unprecedented) purposes. So where do we go from here? The answer, as always, turns out to be relatively simple.

The interview object contains a reference to the same array in the form of  interview._session.config.data[1].instances. Note that the number one assumes that you have only two entities, Global and something else. You will have to inspect your code and find out which node you are interested in if you have more. It looks like this in my case.

Custom Entity Container JavaScript Extension Example #2

Once you have that reference, you can do two things easily.

  1. You can figure out the length of the array and use it in your for…each loop
  2. You can select one of the child array called attributes and dig up the information you need to display

So in this new, non-Debug version of the code, you would end up with the following changes compared to the previous post.

Custom Entity Container JavaScript Extension Example #2

  1. In the early part of the script, get a reference to the part of the interview object you need
  2. Use it in a similar way to previously to get the different attribute values you want to display

This code will run even if you are not using the debugger and you have deployed the project to an Interview URL.

Watch Out!

But there is another caveat. The exact index (location) of your entity in the array of entities will change as you compile and deploy your project. So we need a mechanism to make sure we have selected the correct entity and instances.  What today is index 3 might be index 2 tomorrow. Since the entity you are looking for has a unique public name, you might use that to find it. Something like this (based on code taken from stackoverflow.com).

Custom Entity Container JavaScript Extension Example #2

Working through the different nodes until you find the right one, based on the unique name.

Custom Entity Container JavaScript Extension Example #2 Summary

This approach allows us to take the same technique and improve our “Custom Entity Container JavaScript Extension Example #2” to function outside of the Debug window and give it a more robust mechanism for searching for our entity. I would not be surprised if at some point this reference was made easier to access but for now, this seems to do the trick. The documentation is, as ever, available online.

Code Example

As always the code is available for free download from the OPA Hub Shop. Look for Custom Entity Container JavaScript Extension Example #2  in the product list. But we are still not finished, for in part three of this series we will finish off in style by skinning our List of Instances with jsGrid.

Oracle Policy Automation – JavaScript Custom Search

Oracle Policy Automation – JavaScript Custom Search

As many of you will no doubt  have discovered, the recent version of Oracle Policy Automation now comes equipped with a complete JavaScript Extension API. Simply put, we can create custom Labels, Input Controls and so on using JavaScript objects. Our code, which is part of the Project, is detected at runtime and executed by the JavaScript engine in your browser. In this post we will look at JavaScript Custom Search and how to use it in your own projects.

One of the most fun parts of this new API is of course discovering ways to use it. Following on from the post a couple of weeks ago, I thought I would share an example of using the customSearch. The principle behind using JavaScript Custom Search in Oracle Policy Automation is very easy to understand. Most of us are familiar, for example, with the concept of typing in a little bit of text and then the browser completes it, providing a drop down of potential choices. There are a myriad of ways and places to see it on the Internet. Perhaps you are searching for a street, so you type in the postal code and sure enough, your website might propose the list of streets in that area.

Whatever your reason for using it, here is an example you can play along with. Since we need a data provider, we are going to use JSONPlaceholder – a wonderful fake REST API that you can use for testing just this sort of thing. It is free and easy to use. We can call various different endpoints and the server will report back with fake data. We can use all the verbs and many different sorts of REST call. Great!

What else do we need?otn We need a JavaScript editor (step forward Notepad ++ for example) and the August 2017 edition of Oracle Policy Modeling. Before we look at the code however, remember the following caveat : anything you read here is for entertainment and education purposes only and should not be relied upon for any reason or situation.

Let’s get a big picture first. You are going to be coding three things

  1. The Search
  2. The Commit, which you can think of as “any post search processing”
  3. You will be building a set of records to be passed to the callback function

JavaScript Custom Search

The search itself, as I mentioned before we will use the JSONPlaceholder service. I have selected the users endpoint, so that I can fire off a query like “‘/users?q='” and pass the text string entered by my user. Hopefully the service will return some people.

JavaScript Custom Search Step by Step

The processing and preparation will involve, purely for the purpose of demonstrating the principles, laboriously removing any elements of the data I am not interested in. In fact I am going to delete everything except the name and the email address. The callback function expects a set of data that respects a specific format: “This can either be an array of strings or an array of objects where each object has a text property.” So now you know why I wanted to demonstrate the following

  1. Renaming a property in the object
  2. Using the other property, email, in the Commit.

Here is the first part, basically I am :

  1. getting the text from the user and then passing it to the REST endpoint in the form of a GET.
  2. The response is coming back at me as a bunch of objects, which I am going to loop through and trim by removing unnecessary stuff.
  3. Then I am going to convert it into an array of results for our JavaScript Custom Search.
  4. Then I call the callback function with the array passed in.

JavaScript Custom Search Script

The user can now select one of the values I have returned. When they select their chosen value, the commit will handle it:

JavaScript Custom Search Commit

In the picture above you can see the value which is passed in actually included the email element from the REST call, so I am free to use it (and any of the other bits I didn’t delete in the previous steps) to populate other attributes, such as the email address.

To help you make sense of all of that, you will find below a video which guides you through the steps and shows the different elements.

Have a nice day and I hope you enjoyed reading an example of JavaScript Custom Search in Oracle Policy Automation.

JavaScript Custom Search Video

Update (December 2017)

I forgot to mention that if your input control is displaying an attribute that is not of type text, this code will not run. It works (perhaps self-evidently, but for completeness I reiterate it) only on text attributes.

Oracle Policy Automation -JavaScript Custom API : Google Maps

Oracle Policy Modelling – OPA Custom Control : Google Maps

The other day I was confronted with a requirement to display Google Maps within an Interview. The requirement was not window-based or dialog-based : the Google Map had to be in the main HTML Interview. I was using the August 2017 release, and thus able to us the Control Extension API in JavaScript. Here is a quick tutorial for this OPA Custom Control (using the new Extension API).

The example is so generic that I thought I would share it with you. As before this example is just for educational purposes and there are lots of steps that were synthesised in the end after some refactoring, but is easier to show the long and wordy version here for educational reasons.

Firstly, let’s make the OPA Custom Control Project and set up the simple attributes and Screens.

OPA Custom Control - Attributes

Then we can build out the two Screens.

OPA Custom Control Map Screen

The map screen is just, for the moment, a Screen that is always displayed (because in this demonstration project we will not be doing any logic in rules).

OPA Custom Control Data Collect

The preceding screen, we will collect the information we need to display : firstly the visible details and secondly the latitude and longitude in the Location options of the Screen.

OPA Custom Control Value List

In this demonstration project, the incident type will have a value list, with four choices. These will correspond to four different icons from the Google Maps standard icon list. The list I was able to view from this site, and download the files needed for the demo. They were placed in the usual folder of our OPA Custom Control project, as shown below.

OPA Custom Control Images

We’ll make some adjustments to the Map Screen, adding all the attributes we intend to use in the demonstration, using the public names and substitution tags.

OPA Custom Control Map Elements

The label that will be the basis for the map, and as you can see it needs (for this demonstration) a custom property, as shown below:

Now we can bring in the JavaScript file, using the Oracle Policy Automation Extension API to extend the label control. Now you will add the JavaScript file that will be the basis of the control, by clicking the Custom Files button in the Styles.. dialog.

 

OPA Custom Control Extension API Add File

Our file will use the standard framework of all the JavaScript Extensions (See earlier posts here and here).

The content of the file, extended for the purposes of illustration, begins here, with three main areas of interest.

  1. Creating the script tag to load the Google Maps library
  2. Do the same to create an empty container for the future map
  3. Obtain the latitude and longitude from our project.

Continuing with our script, the entire mount, as you can see at the top of the previous image, is preceded by a check for our custom Property.

OPA Custom Control Extension API Map Setup

TIP : If you are planning on implementing only this customLabel, and you want to display other labels using the standard rendering, then you should put  your custom property if statement right to the top immediately after the customLabel: line, and wrap everything in this if statement so that the entire script will be ignored for ordinary labels.

The next chunk is mostly setting up the Google Map functionality

4. These are the icons that will be used in the different types of incident. We use the $() notation to avoid fixed references to folders.

5. This is the callback function used when Google Maps has loaded

6. This actually loads the map

7. You can build an array of elements if you intend to display multiple markers. Here you will just use the one, with the latitude and longitude garnered earlier and the incident type.

OPA Custom Control Map Label

8. For each of the loaded points, create a marker and add it to the map,

9. With a click event to handle the user interaction

10. The click event will display a dynamic content, in a typical Google Maps information box.

11. Finally as good citizens we will implement the unmount which will remove the Map when we leave the page, avoiding errors about multiple maps being loaded.

The interview experience gives us the following lovely rendering when you enter the details and pass to the Map Screen.

The icon will change depending on the type of incident, and the information box will display whatever attribute values you wish to show.

If anyone is interested in obtaining the JavaScript code for learning purposes, please leave a comment. Note that remove() is not compatible with all browsers, and the Internet Explorer embedded in the Debugger will not like it. But open the Debugger with Ctrl+F5 in your real browser and it will work (for a list of supported browsers see here).

 

Oracle Policy Automation May 2017 – New Features #2

Oracle Policy Automation May 2017 – New Features #2

Following on from the first article in this series, which dealt with the new features in respect of PDF Forms and using PDF as the basic template instead of an RTF File for use with Oracle BI Publisher, this second video from the Oracle Policy Automation May 2017 – New Features series looks at the enhancements around JavaScript.

To be more specific, this video looks at the use of JavaScript to handle styling of interviews or controls on screens. Unlike previous iterations, this new version manages the process in a much more robust and upgrade-friendly way. Gone are the jumble of JavaScript files, to be replaced by JavaScript Extensions of the Oracle Policy Automation space. You will be using JavaScript objects to define the styling attributes of your controls or interviews.

There are a couple of pitfalls along the way which I draw attention to – not necessarily bad things, just points to be aware of when you begin using this styling technique. In a later video I will look at using the same Extension concept to move beyond styling into actual customizing of controls with handlers and so forth. The official documentation regarding Styling Extensions can be found online, at this address at time of writing.

Oracle Policy Automation May 2017 JavaScript Extensions

I’m very pleased to see the return of this functionality, in a much improved, more industrial grade framework. Until the next article, enjoy the video and Oracle Policy Automation May 2017 New Features Part Two.

In the next articles we will look at JavaScript Extensions again, and then the new features around dynamic values in selection lists (back to the future again!). Until then, have fun!