Category: JavaScript Extensions

SIRET / Credit Card Checking in Intelligent Advisor with Luhn

This post was originally going to be called SIRET checking in Intelligent Advisor but the notion of a SIRET number is an acronym famous I think only in France. What we are really talking about is validating anything that uses the Luhn Algorithm (aka Modulus 10 algorithm). There are so many uses, most of them well known and some surprising (customer survey codes at McDonalds, who knew!).

This algorithm is, according to a very well-known site:

From Wikipedia

“used to validate a variety of identification numbers, such as credit card numbers, IMEI numbers, National Provider Identifier numbers in the United States, Canadian Social Insurance Numbers, Israeli ID Numbers, South African ID Numbers, Greek Social Security Numbers (ΑΜΚΑ), and survey codes appearing on McDonald’s, Taco Bell, and Tractor Supply Co. receipts. It is described in U.S. Patent No. 2,950,048, filed on January 6, 1954, and granted on August 23, 1960.

The algorithm is in the public domain and is in wide use today. It is specified in ISO/IEC 7812-1.[1] It is not intended to be a cryptographically secure hash function; it was designed to protect against accidental errors, not malicious attacks. Most credit cards and many government identification numbers use the algorithm as a simple method of distinguishing valid numbers from mistyped or otherwise incorrect numbers.”

So it’s not surprising that Luhn Validation came up sooner rather than later in an Intelligent Advisor project. The implementation is possible in two ways I suppose : firstly, if you are already using RuleScript in the project (which you should not be doing for new projects, but maybe it is an existing one) then it is a really simple task to find a decent implementation of the algorithm in JavaScript and adapt it for your Project. Other algorithms that are more complex can be quite easily implemented that way (sigh, such a pity that RuleScript is no longer part of the future of OPA).

The second way to do it is to use a JavaScript extension for your Input Control and let the Validate key do the work. I suppose there may be a third approach, to try and implement the algorithm in natural language but I doubt it is possible or practical.

Anyway how could it be done. Simple, first get a decent implementation of the Luhn algorithm : for example this one is super fast. Then build out a standard Input Control Extension. Here is a very simple example with some comments below the code:

/*  Generated by the OPA Hub Website 15/09/2020 13:47
Generated Example of Custom Input Extension for Oracle Policy Automation
 I will remember this is for demonstration purposes only. 
*/
OraclePolicyAutomation.AddExtension({
    customInput: function(control, interview) {
        if (control.getProperty("name") == "xSIRET") {
            return {
                mount: function(el) {
                    var div = document.createElement("input");
                    div.id = "xSIRET";
                    div.value = interview.getValue("siret", "record", control.instance);
                    el.appendChild(div);
                },
                update: function(el) {},
                validate: function(el) {
                    if (luhnChk(document.getElementById("xSIRET").value) == true) {
						interview.setInputValue("siret",document.getElementById("xSIRET").value, "record", control.instance);
                        return true;
                    } else {
                        return 'The string fails the Mod 10 Test'
                    }
                },
                unmount: function(el) {
                    if (control.getProperty("name") == "xSIRET") {
                        var xSIRET = document.getElementById("xSIRET");
                        xSIRET.parentNode.removeChild(xSIRET);
                    }
                }
            }
        }
    }
})

var luhnChk = (function (arr) {
    return function (ccNum) {
        var 
            len = ccNum.length,
            bit = 1,
            sum = 0,
            val;

        while (len) {
            val = parseInt(ccNum.charAt(--len), 10);
            sum += (bit ^= 1) ? arr[val] : val;
        }

        return sum && sum % 10 === 0;
    };
}([0, 2, 4, 6, 8, 1, 3, 5, 7, 9]));

As you can probably tell, what matters above is the luhnChk functiion (from the resource linked above) and the validate key. In Input Controls, the Validate needs to either return a boolean (true means the validation has succeeded and the test is passed, false means the validation has failed) or as a simpler alternative, return a string – this is considered to be a failure (false) and the string is used to display the error message. If you choose the pure boolean option then it is up to you to signal to the user that the validation failed.

This version works on instances of an entity, so the entity name and instance are used to retrieve and populate the value of the attribute. So it looks like this when the validation fails:

Luhn Test Example

It is important to note that this example is string based, so if you are planning on testing something different, you will need to strip out spaces, and convert the content to text.

If you are interested the demo 20C Zip File (free of charge) is in the shop, search for Luhn.

Video : Label Extension Overview

Video : Label Extension Overview

Here at the OPA Hub Website we always like to think that we are able to listen to our readers. Recently, one of the growing population of developers being asked to implement extensions came to us with a series of questions about a Label Extension.

And it became clear that a video was probably the most efficient way to address these queries. To be honest the OPA Hub Website finds that Video is over-used today in learning. I’ve nearly 30 years as an educator and consultant, I find it frustrating that education is constantly the target of cost-cutting and it means that even really large software providers think they can get away with selling poorly recorded slides with a soundtrack and call this a “learning program”. It’s definitely not a program, it’s an excuse.

Living in Europe and having worked in the States and elsewhere, I know how difficult it is to solve the equation of large distances, different languages and multiple timezones. But I still believe that face to face training is the best answer.

And I feel that although many other benefits exist for video training – immediacy, repeatability and accessibility – sometimes I find that companies push video or recorded training as another way to save money, while still expecting the same level of recall and interest from the students.

In a way, I see it also in the Covid phenomenon – how much video we have been consuming and how many of my colleagues have reached saturation point but are expected to be watching and doing video 7 or 8 hours a day. Of course I get that this is a necessity – but no allowance is made for just how hard it is to watch or deliver. Employers love the productivity it generates.

So this is why, the OPA Hub Website tries to keep the videos, where possible, to a maximum of 45 minutes at a time. Our Online Learning Program is based on that concept.

Anyway, enough mindless chatter : Here is a video introducing the concept of a Label Extension for Interviews, using the Intelligent Advisor Extensions API. The video talks about the basics, and shows lots of examples. We’ve got a few more videos in the pipeline, so watch this space.

video

If you want to watch the video in a new window on Youtube (yes, for once this is on Youtube) then just click the image below:

https://youtu.be/dbCfOWjktJ8

Spell Checking in Interview Controls

The other day, I came across a question regarding Spell Check in Interview Controls. You know the sort of thing – this would be useful for Inputs, but especially for Text Area Controls where there may be a considerable amount of text that will need spell checking. There are today several approaches but one that stands out.

The first option is to implement something in JavaScript – this has downsides for a couple of reasons. The dictionary for a given language, even compressed and specially structured, is going to be larger than average – the size of the file will make for slower processing. And the JavaScript will need to search this file. Thus, the performance might not be great. There are a couple of good toolkits that find innovative solutions, for example this one, but it will need work to build the apporopriate user interface.

The next option is to hand off some of the processing to the server-side. There are a number of spell check engines out there in open source that use PHP or ASP.NET for example. Some others use third-party servers or Google APIs that need payment. So for a simple spell check in Intelligent Advisor that sounds like a lot of effort.

The final spell check option is to leverage the browser itself. Most modern browsers support the spellcheck=”true” attribute value for inputs and text areas and lots of other text-content tags like <p> and <div>. So the simplest option is to switch on that attribute on any items you want to spell check. For example, add an invisible label extension to your Screen and use it scan all the relevant items on the page and add the spell check capability. For speed, the example below uses jQuery to select the relevant items for spell checking but you don’t need it of course, you can select using standard JavaScript too.

/*  Generated by the OPA Hub Website Code Generator 19/06/2020 18:27
Educational Example of Custom Label Extension for Oracle Policy Automation
I will remember this is for demonstration purposes only.
 */
OraclePolicyAutomation.AddExtension({
	customLabel: function (control, interview) {
		if (control.getProperty("name") == "xSpellCheckEnable") {
			return {
				mount: function (el) {
					console.log("Starting name:xSpellCheckEnable customLabel Mount");
					$(document).ready(function () {
						$("input[type='text'], textarea").attr('spellcheck', true);
					});
					console.log("Ending name:xSpellCheckEnable customLabel Mount");
				},
				update: function (el) {},
				unmount: function (el) {
					if (control.getProperty("name") == "xSpellCheckEnable") {
						console.log("Starting name:xSpellCheckEnable customLabel UnMount");
						console.log("Ending name:xSpellCheckEnable customLabel UnMount");
					}
				}
			}
		}
	}
})

With the above code in place, an input or text area will allow spell checking using the browser. Note the wavy line and the right-click:

Spell Check in IA

I’m not saying this is the perfect solution but there are some good and less good points:

  • No management of files needed
  • No user interface to create
  • Supported by the vast majority of browsers (see link above)
  • No server-side stuff to pay for
  • Applicable to pretty much any HTML tag

There are a few downsides

  • Usually defaults to the operating system / chosen language in the browser settings rather than the document language
  • Not the most exciting user interface
  • If you use multiple browsers you might end up with different word lists.

But sometimes, less is more. This example is free in the Shop. Happy Spell Checking!

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.

Intro Tooltips for Guided Assistance

I’ve been working with my other software (Oracle Siebel CRM) recently. As many of you know I’m the co-Founder also of https://siebelhub.com. I don’t contribute much to it these days as The OPA Hub Website takes up a fair amount of time, but I work with Siebel on a regular basis. One of the big things at the Siebel Hub is my colleague Alex, who has really become the star of the Siebel blogging world. He is also a great JavaScript guy, and Siebel has a big jQuery layer of extensible code which configurators can use to squeeze new User Experience out of the CRM. It’s like Interview Extensions on steroids – we can do all sorts of things with it that we would not do in Oracle Intelligent Advisor. And I was looking at tooltips and guidance implemented with  a library called intro.js

So, why am I mentioning it? Because the other day, I happened to be working on Siebel with this JavaScript library and I thought it would look great implemented in Oracle Intelligent Advisor. What does it do? Basically it provides a set of easy to use methods to create Hints (which you can think of as Tooltips) and also to create guided Introduction sequences. You can think of them as kind of animated introductions to your Interview. They have lots of features, and these are only two of the most obvious. Before we get into the details, let’s see what they look like in a short video.

video

Two Styles of intro.js

Basically it tries to demonstrate two different approaches  to working with intro.js – the targeted approach where the tooltips and so on are called up by the user, on demand, and the second one where the contents autoloads. Both are valid approaches and the autoload demonstrates the use of a JSON object – in this case an external file is not used but that opens up interesting concepts like storing the tooltips in an Excel Sheet in the Project and using our ability to access that data in the Interview.

intro.js with tooltips for Intelligent Advisor

Anyway, I hope you find it useful and you can get it in the OPA Hub Shop as usual. If you are interested in learning more about IntroJS, this book is on our current reading list. Note that this link is an affiliate link, purchases made from this link give a small amount to the OPA Hub Website which is used to pay for hosting the website.

JavaScript Extension : customEntityRemoveButton

JavaScript Extension : customEntityRemoveButton

Once again I came across this question on another forum, so I answered there and decided to reproduce it here in more detail. As some of you are no doubt aware, there are a number of smaller extensions in respect of Entity Collects, that all the developer to manage the process of deleting, or adding instances without having to completely redesign the Entity Collect which is a heavier task by an order of magnitude. customEntityRemoveButton is a good example.

The question, very pertinent I must say, concerned the deletion of instances, and the fact that there is no confirmation dialog. You click the button and the suppression just happens, without a chance to say “oops, didn’t mean that one”. Enter the customEntityRemoveButton!

customEntityRemoveButton 1

  1. An Entity Collect
  2. The Delete Instance Button that will be customized with a customEntityRemoveButton extension

The extension in question is known as a customEntityRemoveButton, and it has a unique handler which you might not have come across. This handler is known as setInstance – and the job of this handler is to provide the instance identifier. So, for a scenario, if you create three instances, then obviously each button needs to know which instance it belongs to, so to speak. This handler fires first (even before the mount handler it seems) so that you can recover the identifier and then use it to ensure the right button does the right job.

The example scenario is that the user would love to have a confirmation dialog. And since I’m often accused to using too much jQuery, this one is in native JavaScript. It would look like this perhaps:

/*  Generated by the OPA Hub Website 07/04/2020 17:54
Educational Example of Custom Remove Instance Button Extension for Oracle Policy Automation
I will remember this is for demonstration purposes only.
 */
 let mycontext = "";
OraclePolicyAutomation.AddExtension({
	customEntityRemoveButton: function (control, interview) {
		if (control.getProperty("name") == "xRemoveButton") {
			return {
				mount: function (el) {
					var div_parent = document.createElement("div");
					div_parent.id = "xButton_parent";
					el.appendChild(div_parent);
					console.log("Button mounted");
					makebutton(mycontext,el,control);
				},
				setInstance: function (el) {
					console.log("Button set Instance for " + el.toString());
					mycontext = el;
				},
				update: function (el) {
					console.log("Button updated for " + el.innerText);

				},
				unmount: function (el) {
					if (control.getProperty("name") == "xRemoveButton" ) {
						console.log("Unmount");
					}
				}
			}
		}
	}
})

function makebutton(instance, mycontext,control) {

	var div = document.createElement("button");
	div.id = "xRemoveButton" + instance;
		div.innerHTML = "Remove Me " + instance;
	div.onclick = function () {
		var goahead = confirm("Are you Sure?");
		

		if(goahead === true) 
		{control.removeInstance(instance);return false;}
	
	else{
		alert("No delete");return false;
	}
			
	};
	mycontext.appendChild(div);

}

I repeat that this is just a quick demonstration that I pulled together from somewhere in my head. The documentation on line is very thin concerning this particular handler and indeed these extensions in general.

customEntityRemoveButton 2

In the screenshot above and below you can see the new improved custom Button!

customEntityRemoveButton 3

Users now relax safe in the hands of our sanity checking dialog box 🙂

If you are interested in the Zip Archive just leave a comment and I will share it. This was done in 20A.

Have a nice day!

Input Extensions – Input Validation

Input Extensions – Input Validation

Following on from the recent posts about Errors and Input Extensions, this week we’re going to look at input validation and error handling. Not, you will understand, error handling in the JavaScript sense (writing try…catch and so forth) but how to handle errors that the user makes when entering data in your Input Extension.

Let’s set the scene with some simple examples. You have created an Input Extension in the form of an INPUT tag that displays an attribute for the user to enter. You intend to use the validate handler to do the work of testing the user’s data entry and flagging it to the user if they have made a mistake.

So you begin by understanding that the validation handler is ultimately a three way trigger : you can return true (in which case there is no error, and the data entered passes validation) or false (you wish to signal to the user there is an error, without an error message) or better still  a text string which means yes there is an error, and furthermore here is a text string to tell you what it is. For our little example, we will therefore be looking to handle true  and text string.

Basic Validation

var currentValue = document.getElementById("xInput").value;
var bBanana = document.getElementById("xInput").value === 'BANANA';

In the above example, we retrieve the current value of the INPUT and compare it to the text string “BANANA”. If you have entered “BANANA” then you have passed our validation (true) and if not (false).

if(!bBanana) 
{
return "JavaScript Validation Error";
}

Great. The case is solved, to paraphrase a famous detective. But then, one day, your Input Extension stops working. It mysteriously refuses to validate your user’s data entry, even when the data entry is correct. It simply refuses to let the user go forward, but there is no error message. So where is the problem coming from?

You take a look at the attribute you are supposed to be validating and notice that the rule designer has added something since you last looked:

Input Validation 1

So the rule designer has added a Regular Expression to the attribute. And what you are entering, perhaps, is not matching the RegEx. But how on earth are you supposed to check for that / handle that in an Input Extension? There is no documented process / property set for this, but if you dig down deep enough, you can find the following properties:

Input Validation – RegEx

control._source.config.inputRestriction.regularExpression (the RegEx)

control._source.config.inputRestriction.rawErrorMessage (the message)

The above properties give you access to the rule designer’s RegEx and associated error message. They do NOT, however, test the value of your input against the RegEx. So don’t forget to actually include the RegEx in your validate handler. At a simple level it might be something like this:

var regExpression = new RegExp(control._source.config.inputRestriction.regularExpression); 
var bTestInput = regExpression.test(currentValue);

Again, we will have a boolean variable which will tell us if the text entered has passed the RegEx validation or not. So now you can include this in your standard validation, to be able to present the user with reasonably decent message:

Input Validation - 3

OPA Hub Website Supporters can download an example project from the OPA Hub Shop. You’ll find the official reference online.

Input Extensions – DropDowns

Input Extensions – DropDowns

Many thanks to long-time reader and Oracle Policy Automation expert Aaron H for an interesting discussion just before the holiday season. The subject for this post is as you can tell, Input extensions that are dropdowns.

Our conversation was wide ranging but this article will focus on a couple of things

  1. How to ensure that the extension displays and handles the text and value elements of your list of values
  2. How to handle <uncertain>
  3. How to have a different label for <uncertain>

Along the way this will give us the opportunity to understand the usefulness of the Value() function in a rule. In later posts in this series we will look at other forms of Input, also beyond the basic INPUT or SELECT tag.

So let’s begin with a simple setup – the Zip Archive is available in the OPA Hub Shop by the way) – starting with just one attribute and a Value List:

The initial Value List looks like this – notice that in this case, there is no distinction between the displayed text and the actual value:

Input Extensions - DropDowns

In this simple scenario, one often sees extension code that focuses on the control.getOptions() method and then iterating through the various options from the returned object, something a little like this (for educational purposes only) :

var myChoices = control.getOptions();
for (key in myChoices) {
if(myChoices[key].value)
{
$('#xDropDown').append('<option value="' + myChoices[key]..text.toString() + '">' + myChoices[key].text.toString() + '</option>');
}
}

The code works fine, but makes a few assumptions that can come back and bite later when the rule designer has made changes.

  1. It does not take into account the possible change in the Value List to include display and values.
  2. It will error out if the dropdown becomes non-mandatory since “uncertain” will cause .toString() to fail

So when the developer of the rule changes the Value List to something like this:

Input Extensions - DropDowns 2

The code would no longer be useful since the [key].text and [key].value are two different values. And if we are updating the underlying control, we need to remember that we call control.setValue() so it is expecting a value, not the display value.

So maybe the code gets changed to :

 $('#xDropDown').append('<option value="' + myChoices[key].value + '">' + myChoices[key].text.toString() + '</option>');

Or something similar. All is well and the dropdown is correctly handling things :

Until the attribute is defined as non-mandatory in the Screen where it is displayed. At which point the code breaks again, as the uncertain value is not handled. Let’s take a step back and remind ourselves of the defaut behaviour in these situations, without an extension:

The standard control renders an empty option for the uncertain value. I’ve always considered it a bit of a bug that it does not respect the optional Display Value (in my case, “Not Sure” – see the screenshot a little further up) but always renders a blank, at least in all my browsers.

So in the case of an Input Extension that needs to render the uncertain value (because the control is not mandatory) and also wants to show the Display Value, the code will probably need to have another quick change:

Input Extensions DropDown Code Last One

Which will ensure that the dropdown is rendered with the correct text and value, if there is one. Also, the added bonus is that the display text of uncertain is rendered as we would expect:

Input Extension Showing Uncertain Vlaue

And finally, we have good use of the Value() function so that we can be sure that the correct value is stored in our Interview:

The function above, in a Word document for example, will return the value rather than the display value. So you can drop it onto the final Screen of your testing Project and compare the two to make sure you have gathered the correct one.

Hopefully that was fun and interesting, and you can practice yourself with your own project. As mentioned above the code is available in the OPA Hub Shop. The documentation is of course on the Oracle Intelligent Advisor website.

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.

Most Popular Downloads on this Site

Most Popular Downloads on this Site

We used to say that anything with “Google Maps” in the title was a sure-fire winner when it came to people downloading examples – after all Google Maps used to be so easy to get into, and so many people just “get” why a map is useful, that it was absolutely the go-to example. But is it still the case? Google APIs now need a Billing Account, and an API key, which in turn needs to have domain restrictions, and other administrative elements. It’s not quite as easy as it used to be.

So we set out to look at the different examples that have been downloaded on this site. And here are the results. Interesting. Under the graph, some comments and remarks which might explain some of the data.

Most Popular Downloads

Custom Google Maps JavaScript Label Extension Example 21

Custom Dynamic Options JavaScript Extension Example 21

Didn’t expect that one to be in there at all!

Custom JSON Search JavaScript Extension Example 19

Same for this one. Maybe Search is the new Map?

Custom Entity Container Extension Example  17

Google Maps as Custom Input Control Extension 15

Ah, see, the combined score is going to be huge.

Custom JavaScript Extensions Map with Google Places and Custom Options List  12

Told you. Google Maps reigns supreme!

Custom Header as a Timer JavaScript Extension 12

Custom Year Picker JavaScript Input Extension Example 9

JavaScript Extension Entity Collect Control 7

JavaScript Entity Collect Extension Excel Data Load 6

Custom Signature Extension Example 6

Wow. This one isn’t even really an extension!

JavaScript Extension Search Examples – Airlines, Great Circle Mapping, Airports 6

Everyone loves planes. I get that.

Embed Website in Interview Label Extension 5

JavaScript Extensions with a Live Entity-based Chart with D3 5

Everyone hates D3. I get that.

JavaScript Extension Search Example – Railways 5

Not as much fun as airplanes.

Loader Image in Entity Instances Search Extension 4

JavaScript Extension fullCustomInput Example 4

JavaScript Extension Custom Label Detail Pop-up 4

Calendar Input Extension Blackout Dates 3

JavaScript Extension Search Example – Siebel REST API 3

JavaScript Extension Relationship Control 2

JavaScript Label Extension Leaflet JS Map 2

Wow. This is the free alternative to Google Maps. I would have imagined this to be more popular.

Force PDF Click Button Extension and Label  1

As you can see from the Chart, Google Maps is hanging on – but only just! It’s ex aequo with the Search Extension. However if you pool together all the Google Maps stuff, it completely wipes the floor with the competition. Definitely the most popular downloads.

Want even more downloads?

If you are interested in even more examples (including a complete Entity Collect, a Carousel, Breadcrumbs, lots of Inputs and more, then you will be interested in our new book, JavaScript Extensions for Oracle Policy Modeling.

Worldwide
Logo by Southpaw Projects LLC