This document discusses techniques for developing responsive user interfaces for Uniface applications. It begins with a recap of coding dynamic server pages (DSPs) using JavaScript and a comparison of ProcScript and JavaScript operations. It then covers topics like activating operations, promises, scoping, HTML5 widgets, validation, CSS classes, tabs, modality, navigation, icons, data paging, security, and code performance. The document concludes with a walkthrough of a demo WebStart application and resources for further information.
6. Comparing ProcScript vs. JavaScript
Server <Detail> trigger
- button clicked
trigger detail
public web
webmessage "Button clicked"
return 0
end; trigger
Also onFocus, onBlur etc. in Extended Triggers
Browser Extended trigger
- editbox changed
webtrigger onChange
javascript
alert(this.getValue());
endjavascript
end ; trigger
7. Comparing ProcScript vs. JavaScript Operations
Server Operations
operation Update
public web
params
string pOptions: IN
endparams
; ProcScript Code
return 0
end ; Update
Browser Operations
weboperation Update
params
string pOptions: IN
endparams
javascript
// JavaScript code
endjavascript
end ; Update
8. Activating Operations
Call weboperation from server (queued)
webactivate $instancename.save()
Call server operation from browser (asynchronous)
this.getInstance().activate("save");
- use promises to control flow
9. operation getLocation
public web
params
string address : in
numeric latitude : inout
numeric longitude: inout
endparams
call CalcCoordinates(address, latitude, longitude)
end ; getLocation
Promises
webtrigger onClick
javascript
this.getInstance().activate("getLocation",address,null,null)
.then(
function(out){
google.maps.locate(out.args[1], out.args[2]);
},
function(e) { alert("Error getting the location !"); }
);
endjavascript
Get Location from GoogleJavaScript Activation Example
4
1
2
3
Browser
Server
Get Location Button
10. Scope
Controls data sent &
received between
browser & server
Scoping operations
block, prevent race
conditions
output input
trigger detail
public web
scope
input
output
operation AnotherDSP.show
endscope
activate "AnotherDSP".show()
return 0
end; trigger
11. Dynamic Scope
operation storeData
public web
scope
input
output
operation myInstanceList().store
endscope
variables
string vInstList, vInstName
endvariables
vInstList = $replace(MODIFIED_INSTANCES, 1, ";", ";", -1)
forlist vInstName in vInstList
newinstance "SUB_DSP", vInstName
activate vInstName.store()
endfor
end ; storeData
output input
weboperation myInstanceList() returns
JavaScript array of Instance Names
12. HTML 5 widgets: bound error labels
Field validation error handling when the user tabs or clicks away from a field.
Associate an error label via the ID attribute with prefix ‘uflderror:’
15. CSS class:classname vs. html:class
putitem/id $FieldPropertes("select.buttons"), "class:btn-lg", "true"
putitem $FieldPropertes("select.buttons"), "!class:btn-lg"
javascript
field.setProperty("!class:btn-lg");
endjavascript
putitem/id $OccProperties("order"), "class:selected", "true"
putitem/id $EntityProperties("order"), "class:empty", "true"
Use class:classname property instead of html:class to change individual classes:
16. CSS Attributes
Add Attribute
putitem/id $OccProperties("ORDER"),"html:data-selected", "true"
HTML
<table id="uent:ORDER.POS" class="table table-hover">
<tbody>
<tr id="uocc:ORDER.POS" data-selected>
<td><span id="ufld:CODE.ORDER.POS">Code</span></td>
<td><span id="ufld:DESCR.ORDER.POS">Name</span></td>
</tr>
</tbody>
</table>
JavaScript Find
var elements = document.querySelectorAll('tr[data-selected]');
jQuery: $('tr[data-selected]').each(…) or $('tr[data-selected]')[0];
17. HTML 5 Widgets: Known Issues
http://unifaceinfo.com/fixes-updates/
Bug #31084: HTML 5 control Reconnect failures ($procerror -259)
Workaround: datatype=string in usys.ini webwidgets
[webwidgets]
EditBox=htmlinput(html:type=text;detail=dblclick;datatype=string)
DropDownList=htmlselect(html:size=1;datatype=string)
ListBox=htmlselect(html:size=3;datatype=string)
CheckBox=htmlinput(html:type=checkbox;datatype=string)
Bug #31422: Date display YYYY-MM-DD
Datetime field empty after update occurrence
Workaround: datatype=string in field widget more properties
20. Tabs
All content in one DSP
e.g. BOOTTABS
Each tab contained by div
element
• Hide with style display:none
Optional DspContainers
21. Modality - CSS
“Lightbox” effect via CSS
• Hidden dialog (html display:none)
• To show:
• Unhide (display:block)
• Change CSS z-index, position, background-color, opacity etc.
• CSS libraries typically provide CSS classes and JavaScript methods
e.g. .modal() + .hide()
22. Modality – Sample Implementation
Create a DSP to handle modal display
• Show() method to load a DSP in container
• Adds re-usable functionality (e.g. title, buttons, callback)
Paint a DSPContainer field on your main page
• Set initial value to load above modal controller DSP
Call methods in other DSP’s (e.g. SAMPLE_MODAL)
activate "<MODAL_DSP>".show(“Confirmation", vMessage, vInstanceName, "Yes,No", %
$instancename, “confirmCallback")
return 0
23. Data Paging
Use DBMS driver read
features:
offset
maxhits
See:
Help Topic:
“Data Paging in Web Applications”
Sample on unifaceinfo.com
27. Security
Sensitive data – can it be tampered with?
• URL, Cookie, Hidden Fields can be modified
• If protection needed, hash encode and/or use server-side storage
• Always validate on server
• Use SSL
Uniface prevents modification of non-editable fields
• Requires $SERVER_SECRET in .asn
Check user is authenticated
Use “public web” for browser activated operations only
More information in Help – see “Web Security Guidelines”
28. Code Performance Tips
Use Javascript API to move logic to browser
Attach & Detach operations
• Clear data when removed from DspContainer?
Reduce data synchronisation
• Only paint user interface entities
• Business logic in services
• DSP containers
• Scoping
Reduce State Management
Cache!