Uniface Responsive Development (2 of 3)
David Akerman – Solution Consultant
AgendaDynamic Server Page (DSP) Coding RecapUser Interface TechniquesDemo WebStart ApplicationCode Walkthrough
Coding DSP’s
Javascript API
Comparing ProcScript vs. JavaScriptServer <Detail> trigger- button clicked
trigger detailpublic web webmessage "Button clicked" return 0end; trigger
Also onFocus, onBlur etc. in Extended Triggers
Browser Extended trigger- editbox changedwebtrigger onChangejavascript
alert(this.getValue());endjavascriptend ; trigger
Comparing ProcScript vs. JavaScript OperationsServer Operations
operation Updatepublic webparams
string pOptions: INendparams ; ProcScript Code return 0end ; Update
Browser Operations
weboperation Updateparams
string pOptions: INendparamsjavascript
// JavaScript codeendjavascriptend ; Update
Activating OperationsCall weboperation from server (queued)
webactivate $instancename.save()
Call server operation from browser (asynchronous)this.getInstance().activate("save");
- use promises to control flow
operation getLocationpublic webparams string address : in numeric latitude : inout numeric longitude: inoutendparams call CalcCoordinates(address, latitude, longitude)end ; getLocation
Promiseswebtrigger onClickjavascriptthis.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
41
2
3
Browser
Server
Get Location Button
Scope
Controls data sent & received between browser & serverScoping operations block, prevent race conditions
output input
trigger detailpublic webscope input output operation AnotherDSP.showendscope activate "AnotherDSP".show() return 0end; trigger
Dynamic Scopeoperation storeDatapublic webscope input output operation myInstanceList().storeendscopevariables string vInstList, vInstNameendvariables 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
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:’
ValidationUse JavaScript for non-declarative browser checks:
Always validate on server!
CSS Classes
<input id="ufld:search.criteria.ui" type="text" class="form-control" placeholder="Search...">
$fieldproperties("SEARCH.CRITERIA") = "html:class=form-control"
$fieldproperties("SELECT.BUTTON") = "html:class=btn btn-primary btn-lg"
javascript fld.setProperty("html:class", "form-control");endjavascript
Modifying Properties
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:
CSS Attributes
Add Attributeputitem/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 Findvar elements = document.querySelectorAll('tr[data-selected]');jQuery: $('tr[data-selected]').each(…) or $('tr[data-selected]')[0];
HTML 5 Widgets: Known Issueshttp://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-DDDatetime field empty after update occurrence
Workaround: datatype=string in field widget more properties
UI Techniques
User Interface TechniquesMessaging & Error handlingResponsivenessTabsModality & Overlays NavigationIcons Data Paging
Tabs
All content in one DSPe.g. BOOTTABSEach tab contained by div element• Hide with style display:none
Optional DspContainers
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 methodse.g. .modal() + .hide()
Modality – Sample ImplementationCreate 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
Data PagingUse DBMS driver read features:
offsetmaxhits
See:Help Topic:“Data Paging in Web Applications”Sample on unifaceinfo.com
Using Icon Fonts – Attributes Only
<html><head> <link rel="stylesheet" type="text/css" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" /></head><body> <i id="ufld:btn_home.buttons.ui" class="fa fa-home fa-fw"></i></body></html>
Using Icon Fonts – Modelled ButtonsUniface button HTML
<input id="ufld:RET.BUTTONS.UI" type="button" class="btn btn-primary fa" value="Button" />
#defines; fa-refresh – see font-awesome cheatsheet#define B_BROWSE_ICON = 
Format trigger#if (<$componentType> = D)$format = $concat($string("<B_BROWSE_ICON>; "), "Retrieve")#endif
Considerations
SecuritySensitive 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 authenticatedUse “public web” for browser activated operations onlyMore information in Help – see “Web Security Guidelines”
Code Performance TipsUse Javascript API to move logic to browserAttach & 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 ManagementCache!
Resources Uniface Help: Tutorials Uniface Training uniface.info - Samples, Forums, Blogs
youtube.com/uniface github.com/uniface- Frameworks & Tools
Walkthrough:WebStart App
Thank You& Questions