Adapting 'Surface Events'
We call Surface Events – or Client-side Events – events that trigger fast and only alter the aspect of the display and/or static contents, and thus don’t require an interaction with the data on the server.
In short Surface Events only affect the surface of the application without requesting the server.
In FoxInCloud Live Tutorial’s Controls and Events form, surface events are those listed in the bottom left box, namely .MouseEnter()
, .MouseMove()
, .MouseLeave()
and .KeyPress()
1.
As Surface Events don’t address the server, the VFP code can’t run as for the default FoxInCloud behavior: some ‘pure web’ code – JavaScript and/or CSS – is required!
This post explains how to take advantage of the powerful Web languages – especially CSS – to replace several VFP instructions and methods by a handful of CSS ‘directives’.
The adaptation statistics shared by developers reveal that Surface Events adaptation account for an average 10% of the total adaptation effort, so hopefully this post can help you save time in this area.
From a Web perspective, Surface Events (SE) break down into 2 categories:
- SE altering display of contents only
- SE altering contents itself
As usual for this blog, this post relies on the FoxInCloud Live Tutorial, namely the Surface Event form:
Surface Events altering display only
Influenced by the Web look and feel, it is quite common for a Desktop Application to suggest an interaction to the user using visual effects; eg. when user hovers a control with the mouse, change its forecolor and/or backcolor.
If you have such effect in your Desktop Application, you obviously want a similar effect to happen in your FoxInCloud Web Application.
Of course, due to the speed of such event, the standard FoxInCloud mechanism – execute the corresponding FoxPro Event code on the server – would be unusable to achieve the effect: things must happen right on the client browser.
Buttons in the Surface Event form are derived from this a class: modify class ficCmdHover of home(1) + 'tools\ab\aw\sample\fic\class\ficSample'
. After running FAA step 2, its code looks like this 2:
By default in Surface Events code, FAA has added RETURN .F.
to prevent FAS from implementing an event handler that would send the event to the server.
Below we’ll see how to implement a similar effect on the web using JavaScript
, CSS
, or both 3.
Solution 1. Using JavaScript only
Using JavaScript is the method closest to what we used to do in VFP; however it takes limited advantage of more powerful Web techniques.
Here are some hints for understanding the code below:
- FoxInCloud considers non-empty string value that event method returns from within
if m.thisForm.wlHTMLgen … endif
as JavaScript code to be executed in the browser when a similar event occurs, - We use the
textmerge
keyword to easily combine JavaScript code and VFP values - Each adapted VFP object inherits a
.wcID
property that FoxInCloud populates with a unique ID at runtime 4; it also uses this ID to populate theid
andclass
attributes when generating the corresponding HTML element. jQuery
is a popular JavaScript framework (library) that FoxInCloud installs and loads automatically;jQuery('#id')
selects the element in the page having ‘id’ asid=""
attribute (see previous point), and exposes methods that alter the HTML element and/or its CSS- To change the HTML element’s aspect, we use the jQuery
.css()
method with an object as parameter; each property of this object is named as the corresponding CSS property {"property": value, "property": value, …}
is called JavaScript Object Notation (JSON), in other word a literal representing an object 5- Regarding line termination, JavaScript and VFP work the other way round: JS uses ‘;’ as instruction terminator, instructions without a closing ‘;’ continue on next line
- Block comment
/* comment */
can be located anywhere, even inside an instruction
Note that this code changes the HTML of the element, and this change can be observed in the browser developer tool:
HTML of the button before hovering:
After hovering the button, the style attribute is set:
Note that this JavaScript-driven alteration of HTML style attribute (AKA inline style
) takes precedence over the rules defined in CSS files. In the Bootstrap version of the ‘Surface event’ form, we’ve implemented a reminder that appears when mouse leaves the ‘JavaScript only’ button:
Solution 2. Using JavaScript and CSS
In this second example, we’ll define a class-based CSS rule in the application’s custom CSS file tuto.css
6 and, when mouse enters/leaves, dynamically add/remove this class to/from the HTML object.
Again, as the class
attribute is part of HTML, we need JavaScript to alter its value, and jQuery
will also come to the rescue to simplify the code, namely its .addClass()
and .removeClass()
methods 7
Here are some hints for understanding the code below:
- As a variation, in
jQuery(".<<this.wcID>>")
, we use a class selector (‘.’) instead of an id selector (‘#’). You can use either one as FoxInCloud automatically assigns the same unique string (eventclient_scx-pgf-pagaspect-cmdjscss
) as ID and class:
The selector .eventclient_scx button:not([disabled]).cmd_Hover
means: any button that is a descendant of an element of class eventclient_scx
(the form), is enabled and has class cmd_Hover
.
Note that the browser (re)evaluates the CSS rules dynamically – and immediatly – whenever any component of the rules changes in HTML.
Solution 3. Using ‘pure’ CSS, version 1
The previous case has unveiled the power of CSS selector syntax that can work on:
- element position in the page hierarchy tree: descendant, child, sibling, first-of, last-of, etc.
- element attributes: #id, .class and any other HTML attribute
- element state :disabled, :checked, :hover, etc. 9
The :hover
state fulfills what we need in this case: change the element’s aspect when mouse hovers it.
In this solution, we’ll add a rule to the CSS rules that FoxInCloud generates into a file named awDefault*.css
10.
We add this rule in the .wcHTMLgen()
method that the object inherits from the aw???
FoxInCloud ‘base class’ and that FoxInCloud runs when generating the HTML for this object, at first time the containing form is required, and using the .CSScustomAdd()
method.
Here are some hints for understanding the code below:
toHTMLgen AS awHTMLgen OF awHTML.prg
is a reference to the FoxInCloud HTML generator that drills into the form and containers until each individual member;- Depending on the value that this method
RETURN
s and/or writes into.wcHTML
, the HTML generatortoHTMLgen
generates standard or custom HTML; .wcHTMLgen()
can be implemented at any level of the VFP class hierarchy, making it possible to make the Web behavior specific to an object or all objects of a given VFP class;- The
.CSScustomAdd()
method adds custom CSS rules to the standardawDefault*.css
style sheet, that the custom style sheetxxx.css
can override if needed.
This solutions works fine for a small number of controls, however, if all controls of a given BaseClass
must have a similar behavor, the solution 4 hereafter is more efficient.
Solution 4. Using ‘pure’ CSS, version 2
This solution combines several features that we’ve gone through in the previous solutions:
- .class CSS selector: we will a class to the generated HTML element and build a CSS rule based on this custom CSS class
- :hover pseudo class; our custom CSS rule will focus on the
:hover
state of the custom CSS class above - custom CSS class upon HTML generation besides
.wcHTMLgen()
, each adapted VFP object inherits a.wCSSclassAdd
property where you can define additional CSS classes that the FoxInCloud HTML generator will add to the generated HTML element. You can manipulate this property either at design time, using the VFP visual designer, or at run time, in.Init()
orform.Load()
11
tuto.css
defines the corresponding CSS rule:
As tuto.css
can be updated in production separately from the app, changing the behavior (eg. background-color
) does not require updating the application.
Surface Events altering contents
Altering HTML contents always require JavaScript; CSS can alter the aspect of contents only, not the contents itself.
To change HTML contents, we also use jQuery
and its utility methods:
.prop()
: creates or reads a property of the HTML element.text()
: replaces or reads the text inside HTML paired tags 12
Note that FoxInCloud detects the user browser’s preferred language as a 2-letter ISO 639 code and stores it into:
- client side:
FoxInCloud.lang
- server side:
thisForm.wcLangUser
(inherited fromaw.vcx!awFrm
)
Wrap-up
Hopefully this post has teached you the important basics of CSS and JS programming, and the main hooks where FoxInCloud lets you add this client-side code to your application:
- CSS selectors
jQuery
and its utility methods- FoxInCloud CSS:
awDefault*.css
andxxx.css
- In VFP event methods, return
JavaScript
from withinif m.thisForm.wlHTMLgen … endif
.wcHTMLgen()
for generating custom HTML, CSS and/JS.wCSSclassAdd
for adding CSS class(es) to one object or all objects derived from a classtoHTMLgen.CSScustomAdd()
to add custom CSS rules
Video
-
on some controls like
textBox
,.InteractiveChange()
also falls into the ‘Surface Event’ category, that FoxInCloud will soon support using the recent HTML DOM Event level 3 API.oninput()
↩ -
Button instances in
EventClient.scx
call this form usingdodefault()
↩ -
As you may be aware of, HTML defines the contents and structure, and CSS defines how this content and structure appears to the user. Events occurring in the browser execute JavaScript code that can alter HTML, CSS or both. In earlier versions on HTML, some HTML tags and attributes could influence the aspect (such as
<b>, <i>
,width, align, background
, etc.); today these tags and attributes are fully deprecated and should no longer be used. Visual FoxPro works with similar principles except Layout properties are just a category in the visual designers and follow the same logic as any other class or object property ↩ -
this ID concatenates
.Name
of form, object parents and object itself ↩ -
VFP does not offer a similar ability to represent an object as a literal; conversely JavaScript misses the date and date-time literal feature like in VFP. Note that JavaScript accepts the dash (‘-‘) character inside property names, which VFP rejects … each language has its pros and cons… ↩
-
named after the FoxInCloud Web App
xxx
code –tuto.css
in this case – the App custom CSS filexxx.css
is loaded by FoxInCloud on each page/form, after all other CSS files, particularly the default, FiC-generatedawDefault*.css
. This gives the ability to (1) override any standard CSS directive and (2) define custom directives. ↩ -
note the camel case convention: in the ‘Web world’, everything is lower case except the first letter of successive words. ↩
-
note the block comment has the same syntax as in JavaScript ↩
-
W3C calls these state modifiers ‘pseudo-classes’ ↩
-
during development, FoxInCloud dynamically generates
awDefault_<sys(2015)>.css
, andawDefaultAll.css
for production ↩ -
altering
.wCSSclassAdd
at run time is advisable for easier maintenance in case.wCSSclassAdd
changes in a parent class. ↩ -
while some tags such as
<br>
or<img>
are unpaired or self-closing, most HTML tags require a closing tag:<p>text</p>
,<i>text</i>
,<div>text</div>
, etc. ↩
tags: user experience adaptation JavaScript CSS
Watch FoxInCloud Marketing Videos :: Watch FoxInCloud Technical Videos :: Stay tuned on FoxInCloud Roadmap :: Learn how to use FoxInCloud :: Download FoxInCloud Adaptation Assistant for free :: Download FoxInCloud Web Application Studio for free