json and javascript tips and tricks -...

27
Scott Klement Director, Product Development and Support Profound Logic JSON and JavaScript Tips and Tricks Copyright © 1999-2016 Introduction To JavaScript and JSON How To Learn JavaScript How It Fits Into Profound UI Profound Events and APIs Debugging JavaScript Incorporating JavaScript Libraries • Examples How JSON can Help Simplify Session Agenda

Upload: phambao

Post on 28-Jun-2018

282 views

Category:

Documents


3 download

TRANSCRIPT

Scott KlementDirector, Product Development and Support

Profound Logic

JSON and JavaScript Tips and Tricks

Copyright © 1999-2016

• Introduction To JavaScript and JSON

• How To Learn JavaScript

• How It Fits Into Profound UI

• Profound Events and APIs

• Debugging JavaScript

• Incorporating JavaScript Libraries

• Examples

• How JSON can Help Simplify

Session Agenda

Copyright © 1999-2016

What are JavaScript and JSON?

JavaScript

• Scripting language developed by Netscape

• Originally developed for use in web browsers to make screens more interactive

• Very, very popular, used in almost all web sites

• Also available outside of browsers (Node.js)

JSON

• JavaScript Object Notation

• Simple (or "shorthand") way to set values in JavaScript

• Now used separately from JavaScript as a document format

Copyright © 1999-2016

How Popular?

Top 9 languages (of

316 that GitHub

recognizes) shown

Copyright © 1999-2016

What JavaScript is NOT

"JavaScript is to Java what Hamster is to Ham"

Copyright © 1999-2016

We use it to create the products themselves

• Visual Designer, Genie, Atrium, Genie Admin, Mobile, etc.

Customers can use it as well

• Make your screens react as users use the mouse or keyboard

• Update screen without going back to server-side code

• Write your own "automatic" transforms in Genie

• Custom DDS Conversion

• Make your own widgets

• Incorporate 3rd party web frameworks and tools

• And so much more!

docs: http://www.profoundlogic.com/docs/display/PUI/JavaScript+Coding

Role in Profound UI displays

Copyright © 1999-2016

JavaScript is a complete programming language, and too much to learn in this session

• I can explain some basics

• If you know another language, it shouldn't be too hard to adapt

• I can provide links to where you can learn more

• Main focus is how to use it in Profound UI displays

• Profound UI displays usually use short/simple snippets of code

Resources for learning JavaScript

• W3 Schools Tutorial (online) http://www.w3schools.com/js/default.asp

• W3 Schools JavaScript Reference (online)

http://www.w3schools.com/jsref/default.asp

• SitePoint (books/e-books) https://www.sitepoint.com/

Learning JavaScript

Copyright © 1999-2016

Quick JavaScript Basics (1 of 3)

Declaring and Comparing

• declare a variable with var

• type of variable is determine by what is assigned to it – and can change.

• A single =means "assign value"

• Double == means "compare" data types will be converted if necessary

• Triple === means "compare" but result only matches if it’s the same data type

var myString = "Hello World";

var myNumber = 1;

var myArray = [ "Monday", "Tuesday", "Wednesday", "Thursday", "Friday" ];

if ( myVariable == "something") {

doSomething();

}

else {

doSomethingElse();

}

if ( myNumber == "1" ) // works!

if ( myNumber === "1" ) // doesn't work, different types

Copyright © 1999-2016

Quick JavaScript Basics (2 of 3)

while ( myNumber > 1) {

// do something while myNumber > 1

}

do {

// do while myNumber > 1, test condition at end of loop.

}

while ( myNumber > 1 );

for (var x=1; x<=10; x++) {

// do something 10 times.

}

var employee_rec = {

first: "Scott",

last: "Klement",

num: 1000

}

for (field in employee_rec) {

// do something for each field in an "object" (data structure)

console.log(field + " = " + employee_rec[field]);

}

Copyright © 1999-2016

Quick JavaScript Basics (3 of 3)

function printSomething( something ) {

console.log(something);

}

// prints "Hello World"

printSomething("Hello World");

// functions can be variables – allow for "callbacks"

// this function automatically calls a routine "num" times.

function repeat( num, callback ) {

for (var x=1; x<=num; x++) {

callback(x);

}

}

// this will print 1-5 on the console display

repeat( 5, printSomething);

// anonymous functions are functions defined on-the-fly just to assign

// to variables or parameters. This prints 1-5 with "call number" before it.

repeat( 5, function(n) { printSomething("call number " + n)});

Copyright © 1999-2016

Tutorials and Books Assume You Write HTML Manually

Consider this example from W3Schools.com's JavaScript Tutorial;

In Profound UI, you drag/drop widgets to make your screen rather than coding HTML. So how

would you use this example in a Profound UI Display?

Tutorials/Books Assume HTML

<script>

function myFunction() {

document.getElementById("demo").innerHTML = "Paragraph

changed.";

}

</script>

<h1>My Web Page</h1>

<p id="demo">A Paragraph</p>

<button type="button" onclick="myFunction()">Try it</button>

Copyright © 1999-2016

Profound UI Equivalents of Tags Are Widgets

There are equivalent properties in Profound UI (Rich Display or Genie)

A Label widget replaces the <p>

(paragraph) HTML tag.

A Button widget replaces the <button>

HTML tag.

<p id="demo">A Paragraph</p>

<button type="button"

onclick="myFunction()">

Try it

</button>

Copyright © 1999-2016

Events Are Properties Of The Widgets

Widgets have properties that correspond to all of the events. You can simply code your JavaScript

in the property field. If you click the button it will provide a code editor with syntax

highlighting, etc.

Copyright © 1999-2016

Event Properties Can Call JavaScript Kept in a Script File

When your code gets more sophisticated, or you want to reuse it, etc, it should

be placed in a file in the IFS. Once set up, you'll be able to call the function

from your JavaScript events

Copyright © 1999-2016

Where Do I Put My Script File?

Docs: http://www.profoundlogic.com/docs/display/PUI/Code+Organization

You can place it in a stream file (PC-style) in the IFS

• /www/YOUR-INSTANCE/htdocs/profoundui/userdata/custom

• It must end in .JS

• It can go in any subdirectory beneath custom

• For example, I might create a subdirectory named jsdemo for my scripts

• In Genie, you must add it to the start.html file

<script type="text/javascript"

src="/profoundui/userdata/custom/jsdemo/example.js"></script>

• The src= in <script> tags only includes directories beneath htdocs

• The Rich Display controller (/profoundui/start URL) and Visual Designer will automatically load

files in that directory when they are restarted or refreshed

• Mobile apps should use the "external javascript" property

• You can use any editor for JavaScript, but Notepad++ (free) and RDi are good ones.

Copyright © 1999-2016

Example Function in a Script File

This function is placed in /www/MY-INSTANCE/htdocs/profoundui/userdata/jsdemo/test.js

function myFunction() {

document.getElementById("demo").innerHTML = "Paragraph changed";

}

function myFunction(){

pui.set("demo", "Paragraph changed.");

}

Modifying an element's innerHTML works nicely for an output field, but for other field

types it can cause problems. This is because Profound UI widgets are built by putting

HTML tags in the page, and then adding their own functionality beyond that.

Profound provides APIs thare are better (and shorter/simpler) for setting/getting values.

Instead of innerHTML, use the pui.set() API.

docs: http://www.profoundlogic.com/docs/pages/viewpage.action?pageId=17137692

Copyright © 1999-2016

Tip: Common Profound UI APIs

• pui.get(id) (alias: get) = retrieve the value of a widget

• pui.set(id, "newValue") (alias: changeElementValue) = set the value of a widget

• getObj(id) (alias for document.getElementById) = get an underlying browser DOM

object for an id.

• applyProperty(id, propertyName, value) = change a widget's property

• pressKey(keyName) = press a function key or enter

• pui.click(id) = click a button on a Rich Display (with no id, just submits the screen)

All of the JavaScript APIs are found in our documentation under

• http://www.profoundlogic.com/docs

• JavaScript Coding

• API Reference

Since Profound UI widgets frequently do things above and beyond what the underlying

HTML tags can do, we recommend using our APIs instead of DOM properties like

innerHTML, value, etc.

Copyright © 1999-2016

Tip: Avoid Naming Conflicts With Objects

The JavaScript code that runs in a given page must co-exist.

• What if Profound UI (now or in the future) had a function named myFunction?

• What if you decided to use a 3rd party tool, and it happened to use myFunction?

• You can minimize this risk by making your own "namespace" using an object.

// Create an "acme" object if it does not already exist

if (typeof acme == "undefined") acme = {};

// Now you can define functions (or variables, etc) that start with "acme."

// which greatly reduces the chance of a conflict

acme.myFunction = function() {

pui.set("demo", "Paragraph changed.");

}

I recommend naming the namespace a short name, based on the company or software

you're writing. For example, if you work for Acme, Inc. you might do this:

Copyright © 1999-2016

Profound UI Has The Browser Events and More

An event runs (or "fires") when something happens. A lot of JavaScript code runs during

events. Thinking about code in terms of it running when an event occurs is important in

JavaScript.

In the preceding example, I used the onclick event of a button widget, so the code ran

when the button was clicked.

All of the events you'll find in HTML are in Profound UI as well. Plus there are many

additional events that are unique to Profound UI.

There isn't time to cover all events in this talk, but I've listed them for you to read on the

following slides.

docs: http://www.profoundlogic.com/docs/display/PUI/Code+Organization

Copyright © 1999-2016

Standard Widget-Level Events (Cursor Movement)

Standard Events on all Profound UI Widgets. These are run when…

• onfocus = the text cursor ("caret") moves to this widget. This can happen by

"tabbing" to the widget, or by clicking on it with the mouse. In either case, the caret

will move to the widget and keyboard input will go to this widget. This is referred to

as "having focus."

• onblur = focus leaves a field. This is called "blur" because it is the opposite of focus.

• onmouseover = the mouse cursor is moved over a widget. (Does not work on touch

screens.)

• onmouseout = the mouse cursor is moved away from a widget. It is the opposite of

onmouseover. (Does not work on touch screens.)

• onmousemove = run whenever the mouse is moved above a widget. This is run for

every movement, no matter how slight, so be careful what you code here, it will be

run many times!

Copyright © 1999-2016

Standard Widget-Level Events (keyboard/mouse buttons)

Standard Events on all Profound UI Widgets. These are run when…

• onchange = run after a user has changed a widget.

• onmousedown = run when the mouse button is pressed down

• onmouseup = run when the mouse button is released

• onclick = run when the left or right mouse button is clicked on a widget.

• ondblclick = run when the mouse button is double-clicked on a widget

• onkeydown = run when the widget has focus and the user pushes down a key on the

keyboard

• onkeypress = run when a user presses a character-generating key. (This event is

deprecated by the current browser standards, and is inconsistent across browsers. I

recommend onkeydown instead.)

• onkeyup = run when the widget has focus and the user releases a key on the

keyboard

Copyright © 1999-2016

Standard Record-Format Events

These events are configured at the record-format level

• onload = run when a record format has finished loading

• onsubmit = run when the display is submitted back to the server. This event should

return true normally, or false to stop the display from submitting to the server

Record Format Events Only Available in Genie

• onpageload = run when 5250 screen has loaded, but before customizations

• subfile row onclick = run when a row is clicked on a subfile that was created by

"detect subfile" without "detect subfile patterns"

• subfile row ondblclick = run when a row is double-clicked on a subfile that was

created by "detect subfile" without "detect subfile patterns"

Copyright © 1999-2016

Drag and Drop Events

In Output Field, HTML Container, Image and Grid widgets (Rich Display File Only)

• ondragstart = run when user begins drag/drop for this widget

• ondragenter = run when a widget is dragged over a drop target

• ondragleave = run when a widget is dragged out of (leaves) a drop target

• ondrop = run when the user drops (button is released) a widget

Copyright © 1999-2016

Widget-Specific Events

Menu Widget

• onoptionclick = run when user clicks a menu option

Fusion Chart Widget

• onchartclick = run when user clicks a chart section in a Fusion Chart widget

ComboBox or Textbox with Auto-complete

• onselect = run when a selection is made from the selection list

Spinner Widget

• onspin = run when the user clicks the up/down arrows on a spinner widget

File Upload or File Upload Drag/Drop Widget (Genie only)

• onupload = run when the user uploads a file to the IFS.

Copyright © 1999-2016

Grid (Subfile) Widget-Specific Events

These events only exist in the Grid Widget

• onrowclick = run when a row is clicked

• onrowdblclick = run when a row is double-clicked

• onrowmouseover = run when the mouse is moved over a row

• onrowmouseout = run when the mouse is moved out of a row

• onpagedown = run when the user pages down in the subfile. You should return true

to allow the page down, or false to stop the grid from paging

• onpageup = run when th user pages up in the subfile. You should return true to allow

the page up, or false to stop the grid from paging

• onscroll = run when the user scrolls the grid with the scrollbar

• onfilterchange = run when the user changes the grid's filter

Copyright © 1999-2016

Global Events

These events are not defined in properties. Instead, they are defined in your JavaScript

code. Once set, they persist for the entire session (or until you un-set them.)

• pui.inputfilter = run for each field submitted to the server, allows you to filter out

unwanted ("garbage") characters.

• pui.onbeforetimeout = run before a timeout occurs, this event can return false to

prevent Profound UI from doing timeout processing (requires client-side timeouts

enabled)

• pui.onload = runs each time any Rich Display record format has loaded, before

running the record-format's onload property event. (Rich Display only)

• pui.onoffline = run when a connection cannot be made to a server. Used by mobile

apps when they wish to do their own processing (such as save data locally, show

locally-stored display records, etc) when the server is not available.

• onsubmit = run before each display is submitted to the server

• ontimeout = runs after client-side timeout processing has ended the session on the

server. Allows you to control what happens (ex: print a custom message, start a new

session, etc.)

Copyright © 1999-2016

Global Events, continued…

These events are not defined in properties. Instead, they are defined in your JavaScript

code. Once set, they persist for the entire session (or until you un-set them.)

• pui.onuseractivity = run every time the user moves the mouse or presses a key.

Usually used for writing custom timeout handling routines.

• pui.overrideSubmitUrl = run when calculating the URL to submit responses to. Can be

used to modify the URL, for example so that additional data appears in Apache logs.

• pui.validate = runs for each modified field in a Rich Display record format that the

user has modified. Routine can prevent submission by returning an error message, or

can modify field values before they are sent to the server.

Copyright © 1999-2016

Global Events (Genie-Specific)

These events are defined in your Genie JavaScript code (such as custom.js) and usually

used to perform rule-based screen customizations.

• afterLoad (function) = run after every 5250 screen has been rendered and

customizations applied. The function must be named afterLoad()

• beforeLoad (function) = run before every 5250 screen has been rendered. The

function must be named beforeLoad().

• customize (function) = used to write code that customizes a screen in JavaScript (as

opposed to using the Genie Designer for customizations.) Run after the beforeLoad()

function, but before designer-based enhancements are rendered, for each 5250

screen. The function must be named customize()

• pui.genie.afterInit = run after automatic enhancements have been applied, but before

designer-based enhancements are applied.

• pui.onPCCommand = run when the STRPCCMD command sends a command, allows

you to write your own custom pc command tool.

• pui.onshutdown = run when a Genie session is being ended

Copyright © 1999-2016

Example: Totalling a Grid

Grid has id=PRODSFL

and we want to total the field

named PSTOCK

Copyright © 1999-2016

Tip: Manipulating Grid Data Values

When a grid in a Rich Display is loaded using the traditional method (such as the WRITE opcode from RPG) you can access the values of the fields on the display with the following grid methods:

• gridObject.grid.getDataValue(row, "fieldname");

• gridObject.grid.setDataValue(row, "fieldname", "newValue");

• gridObject.grid.getAllDataValues(use-filter);

• gridObject.grid.isRowFilteredOut(row);

docs: http://www.profoundlogic.com/docs/display/PUI/Grid+Methods

Notes:

• gridObject is an object that refers to the grid. Use getObj("id") API to retrieve it

• row is the row number (subfile RRN) to retrieve or set

• "fieldname" is the DDS field name to set

• "newValue" is the new value you'd like to set.

NOTE: the dataValueAPIs are unusual in that they refer to DDS field names. Almost everything else refers to the id property of the widget.

A common mistake is to confuse these.

Copyright © 1999-2016

Coding a Totalling Function

NOTES:

• to make it work on more than one grid, we take the id of the grid and the field name as parameters

• getObj() gives us the HTML DOM object of the grid

• getAllDataValues() returns the entire content of the grid the "true" parameter tells it to exclude rows that are filtered out (if filters are used)

• Number() forces the content of the field into a numeric data type

acme.total_grid_field = function( gridName, field ) {

var total = 0;

var data = getObj(gridName).grid.getAllDataValues(true);

for (var x=0; x<data.length; x++) {

total += Number(data[x][field]);

}

return total;

}

Add this below the "myFunction" example, using the "acme" object as before.

Copyright © 1999-2016

Adding the Totals to the Display File

NOTES:

• Drag an output field below the subfile

• Set the id = total

• Right-click and unbind FIELD0001 from the value

• Set the value to something like "total will go here". (This will be replaced.)

Copyright © 1999-2016

Run the total routine from the onload event

Set up the JavaScript to be run

• click an empty space on the screen so the properties box shows "Screen properties"

• Find the "onload" property

• Set it to JavaScript that calls our total function

pui.set("total", acme.total_grid_field("PRODSFL", "PSTOCK"));

NOTES:

• This calls our function, passing the id and field name when the display has loaded

• the output of our function is passed to pui.set() which sets the total field we added

• JavaScript and ids are case-sensitive, it's important to keep the upper/lower case the same

• Since we changed the display file, we need to compile and re-run the program

• If we had only changed the script, we could use pui.refresh() to re-load it without compiling

Copyright © 1999-2016

Now the total is there – but so what?

Copyright © 1999-2016

So what? I could've done that from RPG!

Yes! But…

• RPG (or Cobol, PHP, Node.js – any server-side code) runs before the display is loaded

• Since ours ran in the "onload" event, so it looked about the same.

• What if you wanted to change it without going back to the server and re-loading the

display? With JavaScript you can change it on any event!

Try this:

• Select the grid

• Find the "onfilterchange" event

• Put the same code that we ran in "onload" in that event – it now runs anytime the

user changes the filter!

Copyright © 1999-2016

Tip: How Do I Format Numbers?

When a Field Value is Set With JavaScript

• If it is a textbox (or other input-capable field) and bound to a DDS variable, the value

can be sent back to the server

• The binding dialog does NOT affect the format of the field you set with JavaScript.

You must do the formatting in your JavaScript code

var newVal = 10.50;

pui.set("total", newVal );

// the above will display as 10.5 not 10.50!

// it does not matter if you specified 2 decimals in your binding dialog

// since this is not coming from the server program.

Solutions…

• Most newer browsers (Chrome, Firefox, IE11, etc) support toLocaleFormat() and

Intl.NumberFormat() which have some good number formatting tools

• You can always download a 3rd party tool, or write your own…

Copyright © 1999-2016

The Acme Number Formatter

acme.numberFormatter = new Intl.NumberFormat("en-US", {

useGrouping: false,

minimumIntegerDigits: 1,

minimumFractionDigits: 2

});

acme.format = function(num) {

num = Number(num);

if ( num === 0 || isNaN(num) ) {

return "";

}

else {

return acme.numberFormatter.format(num);

}

}

Intl.NumberFormat

• Second parameter is a JSON object specifying the formatting options

• Since I'm running this outside of a function, it is run when my script is loaded and will

be available when acme.format() is called later.

Copyright © 1999-2016

Formatting Numbers

Options Used

• en-US = use the convention used in the USA. Period for decimals, comma as a thousands

separator

• minimumIntegerDigits = show at least X digit(s) to the left of the decimal place

• minimumFractionDigits = show at least X digit(s) to the right of the decimal place

• useGrouping = whether to show thousands separators (true=show, false=don't)

Note: Intl.NumberFormat (and toLocaleFormat() which is similar) is not a feature of Profound UI, it

is part of the browser. Read more here:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat

var newVal = 10.5;

pui.set("total", acme.format(newVal));

// the above will display as 10.50

Copyright © 1999-2016

Example: Update Totals as they Change

This display is for entering new invoices

It uses the new RPG ALIAS feature to allow long names

The Item Description, Quantity and Price fields are textboxes

(input-capable.)

We want the [line_total] and [total] fields to update as they change

the prices or quantities!

Copyright © 1999-2016

JavaScript to Re-Calculate the Totals

acme.recalculate_invoice = function() {

var itemsGrid = getObj("itemsGrid").grid;

var total = 0;

for (var rrn=1; rrn<=itemsGrid.getRecordCount(); rrn++) {

var quantity = itemsGrid.getDataValue(rrn, "quantity");

var price = itemsGrid.getDataValue(rrn, "price");

var line_total = quantity * price;

total += line_total;

itemsGrid.setDataValue(rrn, "line_total", acme.format(line_total));

}

pui.set("total", acme.format(total));

}

Notes

• getObj(id).grid gets the grid field of the object, saving us some typing

• getRecordCount() tells how many rows are in the grid.

• getDataValue() and setDataValue() are used to get/set the grid values

Copyright © 1999-2016

Run the JavaScript in the onchange event

Change the Display File

• To run this, select the [quantity] field, then ctrl-click the [price] field. Now both are

selected.

• Find the onchange property, and set it to: acme.recalculate_invoice()

• Compile and run the display file. When values are changed, the total updates!

• Notice the way the numbers are formatted

Copyright © 1999-2016

Using the Browser's Developer Tools

Internet Explorer

• Click the "gear" (menu) and select F12 Developer Tools

• or, click outside the Profound UI display (such as in the URL bar) and press F12

Chrome

• Click the menu (…) and select more tools / developer tools

• or, press ctrl-shift-I

Firefox (built-in tools)

• Click the "Firefox" menu, then Web Developer

• or, press

Firefox (Firebug add-on)

• Use the Firebug icon near the URL bar

Copyright © 1999-2016

Some Developing/Debugging Tricks

To Reload Scripts from the Server Without Restarting Profound UI

• Use developer tools

• Select the console tab

• Type pui.refresh() at the prompt

• In fact, you can run any JavaScript at the console prompt, an easy way to test stuff out

• Likewise, pui.refresh() could be called from your display file's events

To Debug Scripts

• The exact mechanism varies from browser to browser, but…

• Each has a debugger in the developer tools

• All allow you to set breakpoints, view variable values as it runs, etc.

• You can select from the JavaScript files in memory to find yours

• Very powerful! (more-so than the IBM STRDBG or even RDi debugger!)

Copyright © 1999-2016

Try the Developer Tools!

Try Refreshing

• Change useGrouping to true, save your changes

• Go to the developer tools, select console, type pui.refresh()

• Watch the formatting change on the display!

Try Debuggging

• Go into the developer tools

• In the debugger, find your script file (acme.js or whatever you named it)

• Set a breakpoint in the acme.recalculate_invoice function

• Change a value (or use pui.refresh() to reload the display) and see it work

• Try viewing values, stepping through code, etc.

Copyright © 1999-2016

Trick: Debugging Inline Code

To Debug Code NOT In a Separate File (coded directly in a Profound UI property)

• Add a line that contains this statement: debugger;

• Open the developer tools

• Run the script – notice it stops on "debugger", like a breakpoint.

• Don't forget to remove the debugger line once you're finished debugging.

Copyright © 1999-2016

Tip: Use the Console To Find Errors

Finding Errors in Code

• The developer tool console will show any errors in JavaScript (unless the code used "catch" to catch them.)

• Some Profound UI specific events will catch errors and display them in a popup

• For example, imagine your script file started like this:

if (typeof acme == "undefined") acme = {};

something.invalid.is=0;

Copyright © 1999-2016

Trick: Log Your Own Messages To the Console

When Breakpoints Are Clumsy

• Sometimes setting a breakpoint is impractical, for example, for an event that runs many times, clicking "continue" in the debugger until you get to the right instance can be frustrating

• Try adding code that uses console.log() to print debug info to the developer's console, instead!

for (var rrn=1; rrn<=itemsGrid.getRecordCount(); rrn++) {

var quantity = itemsGrid.getDataValue(rrn, "quantity");

var price = itemsGrid.getDataValue(rrn, "price");

console.log("row:" + rrn + " price:" + price + " qty:" + quantity);

.

.

Copyright © 1999-2016

Tip: You Can Use Other JavaScript Libraries/Frameworks

Since Profound UI uses standard web technologies (HTML5, CSS, JavaScript) you can use it together with almost any JavaScript library.

Like the JavaScript tutorials, the library examples will show HTML tags, but you can adapt them. For example, here's a free library (Walter Zorn's Tooltips) that creates tooltips with HTML capabilities:

http://www.walterzorn.de/en/tooltip/tooltip_e.htm

You can incorporate it into Profound UI by:

• Download the zip file from the above link

• Unzip it into the /www/YOUR-INSTANCE/htdocs/wz_tooltip directory

• Add a <script> tag into your start.html file, just inside the <body> element

• For Genie, start.html is in your Genie skin, and can be edited in the Genie Admin

• For a Rich Display, it is found in the following IFS file:

/www/YOUR-INSTANCE/htdocs/profoundui/userdata/html/start.html

Copyright © 1999-2016

Example Start.html (Genie shown)

For example, in Genie I would add the <script> tag as follows:

Copyright © 1999-2016

Trying Out Zorn's Tooltips

Next time you re-load (or use pui.refresh()) it will load Zorn's tooltip library into memory.

You can now call it's routines. The docs tell you to use the onmouseover and onmouseoutproperties of an HTML tag, but in Profound UI, use the widget properties instead.

Copyright © 1999-2016

Another 3rd-party Example From Our Docs

There are many thousands of JavaScript tools on the Internet that you can use!

For another example, if you want more editing capabilities in your application, check out TinyMCE, from the Profound UI documentation.

http://www.profoundlogic.com/docs/display/PUI/Integrating+TinyMCE+Editor

Copyright © 1999-2016

Tip: Use JSON to simplify

JSON is JavaScript Object Notation – a "shorthand" for populating objects. I've already shown one

example when doing number formatting. Compare these definitions:

var options = new Object();

options.minimumIntegerDigits = 1;

options.minimumFractionDigits = 2;

options.useGrouping = false;

The regular ("longhand") way

var options = {

minimumIntegerDigits: 1,

minimumFractionDigits: 2,

useGrouping: false

}

The JSON ("shorthand") way

Using JSON format makes things simpler by eliminating the need to type the object name, or to split

the code into multiple lines. For parameters you can define and pass them in one line.

var options = new Object();

options.useGrouping = false;

var fmt = new Intl.NumberFormat("en-US", options);

-vs-

var fmt = new Intl.NumberFormat("en-US", { useGrouping: false });

Copyright © 1999-2016

Tip: Use JSON For Your ACME Code

acme = {

total_grid_field: function( gridName, field) {

. . . code here . . .

},

numberFormatter: new Intl.NumberFormat("en-US", {

. . . code here . . .

}),

format: function(num) {

. . . code here . . .

},

recalculate_invoice: function() {

. . . code here . . .

}

}

Using JSON can make your code simpler, even when defining a file full of routines, like the acme.js

file we built earlier.

The bodies of the functions are omitted for brevity, but they are the same as they were before, only

the acme.xxx = function() part is replaced.

Copyright © 1999-2016

Questions?

For more goodness:

Read about what's happening at Profound Logic in our blog:

http://www.profoundlogic.com/blog/

Share the cool stuff you can do with Profound UI, and discuss JavaScript programming with other customers in the Profound Logic forum:

http://www.profoundlogic.com/forum/

If there's time left, I'm

happy to answer your

questions.