<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>FoxInCloud blog</title>
    <description>FoxInCloud adapts any Visual FoxPro Business Application to the Web. FoxInCloud is simple, let's make it obvious.
</description>
    <link>http://localhost:4000/blog/</link>
    <atom:link href="http://localhost:4000/blog/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Wed, 05 Sep 2018 13:07:56 +0200</pubDate>
    <lastBuildDate>Wed, 05 Sep 2018 13:07:56 +0200</lastBuildDate>
    <generator>Jekyll v3.8.3</generator>
    
      <item>
        <title>Enhance your FiC Application look and feel with a Web Designer!</title>
        <description>&lt;p&gt;Wanna provide your Web Application users a unique experience?&lt;/p&gt;

&lt;p&gt;Hire a Web designer to enhance your FoxInCloud Application’s look and feel!&lt;/p&gt;

&lt;p&gt;This post explains how you can collaborate with a Web Designer and finally integrate his/her work into your FoxInCloud Application.&lt;/p&gt;

&lt;h1 id=&quot;1-let-your-web-designer-be-creative&quot;&gt;1. Let your Web Designer be creative&lt;/h1&gt;

&lt;p&gt;Once your application is ‘conventionnally’ adapted, you can just install a Test Version on your production server that you can showcase to the designer:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;purpose of the Application,&lt;/li&gt;
  &lt;li&gt;target audience,&lt;/li&gt;
  &lt;li&gt;key forms and controls,&lt;/li&gt;
  &lt;li&gt;key steps requiring user’s attention,&lt;/li&gt;
  &lt;li&gt;graphic patterns in the industry (symbols, colors, etc.),&lt;/li&gt;
  &lt;li&gt;competition apps,&lt;/li&gt;
  &lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The designer will work and present you a mockup showing his/her ideas on how your application can graphically improve; this mockup can either be a slide show or a video showing some typical operation on the Application.&lt;/p&gt;

&lt;p&gt;Once you validate this mockup &lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, the designer will create the HTML/CSS/JS templates that you’ll later inject into your application.&lt;/p&gt;

&lt;p&gt;Here is a video showing this whole Web Design process on a live FoxInCloud application &lt;sup id=&quot;fnref:2&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;
&lt;iframe width=&quot;740&quot; height=&quot;416&quot; src=&quot;https://www.youtube.com/embed/TLuGJVzoPhg&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;h1 id=&quot;2-integrate-the-web-design-into-your-web-application&quot;&gt;2. Integrate the Web Design into your Web Application&lt;/h1&gt;

&lt;p&gt;Let’s see how we can change this button named &lt;code&gt;designation&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/image/doo-pagBien-designation-lan.png&quot; alt=&quot;sample button - original&quot; /&gt;&lt;/p&gt;

&lt;p&gt;into this web design:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/image/doo-pagBien-designation-web.png&quot; alt=&quot;sample button - designed&quot; style=&quot;width: 10em;&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;a--add-the-designers-css-and-js-to-your-web-application&quot;&gt;a- Add the Designer’s CSS and JS to your Web Application&lt;/h2&gt;

&lt;p&gt;If your Web designer has written his/her own CSS and/or JS files, and/or has used some specific CSS/JS library ,&lt;sup id=&quot;fnref:8&quot;&gt;&lt;a href=&quot;#fn:8&quot; class=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; you can either:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;copy and paste into your application’s standard &lt;code&gt;xxx.css&lt;/code&gt; and &lt;code&gt;xxx.js&lt;/code&gt; &lt;sup id=&quot;fnref:6&quot;&gt;&lt;a href=&quot;#fn:6&quot; class=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
  &lt;li&gt;copy the designer’s file into your application’s site folders &lt;sup id=&quot;fnref:7&quot;&gt;&lt;a href=&quot;#fn:7&quot; class=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt; and implement the &lt;code&gt;xxxProcess.cawCSSinc()&lt;/code&gt; and/or  &lt;code&gt;xxxProcess.cawJSinc()&lt;/code&gt; method like in the example below:&lt;/li&gt;
&lt;/ul&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-foxpro&quot; data-lang=&quot;foxpro&quot;&gt;* ------------------------------------------------------------
PROTECTED FUNCTION cawCSSinc &amp;amp;&amp;amp; &amp;lt;link rel=&amp;quot;stylesheet&amp;quot; /&amp;gt; {en} for additional CSS files {fr} des CSSs FoxInCloud, des CSS de l&amp;#39;application et des Fichier CSS additionnels
LPARAMETERS ;
  tcCSSadd; &amp;amp;&amp;amp; [&amp;#39;&amp;#39;] {fr} Fichier CSS additionnels
, toForm as awFrm of aw.vcx; &amp;amp;&amp;amp; {en} Reference to form &amp;amp;&amp;amp; {fr} Référence au formulaire
, tcForm; &amp;amp;&amp;amp; {en} form.Name {fr} Nom du formulaire

return DoDefault(;
     &amp;#39;css/animate.min.css, css/hover.min.css, &amp;#39; + m.tcCSSadd; &amp;amp;&amp;amp; {en} add custom CSS before standard CSS
    , m.toForm;
    , m.tcForm;
    )&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This method adds these HTML directive to every page of your application &lt;sup id=&quot;fnref:9&quot;&gt;&lt;a href=&quot;#fn:9&quot; class=&quot;footnote&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&amp;lt;link type=&amp;quot;text/css&amp;quot; rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;/css/animate.min.css&amp;quot;&amp;gt;
&amp;lt;link type=&amp;quot;text/css&amp;quot; rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;/css/hover.min.css&amp;quot;&amp;gt;
&amp;lt;link type=&amp;quot;text/css&amp;quot; rel=&amp;quot;stylesheet&amp;quot; href=&amp;quot;/xxx.css&amp;quot;&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h2 id=&quot;b--generate-html-matching-what-the-designer-wrote&quot;&gt;b- Generate HTML matching what the Designer wrote&lt;/h2&gt;

&lt;p&gt;In VFP, this &lt;code&gt;designation&lt;/code&gt; button is in fact based on a &lt;strong&gt;container class&lt;/strong&gt; named &lt;code&gt;boutonlarge_png&lt;/code&gt;, holding several images around the button itself:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/image/doo-boutonlarge-members.png&quot; alt=&quot;sample button - VFP&quot; /&gt;&lt;/p&gt;

&lt;p&gt;FoxInCloud generates HTML accordingly &lt;sup id=&quot;fnref:3&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot;&gt;7&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&amp;lt;div id=&amp;quot;dooxi_scx-pageframe1-pagbien-designation&amp;quot; class=&amp;quot;container awcnt vhccnt bouton_png boutonlarge_png dooxi_scx-pageframe1-pagbien-designation&amp;quot;&amp;gt;
    &amp;lt;img id=&amp;quot;dooxi_scx-pageframe1-pagbien-designation-image&amp;quot; class=&amp;quot;awimg vhcimg image dooxi_scx-pageframe1-pagbien-designation-image&amp;quot; src=&amp;quot;Images/bp_designation.png&amp;quot; style=&amp;quot;display:none;&amp;quot;&amp;gt;
    &amp;lt;img id=&amp;quot;dooxi_scx-pageframe1-pagbien-designation-image_d&amp;quot; class=&amp;quot;awimg vhcimg image dooxi_scx-pageframe1-pagbien-designation-image_d&amp;quot; src=&amp;quot;&amp;quot; style=&amp;quot;display:none;&amp;quot;&amp;gt;
    &amp;lt;button type=&amp;quot;button&amp;quot; id=&amp;quot;dooxi_scx-pageframe1-pagbien-designation-bouton&amp;quot; class=&amp;quot;commandbutton awcmd vhccmd dooxi_scx-pageframe1-pagbien-designation-bouton ecrire&amp;quot; tabindex=&amp;quot;18&amp;quot;&amp;gt;DÉTAIL&amp;lt;/button&amp;gt;
    &amp;lt;img id=&amp;quot;dooxi_scx-pageframe1-pagbien-designation-ok&amp;quot; class=&amp;quot;image awimg vhcimg dooxi_scx-pageframe1-pagbien-designation-ok&amp;quot; src=&amp;quot;Images/ok_b.png&amp;quot; alt=&amp;quot;ok_b&amp;quot; style=&amp;quot;display:none;&amp;quot;&amp;gt;
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;However the designer has come up with a pretty different (and much more simple) HTML markup &lt;sup id=&quot;fnref:4&quot;&gt;&lt;a href=&quot;#fn:4&quot; class=&quot;footnote&quot;&gt;8&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&amp;lt;button class=&amp;quot;doo-btn-icon hvr-radial-out hvr-shadow diagnostiqueur&amp;quot;&amp;gt;
    &amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;div&amp;gt;&amp;lt;/div&amp;gt;DÉTAIL
&amp;lt;/button&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Using the &lt;code&gt;boutonlarge_png.wcHMTLgen()&lt;/code&gt; method, we then replace the whole HTML that FoxInCloud would have generated by custom HTML &lt;sup id=&quot;fnref:5&quot;&gt;&lt;a href=&quot;#fn:5&quot; class=&quot;footnote&quot;&gt;9&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-foxpro&quot; data-lang=&quot;foxpro&quot;&gt;LPARAMETERS toHTMLgen AS awHTMLgen OF awHTML.prg, tlInnerHTML &amp;amp;&amp;amp; {en} doc in Parent Code {fr} doc dans le code parent

if thisForm.wBSlHTMLgen &amp;amp;&amp;amp; Generating HTML in Bootstrap mode
  this.wcHTML = &amp;#39;&amp;#39;;
   + &amp;#39;&amp;lt;button&amp;#39;;
   + &amp;#39; id=&amp;quot;&amp;#39; + this.wcID + &amp;#39;&amp;quot;&amp;#39;;
   + m.toHTMLgen.cClass(); &amp;amp;&amp;amp; class=&amp;quot;&amp;quot; attribute generated by FoxInCloud
   + m.toHTMLgen.cStyle(&amp;#39;display&amp;#39;); &amp;amp;&amp;amp; style=&amp;quot;&amp;quot; attribute generated by FoxInCloud
   + m.toHTMLgen.cEvents(); &amp;amp;&amp;amp; Let FoxInCloud generate the event handlers in JS
   + &amp;#39;&amp;gt;&amp;lt;span&amp;gt;&amp;lt;/span&amp;gt;&amp;lt;div&amp;gt;&amp;lt;/div&amp;gt;&amp;#39;; &amp;amp;&amp;amp; here is the Web designer&amp;#39;s trick...
   + Upper(Alltrim(Strtran(this.Caption, &amp;#39;\&amp;lt;&amp;#39;)));
   + &amp;#39;&amp;lt;/button&amp;gt;&amp;#39;
endif&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The HTML stored into the &lt;code&gt;.wcHTML&lt;/code&gt; property replaces whatever HTML FoxInCloud would have normally generated for any object instance of this class or any of its sub-class.&lt;/p&gt;

&lt;p&gt;Of course you can overwrite this method in any sub-class or instance of this class to keep by exception the default HTML, or further customize the custom HTML.&lt;/p&gt;

&lt;p&gt;This video shows how the application behaves with all design enhancements implemented:&lt;/p&gt;

&lt;iframe width=&quot;740&quot; height=&quot;416&quot; src=&quot;https://www.youtube.com/embed/cLxJplc_BjM&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;hr /&gt;

&lt;div class=&quot;footnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;Better change now than later, when the whole process is finished… take some time to think with fresh ideas, and do give all the necessary feedback to the designer… always in a positive manner of course. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot;&gt;
      &lt;p&gt;Courtesy from the graphic designer for this Application: Mr. Eric Valcke, &lt;a href=&quot;http://www.traitcreatif.com&quot;&gt;Trait Creatif&lt;/a&gt; &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:8&quot;&gt;
      &lt;p&gt;other than the libraries already included in FoxInCloud like &lt;code&gt;jQuery&lt;/code&gt;, &lt;code&gt;Bootstrap&lt;/code&gt;, etc. &lt;a href=&quot;#fnref:8&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:6&quot;&gt;
      &lt;p&gt;where &lt;code&gt;xxx&lt;/code&gt; is the 2-4 character code that you’ve chosen during FAA step &lt;code&gt;3-Publish&lt;/code&gt; &lt;a href=&quot;#fnref:6&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:7&quot;&gt;
      &lt;p&gt;&lt;code&gt;site/xxxTest&lt;/code&gt; and &lt;code&gt;site/xxxProd&lt;/code&gt; beneath your application folder &lt;a href=&quot;#fnref:7&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:9&quot;&gt;
      &lt;p&gt;Using m.toForm and m.tcForm, you can load libraries only for the forms that need them &lt;a href=&quot;#fnref:9&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot;&gt;
      &lt;p&gt;&lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; is the FoxInCloud standard HTML markup to render a VFP container. &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:4&quot;&gt;
      &lt;p&gt;Designer uses embedded &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt; to easily add a background image using a simple CSS rules such as &lt;code&gt;button.diagnostiqueur div {backgound-image: ...}&lt;/code&gt; or &lt;code&gt;button.diagnostiqueur span {backgound-image: ...}&lt;/code&gt;; this markup allows having several images ‘behind’ the same button, that one can only do in VFP using the ‘contained images’ technique. &lt;a href=&quot;#fnref:4&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:5&quot;&gt;
      &lt;p&gt;We just copy and paste the HTML from the designer and let FoxInCloud compute some critical attributes such as &lt;code&gt;id=&lt;/code&gt; &lt;code&gt;class=&lt;/code&gt;, &lt;code&gt;style=&lt;/code&gt;, and the event handlers &lt;a href=&quot;#fnref:5&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Wed, 05 Sep 2018 00:00:00 +0200</pubDate>
        <link>http://localhost:4000/blog/2018/09/05/Integrate-Web-Design-Markup.html</link>
        <guid isPermaLink="true">http://localhost:4000/blog/2018/09/05/Integrate-Web-Design-Markup.html</guid>
        
        <category>user experience</category>
        
        <category>design</category>
        
        <category>HTML</category>
        
        <category>CSS</category>
        
        
      </item>
    
      <item>
        <title>FoxInCloud 2.27 works around a VFP bug to reach 99.99% availability</title>
        <description>&lt;p&gt;Once in a while, on applications under heavy load, we’ve faced situations where some grids suddenly lost their columns, meaning that their &lt;code&gt;(.RecordSource)&lt;/code&gt; was unexpectedly &lt;code&gt;USE IN&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;After double checking the FoxInCloud code, seeing no correlation with the type of &lt;code&gt;.recordSource&lt;/code&gt; (table, view or cursor), we progressively circumscribed the problem within an area of code where the contents of the grid is turned into XML for state comparison.&lt;/p&gt;

&lt;p&gt;And finally we found what was going on…&lt;/p&gt;

&lt;h1 id=&quot;vfp-cursortoxml-bug&quot;&gt;VFP CursorToXML() bug&lt;/h1&gt;

&lt;p&gt;Yes, you read it right, the VFP &lt;code&gt;CursorToXML()&lt;/code&gt; function has a bug!&lt;/p&gt;

&lt;p&gt;Under certain conditions that honestly we could not isolate, maybe once out of 20,000 calls, without any obvious relation with the data contained in the cursor, &lt;code&gt;CursorToXML()&lt;/code&gt; sometimes returns this XML:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-xml&quot; data-lang=&quot;xml&quot;&gt;&amp;lt;?xml version = &amp;quot;1.0&amp;quot; encoding=&amp;quot;Windows-1252&amp;quot; standalone=&amp;quot;yes&amp;quot;?&amp;gt;&amp;lt;VFPData&amp;lt;/VFPData&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Looks like an error in the pointer when writing the closing tag &lt;code&gt;&amp;lt;/VFPData&amp;gt;&lt;/code&gt; resulting in a malformed XML, and containing no data at all!&lt;/p&gt;

&lt;p&gt;If you wish to investigate this bug, you can &lt;a href=&quot;ftp://foxincloud.com/_XMLerror.zip&quot;&gt;download here&lt;/a&gt; sample data that &lt;code&gt;CursorToXML()&lt;/code&gt; has failed to properly convert while in production, all resulting in the XML shown above.&lt;/p&gt;

&lt;p&gt;And if you attempt to convert these sample data with &lt;code&gt;CursorToXML()&lt;/code&gt; on your dev. machine, it’ll most probably succeed…&lt;br /&gt;
That can probably be called an ‘&lt;em&gt;intermittent bug&lt;/em&gt;’!&lt;/p&gt;

&lt;h2 id=&quot;workaround&quot;&gt;Workaround&lt;/h2&gt;

&lt;p&gt;FoxInCloud processes all &lt;code&gt;CursorToXML()&lt;/code&gt; through a central function: &lt;code&gt;cXMLofCursor()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Whenever it finds mismatched &lt;code&gt;&amp;lt;&lt;/code&gt; or &lt;code&gt;&amp;gt;&lt;/code&gt; in the result from &lt;code&gt;CursorToXML()&lt;/code&gt;, &lt;code&gt;cXMLofCursor()&lt;/code&gt; simply &lt;strong&gt;builds the XML string by scanning&lt;/strong&gt; the cursor’s rows and columns. This obviously takes a little overhead however it happens only once in thousands calls and is 100% successful.&lt;/p&gt;

&lt;h2 id=&quot;result-four-nine-availability&quot;&gt;Result: four-nine availability&lt;/h2&gt;

&lt;p&gt;After solving this VFP bug, applications in production now meet the highest standards for availability, over 99.99%:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/image/CTB-FWAD-status.png&quot; alt=&quot;Biosil Web Application&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/image/CAL-FWAD-status.png&quot; alt=&quot;Biolabo Web Application&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;special-thanks&quot;&gt;Special thanks&lt;/h2&gt;

&lt;p&gt;We could not have successfully achieved such a difficult debug without the close cooperation and help of our friends of the FoxInCloud users community!&lt;/p&gt;

&lt;p&gt;Many thanks to the FoxInCloud users&lt;sup id=&quot;fnref:3&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; who accepted to share logs, put experimental code into production, with sometimes failures and moments of discouragement… We finally did it: turned down a VFP bug that has spoiled us for quite a while…!&lt;/p&gt;

&lt;h1 id=&quot;wait-version-227-brings-more-than-just-a-bug-fix&quot;&gt;Wait, version 2.27 brings more than just a bug fix!&lt;/h1&gt;

&lt;p&gt;Out of the &lt;a href=&quot;/roadmap.php#v2.27.0&quot;&gt;15+ enhancements and fixes&lt;/a&gt; brought by version &lt;code&gt;2.27.0&lt;/code&gt;, let’s focus on 2 that’ll probably suit many VFP developers needs…&lt;/p&gt;

&lt;h2 id=&quot;paged-grid-faster-and-updatable&quot;&gt;Paged grid: faster and updatable&lt;/h2&gt;

&lt;p&gt;In a Web Application, because of the limited bandwidth, browsing through long lists remains a response time issue.&lt;/p&gt;

&lt;p&gt;As VFP application extensively use grids to present long lists of data, FoxInCloud comes with a handy class that turns any VFP grid into a paged grid &lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; where the whole set of rows is divided into pages of 20-100 rows. The user can:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;choose the number of lines per page&lt;/li&gt;
  &lt;li&gt;by clicking the header of any column where &lt;code&gt;.RecordSource&lt;/code&gt; an index: sort by left-click, filter by right-click&lt;/li&gt;
  &lt;li&gt;move to given page by typing its number&lt;/li&gt;
  &lt;li&gt;navigate between page by clicking arrows&lt;/li&gt;
  &lt;li&gt;seamlessly move to the previous or next page just by browsing past the first or last line in the page&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/blog/image/aw.vcx-awCntGrdPage.png&quot; alt=&quot;Grid paging container&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The paged grid in action on &lt;a href=&quot;/tutotest/bs/pagedGrid.tuto&quot;&gt;FoxInCloud Live Tutorial&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/tutotest/bs/pagedGrid.tuto&quot;&gt;&lt;img src=&quot;/blog/image/FLT-bs-pagedGrid.png&quot; alt=&quot;FoxInCloud Live Tutorial - paged grid&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Until this version &lt;code&gt;2.27.0&lt;/code&gt;, the data displayed in the grid were those of a cursor built from the &lt;code&gt;grid.recordSource&lt;/code&gt;, and replacing the corresponding &lt;code&gt;columns.controlSource&lt;/code&gt;. Because of that design, building a page with a large [col * row] count could take some time and the grid could hardly be updateable.&lt;/p&gt;

&lt;p&gt;Starting with &lt;code&gt;V 2.27.0&lt;/code&gt;, &lt;code&gt;awCntGrdPage&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;builds the page cursor with only the unique keys of the records that appear on the page, in the suitable order,&lt;/li&gt;
  &lt;li&gt;sets this one-key column cursor as the &lt;code&gt;grid.recordSource&lt;/code&gt;,&lt;/li&gt;
  &lt;li&gt;sets a relation from the page cursor to the original &lt;code&gt;grid.recordSource&lt;/code&gt; on the key columns &lt;sup id=&quot;fnref:2&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;,&lt;/li&gt;
  &lt;li&gt;keeps the &lt;code&gt;columns.controlSource&lt;/code&gt; unchanged, pointing on the original &lt;code&gt;grid.recordSource&lt;/code&gt; Alias, and/or related Aliases.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;awCntGrdPage.wlCntGrcCSpageCursor&lt;/code&gt; lets you switch between the legacy and the new behavior:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;.T.&lt;/strong&gt; (current default) – legacy behavior: redirect &lt;code&gt;columns.controlSource&lt;/code&gt; to the page cursor&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;.F.&lt;/strong&gt; (future default) – new behavior: keep &lt;code&gt;columns.controlSource&lt;/code&gt; and set a relation from the page cursor into the original &lt;code&gt;grid.recordSource&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;surface-events-live-tutorial&quot;&gt;Surface Events Live Tutorial&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Surface Events&lt;/em&gt; –or &lt;em&gt;Client-side Events&lt;/em&gt;– are events that trigger fast and alter only the aspect of the display and/or static contents, and thus don’t require an interaction with the data on the server: &lt;code&gt;.MouseEnter()&lt;/code&gt;, &lt;code&gt;.MouseMove()&lt;/code&gt;, &lt;code&gt;.MouseLeave()&lt;/code&gt;, &lt;code&gt;.KeyPress()&lt;/code&gt;, &lt;code&gt;.InteractiveChange()&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In short &lt;em&gt;Surface Events&lt;/em&gt; only affect the surface of the application without requesting the server.&lt;/p&gt;

&lt;p&gt;As they must entirely be processed on the client browser, &lt;em&gt;Surface Events&lt;/em&gt; are the only area of a FoxInCloud application where the VFP developer must write some &lt;code&gt;JavaScript&lt;/code&gt; and/or &lt;code&gt;CSS&lt;/code&gt; code.&lt;/p&gt;

&lt;p&gt;FoxInCloud Live Tutorial now provides an &lt;a href=&quot;/tutotest/bs/eventClient.tuto&quot;&gt;on-line sample form&lt;/a&gt; where all possible alternative techniques for writing such code are discussed:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/tutotest/bs/eventClient.tuto&quot;&gt;&lt;img src=&quot;/blog/image/FLT-bs-SE.png&quot; alt=&quot;FoxInCloud Live Tutorial's *Surface Event* form&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The corresponding &lt;a href=&quot;/blog/2018/07/11/adapting-surface-events.html&quot;&gt;blog post&lt;/a&gt; and &lt;a href=&quot;https://www.youtube.com/watch?v=Z1IjcP3rEqY&quot;&gt;video&lt;/a&gt; provide additional detailed explanation.&lt;/p&gt;

&lt;iframe width=&quot;740&quot; height=&quot;416&quot; src=&quot;https://www.youtube.com/embed/Z1IjcP3rEqY&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;hr /&gt;

&lt;div class=&quot;footnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:3&quot;&gt;
      &lt;p&gt;Special thanks to Gilles Lajot-Sarthou (among others) &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;&lt;code&gt;modify class awCntGrdPage of aw.vcx&lt;/code&gt;; this class requires that &lt;code&gt;grid.recordSource&lt;/code&gt; has at least a unique key (&lt;code&gt;primary&lt;/code&gt; or &lt;code&gt;candidate&lt;/code&gt;) &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot;&gt;
      &lt;p&gt;whenever &lt;code&gt;grid.recordSource&lt;/code&gt; is already the target of a &lt;code&gt;relation&lt;/code&gt;, behavior automatically switches back to legacy and grid is set to &lt;code&gt;read-only&lt;/code&gt; &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Mon, 06 Aug 2018 00:00:00 +0200</pubDate>
        <link>http://localhost:4000/blog/2018/08/06/FoxInCloud-2.27-four-nines-availability.html</link>
        <guid isPermaLink="true">http://localhost:4000/blog/2018/08/06/FoxInCloud-2.27-four-nines-availability.html</guid>
        
        <category>availability</category>
        
        <category>optimization</category>
        
        <category>release</category>
        
        <category>technology</category>
        
        
      </item>
    
      <item>
        <title>Adapting 'Surface Events'</title>
        <description>&lt;p&gt;We call &lt;em&gt;Surface Events&lt;/em&gt; – or &lt;em&gt;Client-side Events&lt;/em&gt; – 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.&lt;/p&gt;

&lt;p&gt;In short &lt;em&gt;Surface Events&lt;/em&gt; only affect the surface of the application without requesting the server.&lt;/p&gt;

&lt;p&gt;In FoxInCloud Live Tutorial’s &lt;a href=&quot;/tutotest/bs/Event.tuto&quot;&gt;Controls and Events form&lt;/a&gt;, surface events are those listed in the bottom left box, namely &lt;code&gt;.MouseEnter()&lt;/code&gt;, &lt;code&gt;.MouseMove()&lt;/code&gt;, &lt;code&gt;.MouseLeave()&lt;/code&gt; and &lt;code&gt;.KeyPress()&lt;/code&gt; &lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/tutotest/bs/Event.tuto&quot;&gt;&lt;img src=&quot;/blog/image/FLT-bs-EV-client.png&quot; alt=&quot;Surface Events In FoxInCloud Live Tutorial's 'Controls and Events' form &quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As Surface Events don’t address the server, the VFP code can’t run as for the default FoxInCloud behavior: &lt;strong&gt;some ‘pure web’ code – JavaScript and/or CSS – is required&lt;/strong&gt;!&lt;/p&gt;

&lt;p&gt;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’.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;/shared-projects.php&quot;&gt;adaptation statistics shared by developers&lt;/a&gt; reveal that &lt;em&gt;Surface Events&lt;/em&gt; adaptation account for an average &lt;strong&gt;10% of the total adaptation effort&lt;/strong&gt;, so hopefully this post can help you save time in this area.&lt;/p&gt;

&lt;p&gt;From a Web perspective, Surface Events (SE) break down into 2 categories:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;SE altering display of contents only&lt;/li&gt;
  &lt;li&gt;SE altering contents itself&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As usual for this blog, this post relies on the &lt;a href=&quot;/tutotest/bs/eventClient.tuto&quot;&gt;FoxInCloud Live Tutorial&lt;/a&gt;, namely the &lt;em&gt;Surface Event&lt;/em&gt; form:&lt;/p&gt;

&lt;p&gt;&lt;img style=&quot;width:50%&quot; src=&quot;/blog/image/FLT-bs-SE-menu.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/tutotest/bs/eventClient.tuto&quot;&gt;&lt;img src=&quot;/blog/image/FLT-bs-SE.png&quot; alt=&quot;FoxInCloud Live Tutorial's *Surface Event* form&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1 id=&quot;surface-events-altering-display-only&quot;&gt;Surface Events altering display only&lt;/h1&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;If you have such effect in your Desktop Application, you obviously want a similar effect to happen in your FoxInCloud Web Application.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Buttons in the &lt;em&gt;Surface Event&lt;/em&gt; form are derived from this a class: &lt;code&gt;modify class ficCmdHover of  home(1) + 'tools\ab\aw\sample\fic\class\ficSample'&lt;/code&gt;. After running &lt;a href=&quot;/blog/2018/04/17/why-how-adapt-your-app-for-web.html&quot;&gt;FAA step 2&lt;/a&gt;, its code looks like this &lt;sup id=&quot;fnref:2&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-vfp&quot; data-lang=&quot;vfp&quot;&gt;PROCEDURE Init
* {en} create properties to save current aspect
this.AddProperty(&amp;#39;FontBold_&amp;#39;, this.FontBold)
this.AddProperty(&amp;#39;BackColor_&amp;#39;, this.BackColor)
this.AddProperty(&amp;#39;ForeColor_&amp;#39;, this.ForeColor)
return DoDefault()

* ---------------------------------------------
PROCEDURE MouseEnter
lparameters nButton, nShift, nXcoord, nYcoord &amp;amp;&amp;amp; {en} doc in Parent Code

IF (Type(&amp;#39;m.thisForm.wlHTMLgen&amp;#39;) == &amp;#39;L&amp;#39; AND m.thisForm.wlHTMLgen) &amp;amp;&amp;amp; {en} Added by FoxInCloud base classes Manager (source mode)
  return .F.
endif

* {en} save current aspect
this.FontBold_  = this.FontBold
this.BackColor_ = this.BackColor
this.ForeColor_ = this.ForeColor

* {en} set hover aspect
this.FontBold  = !this.FontBold
this.BackColor = 0 &amp;amp;&amp;amp; black
this.ForeColor = Rgb(255,255,255) &amp;amp;&amp;amp; white

* ---------------------------------------------
PROCEDURE MouseLeave
lparameters nButton, nShift, nXcoord, nYcoord &amp;amp;&amp;amp; {en} doc in Parent Code

IF (Type(&amp;#39;m.thisForm.wlHTMLgen&amp;#39;) == &amp;#39;L&amp;#39; AND m.thisForm.wlHTMLgen) &amp;amp;&amp;amp; {en} Added by FoxInCloud base classes Manager (source mode)
  return .F.
endif

* {en} restore previous aspect
this.FontBold = this.FontBold_
this.BackColor = this.BackColor_
this.ForeColor = this.ForeColor_&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;By default in &lt;em&gt;Surface Events&lt;/em&gt; code, FAA has added &lt;code&gt;RETURN .F.&lt;/code&gt; to prevent FAS from implementing an event handler that would send the event to the server.&lt;/p&gt;

&lt;p&gt;Below we’ll see how to implement a similar effect on the web using &lt;code&gt;JavaScript&lt;/code&gt;, &lt;code&gt;CSS&lt;/code&gt;, or both &lt;sup id=&quot;fnref:3&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;h2 id=&quot;solution-1-using-javascript-only&quot;&gt;Solution 1. Using JavaScript only&lt;/h2&gt;

&lt;p&gt;Using JavaScript is the method closest to what we used to do in VFP; however it takes limited advantage of more powerful Web techniques.&lt;/p&gt;

&lt;p&gt;Here are some hints for understanding the code below:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;FoxInCloud considers non-empty string value that event method returns from within &lt;code&gt;if m.thisForm.wlHTMLgen … endif&lt;/code&gt; as JavaScript code to be executed in the browser when a similar event occurs,&lt;/li&gt;
  &lt;li&gt;We use the &lt;code&gt;textmerge&lt;/code&gt; keyword to easily combine JavaScript code and VFP values&lt;/li&gt;
  &lt;li&gt;Each adapted VFP object inherits a &lt;code&gt;.wcID&lt;/code&gt; property that FoxInCloud populates with a unique ID at runtime &lt;sup id=&quot;fnref:4&quot;&gt;&lt;a href=&quot;#fn:4&quot; class=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;; it also uses this ID to populate the &lt;code&gt;id&lt;/code&gt; and &lt;code&gt;class&lt;/code&gt; attributes when generating the corresponding HTML element.&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;jQuery&lt;/code&gt; is a popular JavaScript framework (library) that FoxInCloud installs and loads automatically; &lt;code&gt;jQuery('#id')&lt;/code&gt; selects the element in the page having ‘id’ as &lt;code&gt;id=&quot;&quot;&lt;/code&gt; attribute (see previous point), and exposes methods that alter the HTML element and/or its CSS&lt;/li&gt;
  &lt;li&gt;To change the HTML element’s aspect, we use the jQuery &lt;a href=&quot;https://api.jquery.com/css/&quot;&gt;&lt;code&gt;.css()&lt;/code&gt;&lt;/a&gt; method with an object as parameter; each property of this object is named as the corresponding CSS property&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;{&quot;property&quot;: value, &quot;property&quot;: value, …}&lt;/code&gt; is called JavaScript Object Notation (JSON), in other word a literal representing an object &lt;sup id=&quot;fnref:5&quot;&gt;&lt;a href=&quot;#fn:5&quot; class=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
  &lt;li&gt;Regarding line termination, JavaScript and VFP work the other way round: JS uses ‘;’ as instruction terminator, instructions without a closing ‘;’ continue on next line&lt;/li&gt;
  &lt;li&gt;Block comment &lt;code&gt;/* comment */&lt;/code&gt; can be located anywhere, even inside an instruction&lt;/li&gt;
&lt;/ol&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-vfp&quot; data-lang=&quot;vfp&quot;&gt;PROCEDURE MouseEnter
lparameters nButton, nShift, nXcoord, nYcoord &amp;amp;&amp;amp; {en} doc in Parent Code

DoDefault() &amp;amp;&amp;amp; see code in parent class

* {en} We change the HTML element&amp;#39;s style directly with jQuery.css() with an object using JSON syntax as parameter
* {en} This technique is the closest to what you&amp;#39;re used to do in VFP, however not very &amp;#39;web-aware&amp;#39;…
* {en} Note that you can see the HTML changing in the browser development tools

IF (Type(&amp;#39;m.thisForm.wlHTMLgen&amp;#39;) == &amp;#39;L&amp;#39; AND m.thisForm.wlHTMLgen) &amp;amp;&amp;amp; {en} Added by FoxInCloud base classes Manager (source mode)

  local lcJS
  text to lcJS textmerge noshow flags 1 pretext 15
    jQuery(&amp;quot;.&amp;lt;&amp;lt;this.wcID&amp;gt;&amp;gt;&amp;quot;).css({ /* jQuery() creates an object around the HTML element(s) with a &amp;#39;.css()&amp;#39; method */
        &amp;quot;font-weight&amp;quot;: &amp;quot;bold&amp;quot;
      , &amp;quot;color&amp;quot;: &amp;quot;white&amp;quot;
      , &amp;quot;background-color&amp;quot;: &amp;quot;black&amp;quot;
     }); /* End of instruction starting with &amp;#39;jQuery(&amp;#39; */
  endtext
 
  RETURN m.lcJS &amp;amp;&amp;amp; {en} FoxInCloud interprets a non-empty string as JavaScript to be executed when event occurs
endif

* ----------------------------------
PROCEDURE MouseLeave
lparameters nButton, nShift, nXcoord, nYcoord &amp;amp;&amp;amp; {en} doc in Parent Code

DoDefault() &amp;amp;&amp;amp; see code in parent class

* {en} We change the HTML element&amp;#39;s style directly by passing an object using JSON syntax to jQuery.css()
* {en} This technique is the closest to what you use to do in VFP, however not very &amp;#39;web-aware&amp;#39;…
* {en} Note that setting the back color back to what is in VFP may contradict what you expect from a CSS framework such as Bootstrap…
* {en} Also note that you can see the HTML changing in the browser development tools

IF (Type(&amp;#39;m.thisForm.wlHTMLgen&amp;#39;) == &amp;#39;L&amp;#39; AND m.thisForm.wlHTMLgen) &amp;amp;&amp;amp; {en} Added by FoxInCloud base classes Manager (source mode)

  local lcJS
  text to lcJS textmerge noshow flags 1 pretext 15
    jQuery(&amp;quot;.&amp;lt;&amp;lt;this.wcID&amp;gt;&amp;gt;&amp;quot;).css({ /* jQuery() creates an object around the HTML element(s) with a &amp;#39;.css()&amp;#39; method */
        &amp;quot;font-weight&amp;quot;: &amp;quot;&amp;lt;&amp;lt;Iif(this.FontBold_, &amp;#39;bold&amp;#39;, &amp;#39;normal&amp;#39;)&amp;gt;&amp;gt;&amp;quot;
      , &amp;quot;color&amp;quot;: &amp;quot;&amp;lt;&amp;lt;HTMLColor(this.foreColor_)&amp;gt;&amp;gt;&amp;quot;
      , &amp;quot;background-color&amp;quot;: &amp;quot;&amp;lt;&amp;lt;HTMLColor(this.backColor_)&amp;gt;&amp;gt;&amp;quot;
     }); /* End of instruction starting with &amp;#39;jQuery(&amp;#39; */
  endtext

  RETURN m.lcJS &amp;amp;&amp;amp; {en} FoxInCloud interprets a non-empty string as JavaScript to be executed when event occurs
endif&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Note that this code changes the HTML of the element, and this change can be observed in the browser developer tool:&lt;/p&gt;

&lt;p&gt;HTML of the button before hovering:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&amp;lt;button type=&amp;quot;button&amp;quot; id=&amp;quot;eventclient_scx-pgf-pagaspect-cmdjs&amp;quot;
class=&amp;quot;eventclient_scx-pgf-pagaspect-cmdjs btn btn-default btn-lg&amp;quot;
tabindex=&amp;quot;330&amp;quot; data-original-title=&amp;quot;eventclient_scx.pgf.pagAspect.cmdJS&amp;quot;&amp;gt;
JavaScript only
&amp;lt;/button&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;After hovering the button, the style attribute is set:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&amp;lt;button type=&amp;quot;button&amp;quot; id=&amp;quot;eventclient_scx-pgf-pagaspect-cmdjs&amp;quot;
class=&amp;quot;eventclient_scx-pgf-pagaspect-cmdjs btn btn-default btn-lg&amp;quot;
tabindex=&amp;quot;330&amp;quot; data-original-title=&amp;quot;eventclient_scx.pgf.pagAspect.cmdJS&amp;quot;
style=&amp;quot;font-weight: normal; color: rgb(0, 0, 0); background-color: rgb(240, 240, 240);&amp;quot;&amp;gt;
JavaScript only
&amp;lt;/button&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Note that this JavaScript-driven alteration of HTML style attribute (AKA &lt;code&gt;inline style&lt;/code&gt;) 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:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/image/FLT-bs-SE-1-JS.png&quot; alt=&quot;Using JavaScript to change aspect may conflict with CSS&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;solution-2-using-javascript-and-css&quot;&gt;Solution 2. Using JavaScript and CSS&lt;/h2&gt;

&lt;p&gt;In this second example, we’ll define a class-based CSS rule in the application’s custom CSS file &lt;a href=&quot;/tutotest/bs/fileDisplay.tuto?tuto.css&quot;&gt;&lt;code&gt;tuto.css&lt;/code&gt;&lt;/a&gt; &lt;sup id=&quot;fnref:6&quot;&gt;&lt;a href=&quot;#fn:6&quot; class=&quot;footnote&quot;&gt;6&lt;/a&gt;&lt;/sup&gt; and,  when mouse enters/leaves, dynamically add/remove this class to/from the HTML object.&lt;/p&gt;

&lt;p&gt;Again, as the &lt;code&gt;class&lt;/code&gt; attribute is part of HTML, we need JavaScript to alter its value, and &lt;code&gt;jQuery&lt;/code&gt; will also come to the rescue to simplify the code, namely its &lt;a href=&quot;http://api.jquery.com/addClass/&quot;&gt;&lt;code&gt;.addClass()&lt;/code&gt;&lt;/a&gt; and&lt;a href=&quot;http://api.jquery.com/removeClass/&quot;&gt; &lt;code&gt;.removeClass()&lt;/code&gt;&lt;/a&gt; methods &lt;sup id=&quot;fnref:7&quot;&gt;&lt;a href=&quot;#fn:7&quot; class=&quot;footnote&quot;&gt;7&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Here are some hints for understanding the code below:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;As a variation, in &lt;code&gt;jQuery(&quot;.&amp;lt;&amp;lt;this.wcID&amp;gt;&amp;gt;&quot;)&lt;/code&gt;, we use a class selector (‘.’) instead of an id selector (‘#’). You can use either one as FoxInCloud automatically assigns the same unique string (&lt;code&gt;eventclient_scx-pgf-pagaspect-cmdjscss&lt;/code&gt;) as ID and class:&lt;/li&gt;
&lt;/ul&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-html&quot; data-lang=&quot;html&quot;&gt;&amp;lt;button type=&amp;quot;button&amp;quot; id=&amp;quot;eventclient_scx-pgf-pagaspect-cmdjscss&amp;quot;
class=&amp;quot;eventclient_scx-pgf-pagaspect-cmdjscss btn btn-default btn-lg&amp;quot;
title=&amp;quot;eventclient_scx.pgf.pagAspect.cmdJSCSS&amp;quot; tabindex=&amp;quot;331&amp;quot;&amp;gt;
JavaScript + CSS
&amp;lt;/button&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;ul&gt;
  &lt;li&gt;a rule is defined in &lt;a href=&quot;/tutotest/bs/fileDisplay.tuto?tuto.css&quot;&gt;&lt;code&gt;tuto.css&lt;/code&gt;&lt;/a&gt; with the class selector &lt;code&gt;.cmd_Hover&lt;/code&gt; &lt;sup id=&quot;fnref:8&quot;&gt;&lt;a href=&quot;#fn:8&quot; class=&quot;footnote&quot;&gt;8&lt;/a&gt;&lt;/sup&gt;:&lt;/li&gt;
&lt;/ul&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;.eventclient_scx button:not([disabled]).cmd_Hover {
  font-weight: bold;
  color: white;
  background-color: black;
}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;The selector &lt;code&gt;.eventclient_scx button:not([disabled]).cmd_Hover&lt;/code&gt; means: any button that is a descendant of an element of class &lt;code&gt;eventclient_scx&lt;/code&gt; (the form), is enabled and has class &lt;code&gt;cmd_Hover&lt;/code&gt;.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-vfp&quot; data-lang=&quot;vfp&quot;&gt;PROCEDURE cmdJSCSS.MouseEnter
  lparameters nButton, nShift, nXcoord, nYcoord &amp;amp;&amp;amp; {en} doc in Parent Code

  DoDefault() &amp;amp;&amp;amp; see code in parent class

  * {en} In this method, we add a HTML class on .MouseEnter(), and remove it on .MouseLeave()
  * {en} We define the CSS rule applicable to class &amp;#39;cmd_Hover&amp;#39; in the application CSS file:
  * {en}   modify file tuto.css ; we can update this file separately from the application.
  * {en} Note that we use &amp;#39;_&amp;#39; and capital letters in the custom class name; it can&amp;#39;t conflict with framework class name that never use these characters

  IF (Type(&amp;#39;m.thisForm.wlHTMLgen&amp;#39;) == &amp;#39;L&amp;#39; AND m.thisForm.wlHTMLgen) &amp;amp;&amp;amp; {en} Added by FoxInCloud base classes Manager (source mode)
    RETURN Textmerge([jQuery(&amp;quot;.&amp;lt;&amp;lt;this.wcID&amp;gt;&amp;gt;&amp;quot;).addClass(&amp;#39;cmd_Hover&amp;#39;);])
  endif
ENDPROC

PROCEDURE cmdJSCSS.MouseLeave
  lparameters nButton, nShift, nXcoord, nYcoord &amp;amp;&amp;amp; {en} doc in Parent Code

  DoDefault() &amp;amp;&amp;amp; see code in parent class

  * {en} In this method, we add a HTML class on .MouseEnter(), and remove it on .MouseLeave()
  * {en} We define the CSS rule applicable to class &amp;#39;cmd_Hover&amp;#39; in the application CSS file:
  * {en}   modify file tuto.css ; we can update this file separately from the application.
  * {en} Note that we use &amp;#39;_&amp;#39; and capital in custom class name; it can&amp;#39;t conflict with framework class name that never use these characters

  IF (Type(&amp;#39;m.thisForm.wlHTMLgen&amp;#39;) == &amp;#39;L&amp;#39; AND m.thisForm.wlHTMLgen) &amp;amp;&amp;amp; {en} Added by FoxInCloud base classes Manager (source mode)
    RETURN Textmerge([jQuery(&amp;quot;.&amp;lt;&amp;lt;this.wcID&amp;gt;&amp;gt;&amp;quot;).removeClass(&amp;#39;cmd_Hover&amp;#39;);])
  endif
ENDPROC&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Note that the browser (re)evaluates the CSS rules dynamically – and immediatly – whenever any component of the rules changes in HTML.&lt;/p&gt;

&lt;h2 id=&quot;solution-3-using-pure-css-version-1&quot;&gt;Solution 3. Using ‘pure’ CSS, version 1&lt;/h2&gt;

&lt;p&gt;The previous case has unveiled the power of &lt;a href=&quot;https://www.w3.org/TR/selectors-3/&quot;&gt;CSS selector syntax&lt;/a&gt; that can work on:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;element position in the page hierarchy tree&lt;/strong&gt;: descendant, child, sibling, first-of, last-of, etc.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;element attributes&lt;/strong&gt;: #id, .class and any other HTML attribute&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;element state&lt;/strong&gt; :disabled, :checked, :hover, etc. &lt;sup id=&quot;fnref:9&quot;&gt;&lt;a href=&quot;#fn:9&quot; class=&quot;footnote&quot;&gt;9&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;:hover&lt;/code&gt; state fulfills what we need in this case: change the element’s aspect when mouse hovers it.&lt;/p&gt;

&lt;p&gt;In this solution, we’ll add a rule to the CSS rules that FoxInCloud generates into a file named &lt;code&gt;awDefault*.css&lt;/code&gt; &lt;sup id=&quot;fnref:10&quot;&gt;&lt;a href=&quot;#fn:10&quot; class=&quot;footnote&quot;&gt;10&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;We add this rule in the &lt;code&gt;.wcHTMLgen()&lt;/code&gt; method that the object inherits from the &lt;code&gt;aw???&lt;/code&gt; 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 &lt;code&gt;.CSScustomAdd()&lt;/code&gt; method.&lt;/p&gt;

&lt;p&gt;Here are some hints for understanding the code below:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code&gt;toHTMLgen AS awHTMLgen OF awHTML.prg&lt;/code&gt; is a reference to the FoxInCloud HTML generator that drills into the form and containers until each individual member;&lt;/li&gt;
  &lt;li&gt;Depending on the value that this method &lt;code&gt;RETURN&lt;/code&gt;s and/or writes into &lt;code&gt;.wcHTML&lt;/code&gt;, the HTML generator &lt;code&gt;toHTMLgen&lt;/code&gt; generates standard or custom HTML;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;.wcHTMLgen()&lt;/code&gt; 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;&lt;/li&gt;
  &lt;li&gt;The &lt;code&gt;.CSScustomAdd()&lt;/code&gt; method adds custom CSS rules to the standard &lt;code&gt;awDefault*.css&lt;/code&gt; style sheet, that the custom style sheet &lt;code&gt;xxx.css&lt;/code&gt; can override if needed.&lt;/li&gt;
&lt;/ol&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-vfp&quot; data-lang=&quot;vfp&quot;&gt;PROCEDURE cmdCSS1.wchtmlgen
  LPARAMETERS toHTMLgen AS awHTMLgen OF awHTML.prg, tlInnerHTML &amp;amp;&amp;amp; {en} doc in Parent Code

  DoDefault(m.toHTMLgen, m.tlInnerHTML)

  * {en} Add a &amp;#39;:hover&amp;#39; CSS rule on this object (could be several objects using a class instead of an ID)
  * {en} FoxInCloud adds this rule to the generated default CSS style sheet for application: awDefault*.css
  &amp;amp;&amp;amp; {en} note 1: in CSS pure language, &amp;#39;:hover&amp;#39; is called a &amp;#39;pseudo-class&amp;#39;; browser development tools use this wording
  &amp;amp;&amp;amp; {en} note 2: that JS and CSS syntaxes are close; however in CSS directives are unquoted and separated by &amp;#39;;&amp;#39; instead of &amp;#39;,&amp;#39;
  &amp;amp;&amp;amp; {en} note 3: this rule automatically restores initial aspect when mouse leaves the button

  local lcCSS

  text to lcCSS textmerge noshow flags 1 pretext 15
    #&amp;lt;&amp;lt;this.wcID&amp;gt;&amp;gt;:hover {
      font-weight: bold;
      color: white;
      background-color: black;
     }
  endtext

  m.toHTMLgen.CSScustomAdd(m.lcCSS)
ENDPROC&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;This solutions works fine for a small number of controls, however, if all controls of a given &lt;code&gt;BaseClass&lt;/code&gt; must have a similar behavor, the solution 4 hereafter is more efficient.&lt;/p&gt;

&lt;h2 id=&quot;solution-4-using-pure-css-version-2&quot;&gt;Solution 4. Using ‘pure’ CSS, version 2&lt;/h2&gt;

&lt;p&gt;This solution combines several features that we’ve gone through in the previous solutions:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;.class CSS selector&lt;/strong&gt;: we will a class to the generated HTML element and build a CSS rule based on this custom CSS class&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;:hover pseudo class&lt;/strong&gt;; our custom CSS rule will focus on the &lt;code&gt;:hover&lt;/code&gt; state of the custom CSS class above&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;custom CSS class upon HTML generation&lt;/strong&gt; besides &lt;code&gt;.wcHTMLgen()&lt;/code&gt;, each adapted VFP object inherits a &lt;code&gt;.wCSSclassAdd&lt;/code&gt; 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 &lt;strong&gt;design time&lt;/strong&gt;, using the VFP visual designer, or at &lt;strong&gt;run time&lt;/strong&gt;, in &lt;code&gt;.Init()&lt;/code&gt; or &lt;code&gt;form.Load()&lt;/code&gt; &lt;sup id=&quot;fnref:11&quot;&gt;&lt;a href=&quot;#fn:11&quot; class=&quot;footnote&quot;&gt;11&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-vfp&quot; data-lang=&quot;vfp&quot;&gt;PROCEDURE cmdCSS2.Init
  * {en} add a CSS class to this object
  * {en} note 1: a &amp;#39;cmd-hover2:hover&amp;#39; rule is defined in tuto.css (custom style sheet for this application)
  * {en} note 2: could also be done at design time in property sheet; we prefer do it programmatically in case the parent class also has this property defined
  * {en} note 3: we could also add this CSS class to the parent class (ficCmdHover) to have all derived buttons behave this way

  this.wCSSclassAdd = this.wCSSclassAdd;
    + Iif(empty(this.wCSSclassAdd), &amp;#39;&amp;#39;, &amp;#39; &amp;#39;);
    + &amp;#39;cmd_Hover2&amp;#39;

  return DoDefault()
ENDPROC&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;&lt;a href=&quot;/tutotest/bs/fileDisplay.tuto?tuto.css&quot;&gt;&lt;code&gt;tuto.css&lt;/code&gt;&lt;/a&gt; defines the corresponding CSS rule:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-css&quot; data-lang=&quot;css&quot;&gt;.eventclient_scx button:not([disabled]).cmd_Hover2:hover {
  font-weight: bold;
  color: white;
  background-color: black;
}&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;As &lt;a href=&quot;/tutotest/bs/fileDisplay.tuto?tuto.css&quot;&gt;&lt;code&gt;tuto.css&lt;/code&gt;&lt;/a&gt; can be updated in production separately from the app, changing the behavior (eg. &lt;code&gt;background-color&lt;/code&gt;) does not require updating the application.&lt;/p&gt;

&lt;h1 id=&quot;surface-events-altering-contents&quot;&gt;Surface Events altering contents&lt;/h1&gt;

&lt;p&gt;&lt;a href=&quot;/tutotest/bs/eventClient.tuto?awParm01=2&quot;&gt;&lt;img src=&quot;/blog/image/FLT-bs-SE-2.png&quot; alt=&quot;FoxInCloud Live Tutorial's *Surface Event* form&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/tutotest/bs/eventClient.tuto?awParm01=2&quot;&gt;&lt;img src=&quot;/blog/image/FLT-bs-SE-2_.png&quot; alt=&quot;FoxInCloud Live Tutorial's *Surface Event* form&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Altering HTML contents always require JavaScript; CSS can alter the aspect of contents only, not the contents itself.&lt;/p&gt;

&lt;p&gt;To change HTML contents, we also use &lt;code&gt;jQuery&lt;/code&gt; and its utility methods:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;http://api.jquery.com/prop/&quot;&gt;&lt;code&gt;.prop()&lt;/code&gt;&lt;/a&gt;: creates or reads a property of the HTML element&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;http://api.jquery.com/text/&quot;&gt;&lt;code&gt;.text()&lt;/code&gt;&lt;/a&gt;: replaces or reads the text inside HTML paired tags &lt;sup id=&quot;fnref:12&quot;&gt;&lt;a href=&quot;#fn:12&quot; class=&quot;footnote&quot;&gt;12&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note that FoxInCloud detects the user browser’s preferred language as a &lt;a href=&quot;https://en.wikipedia.org/wiki/ISO_639&quot;&gt;2-letter ISO 639 code&lt;/a&gt; and stores it into:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;client side&lt;/strong&gt;: &lt;code&gt;FoxInCloud.lang&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;server side&lt;/strong&gt;: &lt;code&gt;thisForm.wcLangUser&lt;/code&gt; (inherited from &lt;code&gt;aw.vcx!awFrm&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-vfp&quot; data-lang=&quot;vfp&quot;&gt;PROCEDURE cmd.Init
  this.AddProperty(&amp;#39;Caption_&amp;#39;, &amp;#39;&amp;#39;)
  return DoDefault()
ENDPROC

PROCEDURE cmd.MouseEnter
  lparameters nButton, nShift, nXcoord, nYcoord &amp;amp;&amp;amp; {en} doc in Parent Code

  local caption_FR, caption_DE, caption_IT, caption_ES, caption_PT, caption_EN

  caption_FR = &amp;quot;Vous me survolez&amp;quot;
  caption_DE = &amp;quot;Du schwebst mich&amp;quot;
  caption_IT = &amp;quot;Mi stai sorvolando&amp;quot;
  caption_ES = &amp;quot;Me estás rondando&amp;quot;
  caption_PT = &amp;quot;Você está me pairando&amp;quot;
  caption_EN = &amp;quot;You&amp;#39;re hovering me&amp;quot;

  IF (Type(&amp;#39;m.thisForm.wlHTMLgen&amp;#39;) == &amp;#39;L&amp;#39; AND m.thisForm.wlHTMLgen) &amp;amp;&amp;amp; {en} Added by FoxInCloud base classes Manager (source mode)

    &amp;amp;&amp;amp; {en} This code executes first time server instantiates the form, once for all users
    &amp;amp;&amp;amp; {en} As this code executes out of a user context, the user language is not known and must be evalutated at run time
    &amp;amp;&amp;amp; {en} At run time, FoxInCloud detects user browser&amp;#39;s preferred language and stores it in FoxInCloud.lang (coded on 2 letters as per ISO 639-1 https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes)
    &amp;amp;&amp;amp; {en} The JavaScript code below adjusts the contents to the user&amp;#39;s language

    local lcJS

    text to lcJS textmerge noshow flags 1 pretext 7
      var cmd = jQuery(&amp;#39;#&amp;lt;&amp;lt;this.wcID&amp;gt;&amp;gt;&amp;#39;); /* get a reference to the jQuery object wrapped around this HTML element */
      cmd.prop(&amp;#39;Caption_&amp;#39;, cmd.text()); /* Save current Caption to a new property of this element created on the fly */
      var newText = &amp;#39;&amp;#39;;
      switch (FoxInCloud.lang) { /* https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Instructions/switch */
      case &amp;#39;fr&amp;#39;:
        newText = &amp;lt;&amp;lt;cLitteralJS(m.Caption_FR)&amp;gt;&amp;gt;;
      case &amp;#39;de&amp;#39;:
        newText = &amp;lt;&amp;lt;cLitteralJS(m.Caption_DE)&amp;gt;&amp;gt;;
      case &amp;#39;it&amp;#39;:
        newText = &amp;lt;&amp;lt;cLitteralJS(m.Caption_IT)&amp;gt;&amp;gt;;
      case &amp;#39;es&amp;#39;:
        newText = &amp;lt;&amp;lt;cLitteralJS(m.Caption_ES)&amp;gt;&amp;gt;;
      case &amp;#39;pt&amp;#39;:
        newText = &amp;lt;&amp;lt;cLitteralJS(m.Caption_PT)&amp;gt;&amp;gt;;
      default:
        newText = &amp;lt;&amp;lt;cLitteralJS(m.Caption_EN)&amp;gt;&amp;gt;;
      }

      /* We can also use a syntax similar to ICase() by nesting ternary operators similar to Iif() [condition ? value if true : value if false] …
      slight downside: nested operators need be wrapped inside parentheses for some browsers (eg. IE).
      Below we indent the closing parentheses the same as the opening counterpart to visually prevent nesting errors */

      newText = FoxInCloud.lang === &amp;#39;fr&amp;#39;
        ? &amp;lt;&amp;lt;cLitteralJS(m.Caption_FR)&amp;gt;&amp;gt;
        : (FoxInCloud.lang === &amp;#39;de&amp;#39;
          ? &amp;lt;&amp;lt;cLitteralJS(m.Caption_DE)&amp;gt;&amp;gt;
          : (FoxInCloud.lang === &amp;#39;it&amp;#39;
            ? &amp;lt;&amp;lt;cLitteralJS(m.Caption_IT)&amp;gt;&amp;gt;
            : (FoxInCloud.lang === &amp;#39;es&amp;#39;
              ? &amp;lt;&amp;lt;cLitteralJS(m.Caption_ES)&amp;gt;&amp;gt;
              : (FoxInCloud.lang === &amp;#39;pt&amp;#39;
                ? &amp;lt;&amp;lt;cLitteralJS(m.Caption_PT)&amp;gt;&amp;gt;
                : &amp;lt;&amp;lt;cLitteralJS(m.Caption_EN)&amp;gt;&amp;gt;
          ) ) ) );

      cmd.text(newText + &amp;#39;…!&amp;#39;); /* Assign new caption to the button */
    endtext

    RETURN m.lcJS &amp;amp;&amp;amp; {en} FoxInCloud interprets a non-empty string as JavaScript to be executed when event occurs
  endif

  &amp;amp;&amp;amp; {en} This code executes in desktop mode only

  this.Caption_ = this.Caption

  this.Caption = ICase(;
    thisForm.wcLangUser = &amp;#39;fr&amp;#39;, m.caption_FR,;
    thisform.wcLangUser = &amp;#39;de&amp;#39;, m.caption_DE,;
    thisform.wcLangUser = &amp;#39;it&amp;#39;, m.caption_IT,;
    thisform.wcLangUser = &amp;#39;es&amp;#39;, m.caption_ES,;
    thisform.wcLangUser = &amp;#39;pt&amp;#39;, m.caption_PT,;
    m.caption_en;
    ) + &amp;#39;…!&amp;#39;
ENDPROC

PROCEDURE cmd.MouseLeave
  lparameters nButton, nShift, nXcoord, nYcoord &amp;amp;&amp;amp; {en} doc in Parent Code

  IF (Type(&amp;#39;m.thisForm.wlHTMLgen&amp;#39;) == &amp;#39;L&amp;#39; AND m.thisForm.wlHTMLgen) &amp;amp;&amp;amp; {en} Added by FoxInCloud base classes Manager (source mode)

    &amp;amp;&amp;amp; {en} This code executes first time server instantiates the form, once for all users
    &amp;amp;&amp;amp; {en} As this code executes out of a user context, the user language is not known and must be evalutated at run time
    &amp;amp;&amp;amp; {en} At run time, FoxInCloud detects user browser&amp;#39;s preferred language and stores it in FoxInCloud.lang (coded on 2 letters as per ISO 639-1 https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes)
    &amp;amp;&amp;amp; {en} The JavaScript code below adjusts the contents to the user&amp;#39;s language

    local lcJS

    text to lcJS textmerge noshow flags 1 pretext 7
      var cmd = jQuery(&amp;#39;#&amp;lt;&amp;lt;this.wcID&amp;gt;&amp;gt;&amp;#39;); /* get a reference to the jQuery object wrapped around this HTML element */
      cmd.text(cmd.prop(&amp;#39;Caption_&amp;#39;)); /* Assign previous saved caption to the button */
    endtext

    RETURN m.lcJS &amp;amp;&amp;amp; {en} FoxInCloud interprets a non-empty string as JavaScript to be executed when event occurs
  endif

  &amp;amp;&amp;amp; {en} This code executes in desktop mode only

  this.Caption = this.Caption_
ENDPROC&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h1 id=&quot;wrap-up&quot;&gt;Wrap-up&lt;/h1&gt;

&lt;p&gt;Hopefully this post has teached you the important basics of CSS and JS programming, and the main hooks where FoxInCloud lets you add this &lt;em&gt;client-side&lt;/em&gt; code to your application:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;CSS selectors&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;jQuery&lt;/code&gt; and its utility methods&lt;/li&gt;
  &lt;li&gt;FoxInCloud CSS: &lt;code&gt;awDefault*.css&lt;/code&gt; and &lt;code&gt;xxx.css&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;In VFP event methods, return &lt;code&gt;JavaScript&lt;/code&gt; from within &lt;code&gt;if m.thisForm.wlHTMLgen … endif&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;.wcHTMLgen()&lt;/code&gt; for generating custom HTML, CSS and/JS&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;.wCSSclassAdd&lt;/code&gt; for adding CSS class(es) to one object or all objects derived from a class&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;toHTMLgen.CSScustomAdd()&lt;/code&gt; to add custom CSS rules&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;video&quot;&gt;Video&lt;/h2&gt;

&lt;iframe width=&quot;740&quot; height=&quot;416&quot; src=&quot;https://www.youtube.com/embed/Z1IjcP3rEqY&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;hr /&gt;

&lt;div class=&quot;footnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;on some controls like &lt;code&gt;textBox&lt;/code&gt;, &lt;code&gt;.InteractiveChange()&lt;/code&gt; also falls into the ‘Surface Event’ category, that FoxInCloud will soon support using the recent HTML DOM Event level 3 API &lt;code&gt;.oninput()&lt;/code&gt; &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot;&gt;
      &lt;p&gt;Button instances in &lt;code&gt;EventClient.scx&lt;/code&gt; call this form using &lt;code&gt;dodefault()&lt;/code&gt; &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot;&gt;
      &lt;p&gt;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 &lt;code&gt;&amp;lt;b&amp;gt;, &amp;lt;i&amp;gt;&lt;/code&gt;, &lt;code&gt;width, align, background&lt;/code&gt;, 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 &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:4&quot;&gt;
      &lt;p&gt;this ID concatenates &lt;code&gt;.Name&lt;/code&gt; of form, object parents and object itself &lt;a href=&quot;#fnref:4&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:5&quot;&gt;
      &lt;p&gt;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… &lt;a href=&quot;#fnref:5&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:6&quot;&gt;
      &lt;p&gt;named after the FoxInCloud Web App &lt;code&gt;xxx&lt;/code&gt; code – &lt;a href=&quot;/tutotest/bs/fileDisplay.tuto?tuto.css&quot;&gt;&lt;code&gt;tuto.css&lt;/code&gt;&lt;/a&gt; in this case – the App custom CSS file &lt;code&gt;xxx.css&lt;/code&gt; is loaded by FoxInCloud on each page/form, after all other CSS files, particularly the default, FiC-generated &lt;code&gt;awDefault*.css&lt;/code&gt;. This gives the ability to (1) override any standard CSS directive and (2) define custom directives. &lt;a href=&quot;#fnref:6&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:7&quot;&gt;
      &lt;p&gt;note the camel case convention: in the ‘Web world’, everything is lower case except the first letter of successive words. &lt;a href=&quot;#fnref:7&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:8&quot;&gt;
      &lt;p&gt;note the block comment has the same syntax as in JavaScript &lt;a href=&quot;#fnref:8&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:9&quot;&gt;
      &lt;p&gt;W3C calls these state modifiers ‘pseudo-classes’ &lt;a href=&quot;#fnref:9&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:10&quot;&gt;
      &lt;p&gt;during development, FoxInCloud dynamically generates &lt;code&gt;awDefault_&amp;lt;sys(2015)&amp;gt;.css&lt;/code&gt;, and &lt;code&gt;awDefaultAll.css&lt;/code&gt; for production &lt;a href=&quot;#fnref:10&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:11&quot;&gt;
      &lt;p&gt;altering &lt;code&gt;.wCSSclassAdd&lt;/code&gt; at run time is advisable for easier maintenance in case &lt;code&gt;.wCSSclassAdd&lt;/code&gt; changes in a parent class. &lt;a href=&quot;#fnref:11&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:12&quot;&gt;
      &lt;p&gt;while some tags such as &lt;code&gt;&amp;lt;br&amp;gt;&lt;/code&gt; or &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; are unpaired or self-closing, most HTML tags require a closing tag: &lt;code&gt;&amp;lt;p&amp;gt;text&amp;lt;/p&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;i&amp;gt;text&amp;lt;/i&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;div&amp;gt;text&amp;lt;/div&amp;gt;&lt;/code&gt;, etc. &lt;a href=&quot;#fnref:12&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Wed, 11 Jul 2018 00:00:00 +0200</pubDate>
        <link>http://localhost:4000/blog/2018/07/11/adapting-surface-events.html</link>
        <guid isPermaLink="true">http://localhost:4000/blog/2018/07/11/adapting-surface-events.html</guid>
        
        <category>user experience</category>
        
        <category>adaptation</category>
        
        <category>JavaScript</category>
        
        <category>CSS</category>
        
        
      </item>
    
      <item>
        <title>Learning FoxInCloud with the FoxInCloud Live Tutorial</title>
        <description>&lt;p&gt;Experienced FoxPro Developers using FoxInCloud all around the world need more than an English documentation: live code that they can understand, learn from, and adapt for their own Application.&lt;/p&gt;

&lt;p&gt;FoxInCloud provides the &lt;strong&gt;&lt;code&gt;FoxInCloud Live Tutorial&lt;/code&gt;&lt;/strong&gt; that developers can use either on line or locally, in the VFP IDE and the &lt;code&gt;http://localhost/&lt;/code&gt; Web site.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;FoxInCloud Live Tutorial&lt;/strong&gt; (FLT) provides working examples of:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;the main cases of adaptation&lt;/li&gt;
  &lt;li&gt;features and scenarios that maybe you doubt FoxInCloud can support&lt;/li&gt;
  &lt;li&gt;the full source code of the application:
    &lt;ul&gt;
      &lt;li&gt;forms and classes&lt;/li&gt;
      &lt;li&gt;programs&lt;/li&gt;
      &lt;li&gt;configuration&lt;/li&gt;
      &lt;li&gt;JavaScript and CSS files&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In Web mode, you can see the forms using 2 different HTML renderings:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Classic&lt;/strong&gt; rendering: controls are laid out just like in the original VFP form, with &lt;em&gt;absolute&lt;/em&gt; positioning using &lt;code&gt;.left&lt;/code&gt;,  &lt;code&gt;.top&lt;/code&gt;,  &lt;code&gt;.width&lt;/code&gt;,  &lt;code&gt;.height&lt;/code&gt; like VFP,&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Responsive&lt;/strong&gt; rendering: controls are laid out similar to the original VFP form, albeit with a &lt;em&gt;relative&lt;/em&gt; positioning that automatically adapts to the device screen size &lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;: controls that can’t fit in width automatically wrap below their predecessor.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can also see the forms either as a &lt;strong&gt;full page&lt;/strong&gt; (like a &lt;code&gt;Top Level Form&lt;/code&gt; in VFP), or as a &lt;strong&gt;child form&lt;/strong&gt;.&lt;/p&gt;

&lt;h1 id=&quot;using-the-foxincloud-live-tutorial-on-line&quot;&gt;Using the FoxInCloud Live Tutorial &lt;em&gt;on line&lt;/em&gt;&lt;/h1&gt;

&lt;p&gt;Just type in your browser &lt;a href=&quot;http://foxincloud.com/tutoTest/&quot;&gt;http://foxincloud.com/tutoTest/&lt;/a&gt;; you get the &lt;em&gt;classic&lt;/em&gt; version:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://foxincloud.com/tutoTest/&quot;&gt;&lt;img src=&quot;/blog/image/FLT.png&quot; alt=&quot;FoxInCloud Live Tutorial home, classic mode&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that the menu on the left derives from a &lt;code&gt;tuto.mnx&lt;/code&gt; VFP menu, the rest being generated from a VFP form.&lt;/p&gt;

&lt;p&gt;This version’s layout does not change according to browser size, it just overflows:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/image/FLT-narrow.png&quot; alt=&quot;FoxInCloud Live Tutorial home, classic mode&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;switching-to-the-responsive-version-of-flt&quot;&gt;Switching to the &lt;em&gt;Responsive&lt;/em&gt; version of FLT&lt;/h2&gt;

&lt;p&gt;You can display the &lt;em&gt;Responsive&lt;/em&gt; version of FLT either by:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;clicking the ‘Responsive’ button at the top right of the form&lt;/li&gt;
  &lt;li&gt;type in your browser &lt;a href=&quot;http://foxincloud.com/tutoTest/bs/&quot;&gt;http://foxincloud.com/tutoTest/bs/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In both cases you get:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://foxincloud.com/tutoTest/bs/&quot;&gt;&lt;img src=&quot;/blog/image/FLT-bs.png&quot; alt=&quot;FoxInCloud Live Tutorial home, responsive mode&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As it’s responsive, this version  adapts to the browser’s width (notice that the menu has wrapped on 2 lines, the fox is now hidden and the control buttons are now at the bottom):&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/image/FLT-bs-md.png&quot; alt=&quot;FoxInCloud Live Tutorial home, responsive mode, medium&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The layout further changes when narrowing further the browser width (notice the menu collapsed to a ‘hamburger’ menu):&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/image/FLT-bs-sm.png&quot; alt=&quot;FoxInCloud Live Tutorial home, responsive mode, small&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;displaying-the-same-form-as-a-full-page-or-as-a-child-form&quot;&gt;Displaying the same form as a full page or as a child form&lt;/h2&gt;

&lt;p&gt;Let’s display the ‘Controls &amp;amp; Events’ form which demonstrates the range of VFP Controls and Events that FoxInCloud supports:&lt;/p&gt;

&lt;h3 id=&quot;1-as-a-full-page&quot;&gt;1. as a full page&lt;/h3&gt;

&lt;p&gt;In the ‘Support’ menu, select the ‘Controls &amp;amp; Events’ pad:&lt;/p&gt;

&lt;p&gt;&lt;img style=&quot;width:50%&quot; src=&quot;/blog/image/FLT-bs-CE-menu.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;You get the ‘Controls &amp;amp; Events’ form displayed as a full page:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://foxincloud.com/tutotest/bs/Event.tuto&quot;&gt;&lt;img src=&quot;/blog/image/FLT-bs-CE-full.png&quot; alt=&quot;'Controls &amp;amp; Events' form displayed as a full page&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;2-as-a-child-form&quot;&gt;2. as a child form&lt;/h3&gt;

&lt;p&gt;Get back to ‘home’ and click the ‘Controls &amp;amp; Events’ button:&lt;/p&gt;

&lt;p&gt;&lt;img alt=&quot;'Controls &amp;amp; Events' button&quot; style=&quot;width:50%&quot; src=&quot;/blog/image/FLT-bs-CE-btn.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;You get the ‘Controls &amp;amp; Events’ form displayed as a child form:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/image/FLT-bs-CE-child.png&quot; alt=&quot;'Controls &amp;amp; Events' form displayed as a full page&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Note that &lt;strong&gt;both forms share the exact same code&lt;/strong&gt; and expose the exact same functionalities – go ahead testing!&lt;/p&gt;

&lt;p&gt;The benefit of displaying a form as a full page is that you can provide a direct link to any form: eg. &lt;a href=&quot;http://foxincloud.com/tutotest/bs/Event.tuto&quot;&gt;http://foxincloud.com/tutotest/bs/Event.tuto&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;displaying-the-same-form-in-responsive-and-classic-modes&quot;&gt;Displaying the same form in ‘Responsive’ and ‘Classic’ modes&lt;/h2&gt;

&lt;p&gt;In the ‘Support’ menu, select the ‘Controls &amp;amp; Events’ pad:&lt;/p&gt;

&lt;p&gt;&lt;img alt=&quot;'Controls &amp;amp; Events' pad&quot; style=&quot;width:50%&quot; src=&quot;/blog/image/FLT-bs-CE-menu.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;You get the ‘Controls &amp;amp; Events’ form displayed in ‘Responsive’ mode:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://foxincloud.com/tutotest/bs/Event.tuto&quot;&gt;&lt;img src=&quot;/blog/image/FLT-bs-CE-full.png&quot; alt=&quot;'Controls &amp;amp; Events' form displayed as a full page&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then click on the ‘Classic’ option button:&lt;/p&gt;

&lt;p&gt;&lt;img alt=&quot;'Classic' option button&quot; style=&quot;width:50%&quot; src=&quot;/blog/image/FLT-bs-classic-opt.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;You get the same ‘Controls &amp;amp; Events’ form in classic mode:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/image/FLT-CE-full.png&quot; alt=&quot;'Controls &amp;amp; Events' form displayed as a full page in classic mode&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;reviewing-the-source-code-of-some-vfp-object&quot;&gt;Reviewing the source code of some VFP object&lt;/h2&gt;

&lt;p&gt;The FoxInCloud Live Tutorial gives you the ability to review, on line, the code running in an object just be hovering that object with your mouse.&lt;/p&gt;

&lt;p&gt;Open the &lt;code&gt;Modal&lt;/code&gt; form (# 1 in ‘Adaptation’ menu):&lt;/p&gt;

&lt;p&gt;&lt;img alt=&quot;'Modal form data return' menu&quot; style=&quot;width:50%&quot; src=&quot;/blog/image/FLT-bs-MF-menu.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://foxincloud.com/tutotest/bs/Modal.tuto&quot;&gt;&lt;img src=&quot;/blog/image/FLT-bs-MF-full.png&quot; alt=&quot;'Modal' form displayed as a full page&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When hovering any of the buttons in the form, you see the corresponding source code appear in the code frame below:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://foxincloud.com/tutotest/bs/Modal.tuto&quot;&gt;&lt;img src=&quot;/blog/image/FLT-bs-MF-full-code.png&quot; alt=&quot;'Modal' form button code displays when hovering&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ctrl-clicking the code area displays it into a new browser tab &lt;sup id=&quot;fnref:3&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/image/FLT-bs-MF-code.png&quot; alt=&quot;Ctrl-clicking the code area displays it into a new tab&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;reviewing-the-source-code-of-a-vfp-form&quot;&gt;Reviewing the source code of a VFP form&lt;/h2&gt;

&lt;p&gt;Each form in FLT has a source code button &lt;code&gt;&amp;lt;/&amp;gt;&lt;/code&gt; to display the full form source code;&lt;/p&gt;

&lt;p&gt;&lt;img alt=&quot;'Form VFP source code' button&quot; style=&quot;width:20%&quot; src=&quot;/blog/image/FLT-srce-btn.png&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;click&lt;/code&gt; opens VFP code a new child form:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/blog/image/FLT-srce-form.png&quot; alt=&quot;VFP Form code displayed in a new child form&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;ctrl+click&lt;/code&gt; opens VFP code a new browser tab &lt;sup id=&quot;fnref:3:1&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/blog/image/FLT-srce-tab.png&quot; alt=&quot;VFP Form code displayed in a new browser tab&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;getting-details-about-a-vfp-form&quot;&gt;Getting details about a VFP form&lt;/h2&gt;

&lt;p&gt;Need more information about a form in FoxInCloud Live Tutorial? Clicking the fox head will tell you more…&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/image/FLT-help-form.png&quot; alt=&quot;Additional information on a VFP Form&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;reviewing-the-full-app-source-code&quot;&gt;Reviewing the full app. source code&lt;/h2&gt;

&lt;p&gt;Besides code in forms, you can review the full application source code by using the ‘Source’ menu:&lt;/p&gt;

&lt;p&gt;&lt;img alt=&quot;'Source code' menu item&quot; style=&quot;width:50%&quot; src=&quot;/blog/image/FLT-BS-menu-Source.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Eg., clicking &lt;code&gt;Main program&lt;/code&gt; displays the Web Application Server’s main program source code:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/image/FLT-main-code.png&quot; alt=&quot;Web Application Server's main program source code&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;reviewing-the-foxincloud-web-application-dashboard&quot;&gt;Reviewing the FoxInCloud Web Application Dashboard&lt;/h2&gt;

&lt;p&gt;The FoxInCloud Web Application Dashboard is the central point where you get control over all the operations of your Web Application: errors (if any), users, status, and much more… &lt;sup id=&quot;fnref:2&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;&lt;img alt=&quot;'FoxInCloud Web Application Dashboard' menu item&quot; style=&quot;width:50%&quot; src=&quot;/blog/image/FLT-FWAD-menu.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://foxincloud.com/tutotest/bs/foxincloud-status.tuto&quot;&gt;&lt;img src=&quot;/blog/image/FLT-FWAD.png&quot; alt=&quot;FoxInCloud Web Application Dashboard&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;debugging-your-web-application&quot;&gt;Debugging your Web Application&lt;/h2&gt;

&lt;p&gt;Among many other benefits, a Web Application logs about everything you’d dream of knowing to understand and fix errors.&lt;/p&gt;

&lt;p&gt;As a standard feature, FoxInCloud provides a very handy Error Browser where you can see what each user has done just before and after each error:&lt;/p&gt;

&lt;p&gt;&lt;img alt=&quot;'FoxInCloud Web Application Error Browser' menu item&quot; style=&quot;width:30%&quot; src=&quot;/blog/image/FLT-EB-menu.png&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://foxincloud.com/tutotest/bs/ErrorLog.tuto&quot;&gt;&lt;img src=&quot;/blog/image/FLT-EB.png&quot; alt=&quot;FoxInCloud Web Application Error Browser&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1 id=&quot;using-the-foxincloud-live-tutorial-locally&quot;&gt;Using the FoxInCloud Live Tutorial &lt;em&gt;locally&lt;/em&gt;&lt;/h1&gt;

&lt;p&gt;Still in doubt about what’s running under the hood? Just run the same features locally, right from within your VFP IDE!&lt;/p&gt;

&lt;h2 id=&quot;1-install-foxincloud-web-application-studio-fws&quot;&gt;1. Install FoxInCloud Web Application Studio (FWS)&lt;/h2&gt;

&lt;p&gt;Just follow the steps in this blog post: &lt;a href=&quot;http://foxincloud.com/blog/2018/05/17/Managing-your-foxincloud-project.html#round-i-heat-up&quot;&gt;Managing your FoxInCloud Project&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once you’ve completed these steps,&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Start VFP using the FWS shortcut on your desktop:&lt;br /&gt;
&lt;img alt=&quot;FWS shortcut on your desktop&quot; style=&quot;width:20%&quot; src=&quot;/blog/image/FWS-shortcut.png&quot; /&gt;&lt;/li&gt;
  &lt;li&gt;You now have a FoxInCloud pad in your VFP system menu &lt;sup id=&quot;fnref:4&quot;&gt;&lt;a href=&quot;#fn:4&quot; class=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;:&lt;br /&gt;
&lt;img src=&quot;/blog/image/FWS-pad.png&quot; alt=&quot;FoxInCloud system menu pad&quot; /&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2 id=&quot;2-run-foxincloud-live-tutorial-in-desktop-mode&quot;&gt;2. Run FoxInCloud Live Tutorial in Desktop mode&lt;/h2&gt;

&lt;p&gt;As any FoxInCloud application, FLT runs the same code on the desktop and on the Web… You may want to see first how it goes on the desktop…&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/image/FWS-menu-FLT-desktop.png&quot; alt=&quot;Run FoxInCloud Live Tutorial on the desktop&quot; /&gt;&lt;/p&gt;

&lt;p&gt;You can see the FLT home page:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/image/tutoLAN.index.png&quot; alt=&quot;FoxInCloud Live Tutorial desktop home page&quot; /&gt;&lt;/p&gt;

&lt;p&gt;You can also see in your VFP IDE the FLT LAN/desktop project open that you can explore once you’re done testing the FLT LAN/desktop app:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/image/tutoLAN.project.png&quot; alt=&quot;FoxInCloud Live Tutorial desktop home page&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;3-run-foxincloud-live-tutorial-in-web-mode&quot;&gt;3. Run FoxInCloud Live Tutorial in Web mode&lt;/h2&gt;

&lt;p&gt;As the FoxInCloud installation has created the FoxInCloud Live Tutorial Web Application for you, you can start it just by selecting this menu item:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/image/FWS-menu-FLT-web-local.png&quot; alt=&quot;Run FoxInCloud Live Tutorial in the browser, responsive version&quot; /&gt;&lt;/p&gt;

&lt;p&gt;You can see your default browser pop up and loading the FoxInCloud Live Tutorial home page…&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/image/FLT-bs-loading.png&quot; alt=&quot;FoxInCloud Live Tutorial home page loading&quot; /&gt;&lt;/p&gt;

&lt;p&gt;… while the FLT Web Application Server is starting within the VFP IDE:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/image/FLT-server-IDE.png&quot; alt=&quot;FoxInCloud Live Tutorial Web Application Server IDE&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Once the the FLT Web Application Server has started …&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/image/FLT-server-IDE-done.png&quot; alt=&quot;FoxInCloud Live Tutorial Web Application Server IDE&quot; /&gt;&lt;/p&gt;

&lt;p&gt;… FoxInCloud Live Tutorial home page is loaded in the browser:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/image/FLT-bs-loaded.png&quot; alt=&quot;FoxInCloud Live Tutorial home page loaded&quot; /&gt;&lt;/p&gt;

&lt;p&gt;When stopping the Application Server using the ‘exit’ button, you can see the Web Application project open in the VFP IDE, from where you can open and explore the full source code:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/image/tutoTest.project.png&quot; alt=&quot;FoxInCloud Live Tutorial home page loaded&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;video-wrap-up&quot;&gt;Video wrap-up&lt;/h1&gt;

&lt;iframe width=&quot;740&quot; height=&quot;416&quot; src=&quot;https://www.youtube.com/embed/ywvXGQ9dZn4&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;hr /&gt;

&lt;div class=&quot;footnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;Responsive rendering uses the popular and free &lt;a href=&quot;https://getbootstrap.com/&quot;&gt;Bootstrap framework&lt;/a&gt; &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot;&gt;
      &lt;p&gt;you may need to allow popups on &lt;code&gt;foxincloud.com&lt;/code&gt; &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt; &lt;a href=&quot;#fnref:3:1&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot;&gt;
      &lt;p&gt;the FoxInCloud Web Application Dashboard requires a secured authentication by default; for the FoxInCloud Live Tutorial, this safety was removed for demo purpose. &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:4&quot;&gt;
      &lt;p&gt;captions and menu items may be slightly different in your case depending on the extensions you’ve loaded in VFP &lt;a href=&quot;#fnref:4&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Thu, 05 Jul 2018 00:00:00 +0200</pubDate>
        <link>http://localhost:4000/blog/2018/07/05/Learning-FoxInCloud-with-Live-Tutorial.html</link>
        <guid isPermaLink="true">http://localhost:4000/blog/2018/07/05/Learning-FoxInCloud-with-Live-Tutorial.html</guid>
        
        <category>learning</category>
        
        <category>adaptation</category>
        
        <category>development</category>
        
        
      </item>
    
      <item>
        <title>Managing your FoxInCloud Project</title>
        <description>&lt;p&gt;This post describes how to adapt and publish your VFP application as a Web Application from scratch.&lt;/p&gt;

&lt;p&gt;With FoxInCloud, your application runs the same code on the Web, and on the Desktop as usual.&lt;/p&gt;

&lt;p&gt;This is made possible by adapting your application’s code to run in either mode; these adaptations are simple, and many are automated:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;adding new instructions such as testing desktop mode or web mode,&lt;/li&gt;
  &lt;li&gt;moving instructions to another method without changing the functionality,&lt;/li&gt;
  &lt;li&gt;replacing native instructions such as &lt;code&gt;DO FORM&lt;/code&gt; by calls to functions or methods provided by FoxInCloud.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The free &lt;code&gt;FoxInCloud Adaptation Assistant&lt;/code&gt; (FAA, see below) identifies the adaptations in your app., performs as many as possible, and leaves the more complex to your attention. You can open and modify the source code right from FAA, and FAA provides you the guidance on why and how you can do the adaptation.&lt;/p&gt;

&lt;p&gt;As the adapted code runs the same in desktop mode, you can adapt your application progressively, while continuing the regular maintenance and evolutions that your daily client service requires.&lt;/p&gt;

&lt;p&gt;You can also create a new sub-project with only the forms that you intend to expose to the Web, publish to production, then expand it over time; this project and your regular desktop project share the same adapted files that run in desktop mode side by side with non-adapted files.&lt;/p&gt;

&lt;p&gt;All the FoxInCloud resources on which your adapted code relies (installed in &lt;code&gt;home(1) + &quot;tools\ab\&quot;&lt;/code&gt;) are free to use and distribute with your desktop application. These files are also always available in a &lt;a href=&quot;https://github.com/FoxInCloud/FoxInCloud-AB&quot;&gt;public GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://foxincloud.com/images/awAdapter-en.png&quot; alt=&quot;FoxInCloud Adaptation Assistant&quot; /&gt;&lt;/p&gt;

&lt;h1 id=&quot;round-i-heat-up&quot;&gt;Round I: Heat-up&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Est. duration: 2 hours&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this first sequence you will verify that you have all the necessary softwares and services installed on your development machine.&lt;/p&gt;

&lt;h2 id=&quot;1--make-sure-you-run-the-latest-vfp9-sp2&quot;&gt;1- Make sure you run the latest VFP9 SP2&lt;/h2&gt;

&lt;p&gt;This VFP command should display &lt;code&gt;Visual FoxPro 09.00.0000.7423 for Windows&lt;/code&gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-vfp&quot; data-lang=&quot;vfp&quot;&gt;? Version()&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;If the last 4 figures are less than &lt;code&gt;5815&lt;/code&gt;, first download and install &lt;a href=&quot;https://www.microsoft.com/en-us/download/details.aspx?id=13959&quot;&gt;VFP9 SP2&lt;/a&gt; from the Microsoft site.&lt;/p&gt;

&lt;p&gt;Then download and install &lt;a href=&quot;https://github.com/VFPX/VFP9SP2Hotfix3&quot;&gt;SP2 Hotfix 3&lt;/a&gt; from the VFPx site.&lt;/p&gt;

&lt;h2 id=&quot;2--install-foxincloud-adaptation-assistant-faa&quot;&gt;2- Install FoxInCloud Adaptation Assistant (FAA)&lt;/h2&gt;

&lt;p&gt;Go to the &lt;a href=&quot;download.php&quot;&gt;FoxInCloud download page&lt;/a&gt;, click on the FAA screenshot and save &lt;code&gt;awAdapterSetup.zip&lt;/code&gt;. Expand this archive into a sub-folder &lt;code&gt;awAdapterSetup\&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Read the text files &lt;code&gt;awAdapter-licence-*.txt&lt;/code&gt; and &lt;code&gt;awAdapterSetup-*.txt&lt;/code&gt; (brief description of what &lt;code&gt;awAdapterSetup.exe&lt;/code&gt; will do on your computer).&lt;/p&gt;

&lt;p&gt;Then double-click the VFP executable &lt;code&gt;awAdapterSetup.exe&lt;/code&gt;; if ever you don’t have the proper version of VFP installed or associated to &lt;code&gt;*.exe&lt;/code&gt;, you’ll get a ‘VFP resource mismatch’ message, then get back to step 1; otherwise &lt;code&gt;awAdapterSetup.exe&lt;/code&gt; copies the necessary files to your computer and displays the result as explained in the &lt;code&gt;awAdapterSetup-*.txt&lt;/code&gt; text file.&lt;/p&gt;

&lt;p&gt;Clicking OK in the final message box automatically starts FAA:
&lt;img src=&quot;/blog/image/awAdapterSetup-2.png&quot; alt=&quot;FAA installation completed message box&quot; /&gt;.&lt;/p&gt;

&lt;p&gt;Whenever a new version is posted on the FoxInCloud site, when starting while connected to the Internet, FAA downloads and installs this new version automatically.&lt;/p&gt;

&lt;h2 id=&quot;3--make-sure-iis-is-installed-on-your-development-machine&quot;&gt;3- Make sure IIS is installed on your development machine&lt;/h2&gt;

&lt;p&gt;You can follow different tracks to check IIS is installed (translate the &lt;code&gt;strings&lt;/code&gt; into your OS language):&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Press the Windows key on your keyboard, type &lt;code&gt;Windows Features&lt;/code&gt;, press Enter&lt;/li&gt;
  &lt;li&gt;In Windows Explorer address bar, type &lt;code&gt;control panel&lt;/code&gt;, then select &lt;code&gt;applications&lt;/code&gt;, then &lt;code&gt;Turn Windows Features on or off&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;For Windows 10, open the parameters pane, select &lt;code&gt;Applications&lt;/code&gt;, then &lt;code&gt;Application and features&lt;/code&gt;, then move to the bottom and select &lt;code&gt;programs and features&lt;/code&gt;, then click &lt;code&gt;Turn Windows Features on or off&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This displays the Windows Features Treeview:
&lt;img src=&quot;https://webconnection.west-wind.com/docs/IMAGES/misc/IISFeatures.png&quot; alt=&quot;Windows Features Treeview&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Check the options like indicated in the above image or, if you hesitate or have difficulties in matching your OS language to this picture, select all options &lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;Next, to make sure IIS will have the right to access the folder where your application resides:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Open the IIS management console (Press Windows key then type ‘IIS’ and press ‘Enter’),&lt;/li&gt;
  &lt;li&gt;Navigate to the ‘Sites’ node,&lt;/li&gt;
  &lt;li&gt;Click “Define the default values for Web sites”,&lt;/li&gt;
  &lt;li&gt;In the ‘Identification…’ line, click the ellipsis&lt;/li&gt;
  &lt;li&gt;Type in your user ID and passWord; IIS will use this account to access the folder wherever your Web Application is later installed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;4--install-foxincloud-application-server-fas-and-foxincloud-web-application-studio-fws&quot;&gt;4- Install FoxInCloud Application Server (FAS) and FoxInCloud Web Application Studio (FWS)&lt;/h2&gt;

&lt;p&gt;Grab FAS for free by signing up your on the &lt;a href=&quot;http://foxincloud.com/download.php#trialForm&quot;&gt;FoxInCloud download page&lt;/a&gt; &lt;sup id=&quot;fnref:5&quot;&gt;&lt;a href=&quot;#fn:5&quot; class=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;The file you download is a signed MSI-based InstallShield installation package, with all due security protections.&lt;/p&gt;

&lt;p&gt;Running the installation installs:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;The FoxInCloud Application Server in &lt;code&gt;home(1) + 'tools\ab\aw\'&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;The FoxInCloud Samples in  &lt;code&gt;home(1) + 'tools\ab\aw\samples'&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;The sample applications in IIS that you can run locally&lt;/li&gt;
  &lt;li&gt;A &lt;code&gt;FoxInCloud Web Application Studio&lt;/code&gt; shortcut on your desktop&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At this stage you have 2 FoxInCloud shortcuts on your desktop:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/image/aw-128.jpg&quot; alt=&quot;FoxInCloud shortcut&quot; /&gt;&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;FoxInCloud Adaptation Assistant (FAA)&lt;/li&gt;
  &lt;li&gt;FoxInCloud Web App. Studio (FWS)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In the first steps of your FoxInCloud journey, you’ll probably use more the FAA shortcut and concentrate on Adaptations.&lt;/p&gt;

&lt;p&gt;After a while, when you start testing your app in the browser, you’ll favor FWS shortcut that provides you all the resources, including FAA from the &lt;code&gt;FoxInCloud&lt;/code&gt; menu added to VFP system menu.&lt;/p&gt;

&lt;p&gt;Make spend some time reviewing the options offered by the &lt;code&gt;FoxInCloud&lt;/code&gt; menu in FWS!&lt;/p&gt;

&lt;h1 id=&quot;round-ii-review-your-application-with-faa-in-copy-mode&quot;&gt;Round II: Review your application with FAA in &lt;em&gt;Copy Mode&lt;/em&gt;&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Est. duration: 1-2 days (including readings)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;(for more details, please consult this &lt;a href=&quot;http://foxincloud.com/pdf/FoxInCloud-How-to-FAAquickRef-en.pdf&quot;&gt;complete description of FAA operations&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;As explained earlier, FAA performs some adaptations automatically, modifying your application’s code.&lt;/p&gt;

&lt;p&gt;As FoxInCloud’s philosophy is to &lt;strong&gt;never break existing code&lt;/strong&gt; – just add new functionalities on top of existing features – FAA provides a way to check that what FAA does automatically preserves your code’s integrity: the &lt;code&gt;Copy Mode&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;Copy Mode&lt;/code&gt;, FAA &lt;strong&gt;copies your project and related files&lt;/strong&gt; to a &lt;code&gt;Test&lt;/code&gt; folder &lt;sup id=&quot;fnref:7&quot;&gt;&lt;a href=&quot;#fn:7&quot; class=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; and then works on this copy only: FAA leaves your source files unchanged &lt;sup id=&quot;fnref:2&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;only purpose&lt;/strong&gt; of &lt;code&gt;Copy Mode&lt;/code&gt; is to let you check that your desktop application runs the same after FAA automated adaptations; after you do a complete run in &lt;code&gt;Copy Mode&lt;/code&gt; you will just drop it in favor of &lt;code&gt;Source Mode&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;1--analyze-your-project-copy&quot;&gt;1- Analyze your project &lt;em&gt;copy&lt;/em&gt;&lt;/h2&gt;

&lt;p&gt;Click the red &lt;code&gt;+&lt;/code&gt; sign, pick your &lt;strong&gt;original project&lt;/strong&gt; and start analysis.&lt;/p&gt;

&lt;p&gt;Completed analysis provides a list of adaptations that you can sort and filter using the controls on top of the grid columns, and statistics at the bottom &lt;sup id=&quot;fnref:6&quot;&gt;&lt;a href=&quot;#fn:6&quot; class=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/image/FAA-mode.png&quot; alt=&quot;FAA statistics&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The mid pane explains how the current adaptation will be performed (either automatically or manually); you can display these explanations as a VFP program with code sample, and/or view a training video when available.&lt;/p&gt;

&lt;p&gt;Please note that the estimated adaptation effort is based on unit times that you can adapt to your project experience by clicking the red line “Estimated adaptation time” down right.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/image/FAA-est.png&quot; alt=&quot;FAA estimate&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;2--adapt-your-project-copy&quot;&gt;2- Adapt your project &lt;em&gt;copy&lt;/em&gt;&lt;/h2&gt;

&lt;p&gt;This step is why &lt;code&gt;Copy Mode&lt;/code&gt; exists: by clicking the &lt;code&gt;2-Adapt&lt;/code&gt; button, FAA performs the automated adaptations on your project’s copy.&lt;/p&gt;

&lt;p&gt;After this step, you will open the copy project and run your adapted application in desktop mode to make sure that FAA has broken nothing in your code that could prevent your applications from working OK.&lt;/p&gt;

&lt;p&gt;If ever you see something wrong, just shoot an email to &lt;code&gt;support at foxincloud dot com&lt;/code&gt; with the original code (unchanged in your original application) and the modified, not working code (in your application copy); we will fix the issue rapidly and post a new version of FAA that will update automatically at your next startup.&lt;/p&gt;

&lt;p&gt;To re-run Adaptation on the whole source code, make sure to select the “re-copy…” option in the drop down menu that appears when clicking the &lt;code&gt;2-Adapt&lt;/code&gt; button.&lt;/p&gt;

&lt;p&gt;Please &lt;strong&gt;make sure to test&lt;/strong&gt; your adapted application copy thoroughly until you find everything works fine as usual in desktop mode!&lt;/p&gt;

&lt;h2 id=&quot;3--publish-your-project-copy&quot;&gt;3- Publish your project &lt;em&gt;copy&lt;/em&gt;&lt;/h2&gt;

&lt;p&gt;This step is just a way for you to make sure that the Web App publication works fine for you with all required dependencies available; it is a temporary publication that the final &lt;code&gt;Source Mode&lt;/code&gt; publication will later override.&lt;/p&gt;

&lt;p&gt;At least you can see some of your form display in the browser, which you are eager to see happen…&lt;/p&gt;

&lt;p&gt;It can also help you understand how the publication wizard works and train at using it.&lt;/p&gt;

&lt;p&gt;After this step completes, you have 2 Web projects named &lt;code&gt;xxxTest&lt;/code&gt; and &lt;code&gt;xxxProd&lt;/code&gt;, located in the same folder as your copy project.&lt;br /&gt;
FAA creates 2 projects to let you later deploy 2 versions of your Web Application on the Production Server, one for Testing and one for Production. You may choose to deploy a single application or both according to your preference.&lt;/p&gt;

&lt;p&gt;These 2 projects won’t probably not build completely, especially when using the Trial edition where a lot of FoxInCloud code is gathered in &lt;code&gt;aw.app&lt;/code&gt;, causing project manager to complain for missing references.&lt;br /&gt;
This is perfectly normal and has no consequence as Trial does not support building an &lt;code&gt;app&lt;/code&gt; or an &lt;code&gt;exe&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;However you can use these projects a shortcuts to the files generated by FoxInCloud &lt;sup id=&quot;fnref:8&quot;&gt;&lt;a href=&quot;#fn:8&quot; class=&quot;footnote&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;, and later start the Server from within the FWS IDE.&lt;/p&gt;

&lt;p&gt;Important: from now on, make sure to always open a &lt;code&gt;FoxInCloud Web Application Studio&lt;/code&gt; IDE to work on your adapted application and, most importantly, start your FoxInCloud Web Application Server. If anything goes wrong such as a missing procedure or class, select &lt;code&gt;restore environment&lt;/code&gt; from the &lt;code&gt;FoxInCloud&lt;/code&gt; system menu pad.&lt;/p&gt;

&lt;h2 id=&quot;tips-and-tricks&quot;&gt;Tips and tricks&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Code changes you do in &lt;code&gt;Copy Mode&lt;/code&gt; may be overridden next time you Analyze or Adapt because FAA may overwrite your modified copy by the original file. Change code in &lt;code&gt;Copy Mode&lt;/code&gt; for training only, and/or to check manually adapted code runs the same in desktop mode.&lt;/li&gt;
  &lt;li&gt;FAA project-level settings and options are memorized separately for &lt;code&gt;Copy Mode&lt;/code&gt; and &lt;code&gt;Source Mode&lt;/code&gt;: mode, review, ignore, statistics, etc.&lt;/li&gt;
  &lt;li&gt;You can re-do over and over any of the 3 steps: Analyze, Adapt and Publish&lt;/li&gt;
  &lt;li&gt;You can learn from the adapted applications installed with FoxInCloud: just browse the &lt;code&gt;FoxInCloud&lt;/code&gt; menu to start either desktop, local Web and/or remote Web versions. You have the full source code of these applications for your review.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;round-iii-adapt-your-app-source-code-for-real&quot;&gt;Round III: Adapt your app Source Code, for real&lt;/h1&gt;

&lt;p&gt;Once you have successfully completed step II above, you switch FAA to &lt;code&gt;Source Mode&lt;/code&gt; and start the final steps that will end up by putting your Web Application into Production.&lt;/p&gt;

&lt;p&gt;From now on there’s no need to step back to &lt;code&gt;Copy Mode&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;1--analysis&quot;&gt;1- Analysis&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Est. duration: 15’ to hour(s) depending on your application size&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Very similar to what happened in &lt;code&gt;Copy Mode&lt;/code&gt;, just let FAA complete the scan.&lt;/p&gt;

&lt;h2 id=&quot;2--adapt&quot;&gt;2- Adapt&lt;/h2&gt;

&lt;h3 id=&quot;a--automated&quot;&gt;a- Automated&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Est. duration: 15’ to hour(s) depending on your application size&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Click the button and let FAA complete his job:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;strong&gt;Replace native classes&lt;/strong&gt; by “FoxInCloud Base Classes”: eg. &lt;code&gt;Form&lt;/code&gt; replaced by &lt;code&gt;awFrm of aw.vcx&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Perform the Automated Adaptations&lt;/strong&gt; identified at step 1&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;When this steps completes, you should no longer see any adaptation tagged as “Automated Adaptation” in FAA left drop-down list.&lt;/p&gt;

&lt;h3 id=&quot;b--manual&quot;&gt;b- Manual&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Est. duration: depending on your application: see figures provided by FAA&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/blog/image/FAA-stats.png&quot; alt=&quot;FAA statistics&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Here comes the part where your development skills come at play.&lt;/p&gt;

&lt;p&gt;At this stage you need to filter the Adaptations list on &lt;code&gt;Manual Adaptations after Step 2- Adapt&lt;/code&gt; (left drop-down)&lt;/p&gt;

&lt;p&gt;We recommend that you process adaptations by type rather than by file; eg. you could start with the call-back adaptations (‘User decision required: …’) that are the most critical. For instance, select one of such adaptation that you can easily test (eg. on an easily accessible form), do it, and test it right away to make sure you’ve fully understood the process.&lt;/p&gt;

&lt;p&gt;Also make sure to test your application after a bunch of adaptations to remain sure you’re on the right track.&lt;/p&gt;

&lt;p&gt;Nothing changes at this stage and this is perfectly normal: it’s just your application running the same as usual, with slightly different classes and code, albeit ready to run on the Web.&lt;/p&gt;

&lt;h3 id=&quot;tips-and-tricks-1&quot;&gt;Tips and tricks&lt;/h3&gt;

&lt;ul&gt;
  &lt;li&gt;If you KNOW that a module and/or file won’t be used in Web mode, and thus don’t need be adapted,
    &lt;ul&gt;
      &lt;li&gt;ignore it using the &lt;code&gt;Ignore&lt;/code&gt; button&lt;/li&gt;
      &lt;li&gt;choose the &lt;code&gt;not ignored&lt;/code&gt; option below: all ignored files, modules and adaptations will disappear from the list&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/blog/image/FAA-ignore.png&quot; alt=&quot;FAA 'ignore' feature&quot; /&gt;&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Once you’ve completed an Adaptation and want it removed from the list, you can either re-analyze the project or click &lt;code&gt;Ignore&lt;/code&gt; like above explained&lt;/li&gt;
  &lt;li&gt;In case of doubt that FAA documentation and/or video can’t address, ask for free support on any public area such as the VFP forums below &lt;sup id=&quot;fnref:3&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot;&gt;7&lt;/a&gt;&lt;/sup&gt;; please make sure to post the whole code where you have a doubt.&lt;/li&gt;
  &lt;li&gt;You may want to fully adapt a couple of forms for your first Web Application tests (see below).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;3--publish&quot;&gt;3- Publish&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Est. duration: 2 hours&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Once you have a couple of forms adapted, you can run step 3-Publish like you did earlier in &lt;code&gt;Copy Mode&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;When this Publish step completes &lt;sup id=&quot;fnref:4&quot;&gt;&lt;a href=&quot;#fn:4&quot; class=&quot;footnote&quot;&gt;8&lt;/a&gt;&lt;/sup&gt;, you &lt;strong&gt;need to review&lt;/strong&gt; the &lt;code&gt;xxxSets&lt;/code&gt; program that FAA has built from the startup code in your desktop application’s main program. Please make sure that this code is OK and edit it as you see fit. Make sure also to &lt;strong&gt;read the documentation&lt;/strong&gt; in this program to fully understand what it is used for.&lt;/p&gt;

&lt;p&gt;When typing in your browser: http://localhost/xxxTest/, you can see a a static page built by FAA showing a clickable list of your app’s forms.&lt;/p&gt;

&lt;p&gt;After starting your Application Server by typing in the FWS IDE command window &lt;code&gt;do &amp;lt;path to&amp;gt;xxxTest&lt;/code&gt;, you can click on any of these links and see your form rendered as HTML in the browser.&lt;/p&gt;

&lt;p&gt;Of course this is just a test page, not your final Web App home page! To install your Web App home page:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Open IIS management console like explained earlier&lt;/li&gt;
  &lt;li&gt;Navigate to your app node under ‘Default Web Site’: eg. &lt;code&gt;xxxTest&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Click ‘Default Document’&lt;/li&gt;
  &lt;li&gt;Click ‘Add’&lt;/li&gt;
  &lt;li&gt;Enter ‘index.xxx’, click OK&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now if you reload http://localhost/xxxTest/ in your browser, you see a sample home page using a ‘sampleIndex’ form (sample login form) installed by FoxInCloud.&lt;/p&gt;

&lt;p&gt;To replace this &lt;em&gt;sampleIndex&lt;/em&gt; by your own login form, &lt;code&gt;modify command xxxServer&lt;/code&gt;, navigate to &lt;code&gt;procedure Index&lt;/code&gt; and replace &lt;code&gt;'App\Sample\sampleIndex.scx'&lt;/code&gt; by the name of the your login form. Make sure to open your login form in the VFP designer and:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;set &lt;code&gt;.wlAnonymousAllowed = .T.&lt;/code&gt;&lt;/strong&gt;: this will allow this form to display to anonymous user,&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;adapt the login method&lt;/strong&gt; like in&lt;br /&gt;
&lt;code&gt;modify form App\Sample\sampleIndex.scx method txtPass.valid&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You could also have a splash form as index form, with a menu or a button calling the login form; in such case both these forms should have &lt;code&gt;.wlAnonymousAllowed = .T.&lt;/code&gt;. to know more about all the possible variations, just ask on a support forum &lt;sup id=&quot;fnref:3:1&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot;&gt;7&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;Once you’ve done this step successfully, your web app is up and running! Your Index form can either display a regular VFP menu or a ‘menu’ form with buttons opening the various sub-forms of your app. What’s really important is, just like in a desktop application, to set the starting point as explained above.&lt;/p&gt;

&lt;p&gt;Note that the &lt;code&gt;Publish&lt;/code&gt; step should run only once successfully; whenever your app shows up in the browser OK, you no longer need to run this step. You might want to re-run step 1 et 2 whenever you add new code to your application (see below). If your code is stable, you can just use FAA as its name states: an Assistant to help you identify and complete your adaptations.&lt;/p&gt;

&lt;h1 id=&quot;round-iv-maintain-your-adapted-source-code&quot;&gt;Round IV: Maintain your adapted Source Code&lt;/h1&gt;

&lt;p&gt;As FoxInCloud &lt;strong&gt;adapts, not converts&lt;/strong&gt; your application, your maintain a single (adapted) code base that you deploy on the Desktop as usual, and on the Web.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Desktop deployment&lt;/strong&gt; of adapted code does not require any additional license; all the FoxInCloud modules (*.prgs and *.vc?) added to your application are under GNU General Public License and thus can be included, distributed and even used in your application for free.&lt;/p&gt;

&lt;p&gt;Whenever your adapted app. needs new features, you can either (1) develop this new code as usual and later run FAA to adapt it or, as soon as you have a fair experience of adaptations, (2) develop this new code the &lt;em&gt;FoxInCloud way&lt;/em&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Base new classes and objects on the FoxInCloud sub-classes created by FAA (&lt;code&gt;xxx.vcx&lt;/code&gt;)&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Write adapted code; eg.:&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;implement a new event, adding 3 ‘magic lines’ as header:&lt;/li&gt;
&lt;/ul&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-vfp&quot; data-lang=&quot;vfp&quot;&gt;procedure someEvent
if thisForm.wlHTMLgen
  return
endif

&amp;amp;&amp;amp; your regular code starts here&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;ul&gt;
  &lt;li&gt;display a message box expecting a user response, add the call-back method as 1rst parameter:&lt;/li&gt;
&lt;/ul&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-vfp&quot; data-lang=&quot;vfp&quot;&gt;thisForm.wMessageBox(&amp;#39;wFormCallBack&amp;#39;, eMessageText [, nDialogBoxType ][, cTitleBarText][, nTimeout])
...
procedure wFormCallBack
lparameters tuUserChoice
if m.tuUserChoice = IDYES
  &amp;amp;&amp;amp; code processing user response
endif&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;ul&gt;
  &lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1 id=&quot;et-voilà&quot;&gt;Et voilà!&lt;/h1&gt;

&lt;p&gt;Hopefully this post has given you a complete view on the whole FoxInCloud development process, and helped you understand how to better use the free tools offered by FoxInCloud for adapting your application.&lt;/p&gt;

&lt;p&gt;This &lt;a href=&quot;/blog/2018/04/17/why-how-adapt-your-app-for-web.html&quot;&gt;earlier post&lt;/a&gt; further clarifies the why and how behind adaptations.&lt;/p&gt;

&lt;p&gt;Have a fruitful journey with FoxInCloud!&lt;/p&gt;

&lt;hr /&gt;

&lt;div class=&quot;footnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;Selecting all options is OK for a development machine having very little risk to be accessed from the outside world. Carefully selecting the options is mandatory on a Production Server. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:5&quot;&gt;
      &lt;p&gt;we will send you a notification email whenever newer versions are available; you can unsubscribe from any notification email you receive. &lt;a href=&quot;#fnref:5&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:7&quot;&gt;
      &lt;p&gt;By default, the files are copied to the same folder hierarchy within a &lt;code&gt;Test&lt;/code&gt; folder located at the root of the same drive. You can change this setting in FAA. &lt;a href=&quot;#fnref:7&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot;&gt;
      &lt;p&gt;When using &lt;code&gt;Copy Mode&lt;/code&gt;, you don’t need to copy your project for FAA! However, if you prefer to copy yourself, you can just run it in &lt;code&gt;Source Mode&lt;/code&gt;… &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:6&quot;&gt;
      &lt;p&gt;Statistics always reflect the current filter; eg. filtering on a file provides the estimated time to completely adapt it; this can help you organize the work of your team members. &lt;a href=&quot;#fnref:6&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:8&quot;&gt;
      &lt;p&gt;mainly &lt;code&gt;xxxTest.prg&lt;/code&gt; – Server startup, &lt;code&gt;xxxSets.prg&lt;/code&gt; – App Environment Settings, &lt;code&gt;xxxServer.prg&lt;/code&gt; – Server classes and settings; and other maintenance utilities in the &lt;code&gt;Progs\&lt;/code&gt; folder &lt;a href=&quot;#fnref:8&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot;&gt;
      &lt;p&gt;VFP support forums: https://support.west-wind.com/, https://www.levelextreme.com/, https://www.foxite.com/ &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt; &lt;a href=&quot;#fnref:3:1&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;sup&gt;2&lt;/sup&gt;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:4&quot;&gt;
      &lt;p&gt;in what follows, &lt;code&gt;xxx&lt;/code&gt; is the code you chose during the publish step. &lt;a href=&quot;#fnref:4&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Thu, 17 May 2018 00:00:00 +0200</pubDate>
        <link>http://localhost:4000/blog/2018/05/17/Managing-your-foxincloud-project.html</link>
        <guid isPermaLink="true">http://localhost:4000/blog/2018/05/17/Managing-your-foxincloud-project.html</guid>
        
        <category>strategy</category>
        
        <category>development</category>
        
        <category>adaptation</category>
        
        <category>FAA</category>
        
        
      </item>
    
      <item>
        <title>FoxInCloud 2.26.2 is released!</title>
        <description>&lt;h1 id=&quot;foxincloud-2262-even-more-hardened&quot;&gt;FoxInCloud 2.26.2: even more hardened&lt;/h1&gt;

&lt;p&gt;FoxInCloud 2.26.2 is the second maintenance release for version 2.26, the 26th in FoxInCloud History (close to 4 releases per year), tallying over &lt;a href=&quot;http://foxincloud.com/roadmap.php&quot;&gt;450 fixes, enhancements and support extensions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This is in the process of cleaning up the code, polishing functionalities based on user feedback, improving availability up close to the magic ‘4 nines’ (99.99%)&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://foxincloud.com/tutotest/bs/foxincloud-status.tuto?&amp;amp;tab=APPSTARTUP&quot;&gt;&lt;img src=&quot;/blog/image/FWAD-app-log_.png&quot; alt=&quot;FoxInCloud Web Application Availability&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;2.26.2 brings more than 13 fixes; even if it seems a few, most of these fixes respond to customer demands, to help them improve their Web app even more.&lt;/p&gt;

&lt;h2 id=&quot;execute-javascript-on-formactivate&quot;&gt;Execute JavaScript on form.activate()&lt;/h2&gt;

&lt;p&gt;One example of how a small fix can bring a new cool feature is the ability to execute some JavaScript on form.activate().&lt;/p&gt;

&lt;p&gt;By doing so, one FoxInCloud developer could display nice notifications when a form opens like shown on this video:&lt;/p&gt;

&lt;iframe width=&quot;100%&quot; height=&quot;550&quot; src=&quot;https://www.youtube.com/embed/EfsUjb63zjo&quot; frameborder=&quot;0&quot; allow=&quot;autoplay; encrypted-media&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;h2 id=&quot;use-graphical-web-icon-as-menu-bar-picture&quot;&gt;Use graphical Web icon as menu bar PICTURE&lt;/h2&gt;

&lt;p&gt;When using the Boostrap mode in FoxinCloud, it’s fun to replace the traditional Foxpro icons (.jpg, or even .bmp) by font-based vector icons from one of the 2 free icons sets provided with FoxInCloud: &lt;code&gt;Glyphicons&lt;/code&gt; and &lt;code&gt;Font-Awesome&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Whenever FoxInCloud finds a &lt;code&gt;PICTURE&lt;/code&gt; clause in some menu command, it adds this picture to the &lt;code&gt;awBSicon&lt;/code&gt; table where you can later associate the picture with a font-based icon; at run time, FoxInCloud places the latter into the popup like demonstrated in the &lt;a href=&quot;http://foxincloud.com/tutotest/bs/&quot;&gt;FoxInCloud Live Tutorial menu&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://foxincloud.com/tutotest/bs/&quot;&gt;&lt;img src=&quot;/blog/image/FLT-bs-menu-source_code.png&quot; alt=&quot;FoxInCloud Live Tutorial menu&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note above that ‘traditional’ and font-based icons can co-exist in the same menu popup.&lt;/p&gt;

&lt;h2 id=&quot;foxincloud-adaptation-assistant-enhancements&quot;&gt;FoxInCloud Adaptation Assistant enhancements&lt;/h2&gt;

&lt;p&gt;We love your feedback on &lt;code&gt;FAA&lt;/code&gt;! You manage to find issues that we would otherwise never find! Thanks also for using the error feedback form.&lt;/p&gt;
</description>
        <pubDate>Thu, 19 Apr 2018 00:00:00 +0200</pubDate>
        <link>http://localhost:4000/blog/2018/04/19/FoxInCloud-2.26.2-is-released.html</link>
        <guid isPermaLink="true">http://localhost:4000/blog/2018/04/19/FoxInCloud-2.26.2-is-released.html</guid>
        
        <category>usability</category>
        
        <category>user experience</category>
        
        <category>availability</category>
        
        
      </item>
    
      <item>
        <title>Why and How adapt your App for the Web?</title>
        <description>&lt;p&gt;At FoxInCloud we see the Web as just another User Interface (UI) device. And no one should ever need to rewrite an application for another UI device, not even rewrite the UI, just do whatever provides a similar UI on the new device.&lt;/p&gt;

&lt;p&gt;From this stand point, a desktop Application only needs be adapted to: (1) display the UI inside a browser and (2) run on a Web server.&lt;/p&gt;

&lt;p&gt;This post discusses the &lt;strong&gt;3 areas&lt;/strong&gt; where code needs adaptation, and how &lt;a href=&quot;http://foxincloud.com/download.php&quot;&gt;FoxInCloud Adaptation Assistant (FAA)&lt;/a&gt; and &lt;a href=&quot;http://foxincloud.com/download.php#trialForm&quot;&gt;FoxInCloud Application Server (FAS)&lt;/a&gt; handle them.&lt;/p&gt;

&lt;p&gt;It provides a broad view on why and how adaptations are needed, and will hopefully ring a bell when you later meet such a situation while developing.&lt;/p&gt;

&lt;hr /&gt;

&lt;h1 id=&quot;a---map-vfp-and-browser-event-models&quot;&gt;A - Map VFP and Browser event models&lt;/h1&gt;

&lt;p&gt;The event models implemented in VFP and Browsers (&lt;a href=&quot;https://www.w3.org/TR/DOM-Level-2-Events/events.html&quot;&gt;HTML DOM events&lt;/a&gt; to be precise) are mostly similar, though with some slight differences such as:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;VFP events that &lt;strong&gt;don’t exist in HTML&lt;/strong&gt;: eg. &lt;code&gt;.Validate()&lt;/code&gt;, &lt;code&gt;.When()&lt;/code&gt;, &lt;code&gt;.DropDown()&lt;/code&gt;, …&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;HTML events bubble&lt;/strong&gt;, VFP events don’t: by default in HTML, an event occurred in a contained element also triggers on all parent containers up to the document (equivalent for the form);&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Fast events&lt;/strong&gt; such as &lt;code&gt;.MouseOver()&lt;/code&gt; and &lt;code&gt;.InteractiveChange()&lt;/code&gt; can’t be timely processed on the server and require some browser-based code instead.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;how-foxincloud-handles-events&quot;&gt;How FoxInCloud handles Events&lt;/h3&gt;

&lt;h5 id=&quot;1--choose-who-processes-the-event-browser-server-or-both&quot;&gt;1- Choose who processes the event: Browser, Server, or both&lt;/h5&gt;

&lt;p&gt;When running FAA step 2, after replacing native classes (such as &lt;code&gt;Textbox&lt;/code&gt;, &lt;code&gt;Combobox&lt;/code&gt;, etc.) by classes derived from FoxInCloud (such as &lt;code&gt;xxxTxt&lt;/code&gt;, &lt;code&gt;xxxCbo&lt;/code&gt;, etc.) FAA adds at the beginning of each Event Method:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-vfp&quot; data-lang=&quot;vfp&quot;&gt;IF (TYPE(&amp;#39;m.thisForm.wlHTMLgen&amp;#39;) == &amp;#39;L&amp;#39; AND m.thisForm.wlHTMLgen)
  RETURN &amp;lt;value&amp;gt;
ENDIF&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;First time it needs a Form, FAS:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;sets &lt;code&gt;m.thisForm.wlHTMLgen = .T.&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;runs &lt;strong&gt;each&lt;/strong&gt; event methods in &lt;strong&gt;all&lt;/strong&gt; member objects of the form&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;decides what to do based on the &lt;code&gt;&amp;lt;value&amp;gt;&lt;/code&gt; returned by the &lt;code&gt;RETURN &amp;lt;value&amp;gt;&lt;/code&gt; instruction above:&lt;/p&gt;

    &lt;ul&gt;
      &lt;li&gt;&lt;code&gt;.T.&lt;/code&gt;: (default) run VFP event code on server&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;.F.&lt;/code&gt;: ignore event &lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;string&lt;/code&gt;: assume JavaScript to be run on the browser&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If necessary, &lt;code&gt;thisForm.wcScriptClientServer()&lt;/code&gt; and &lt;code&gt;thisForm.wcScriptServerClient()&lt;/code&gt; makes the event be processed by the browser &lt;strong&gt;and&lt;/strong&gt; the server in either order.&lt;/p&gt;

&lt;p&gt;» &lt;a href=&quot;http://foxincloud.com/tutotest/bs/Modal.tuto&quot;&gt;FoxInCloud Live Tutorial Sample&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://foxincloud.com/tutotest/bs/Modal.tuto&quot;&gt;&lt;img src=&quot;/blog/image/FLT-bs-modal.png&quot; alt=&quot;FoxInCloud Live Tutorial Sample: modal form&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5 id=&quot;2--handle-event&quot;&gt;2- Handle event&lt;/h5&gt;

&lt;p&gt;Based on the above value, FAS creates a JavaScript event handler invoking &lt;code&gt;FoxInCloud.js&lt;/code&gt;, a standard JavaScript module that any FoxInCloud Web page loads by default.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;FoxInCloud.js&lt;/code&gt; collects whatever value from the form controls, processes the event, takes care of cancelling &lt;code&gt;bubbling&lt;/code&gt; and/or default behavior such as context menu on &lt;code&gt;.RightClick()&lt;/code&gt; and, if required, sends event to server using &lt;code&gt;AJAX&lt;/code&gt;, for processing by the VFP app.&lt;/p&gt;

&lt;p&gt;» &lt;a href=&quot;http://foxincloud.com/tutotest/bs/Event.tuto&quot;&gt;FoxInCloud Live Tutorial Sample&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://foxincloud.com/tutotest/bs/event.tuto&quot;&gt;&lt;img src=&quot;/blog/image/FLT-bs-event.png&quot; alt=&quot;FoxInCloud Live Tutorial Sample: events form&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h1 id=&quot;b---replace-local-peripherals-by-the-browser&quot;&gt;B - Replace local peripherals by the Browser&lt;/h1&gt;

&lt;p&gt;When running on the desktop, an app can directly address peripherals on the user’s machine: screen, printer(s), storage, etc.; when running on a server, app can only address the server’s resources, and reach the client’s machine through a protocol named ‘HTTP’, acronym for ‘HyperText Transfer Protocol’.&lt;/p&gt;

&lt;p&gt;As its name says, ‘HTTP’ can only transfer text, without any ability to ‘discuss’ with user’s screen, printer or storage directly.&lt;/p&gt;

&lt;p&gt;Furthermore, the server can only &lt;strong&gt;respond&lt;/strong&gt; to an HTTP request from the browser, in other words it can’t initiate a message to the browser &lt;sup id=&quot;fnref:2&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;As a consequence, every piece of code where your application delivers a result to the user – either on display, printer of file – must be replaced by an equivalent mechanism going through the Browser.&lt;/p&gt;

&lt;h3 id=&quot;how-foxincloud-handles-peripherals&quot;&gt;How FoxInCloud Handles Peripherals&lt;/h3&gt;

&lt;p&gt;With FAA replacing the native classes by classes derived from FoxInCloud’s &lt;code&gt;aw.vcx&lt;/code&gt; ‘base classes’, FoxInCloud exposes classes, methods and procedures that replace the VFP native command and functions addressing the peripherals. These methods and functions run different code whether the app. is in &lt;code&gt;desktop mode&lt;/code&gt; or &lt;code&gt;web mode&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;desktop mode&lt;/strong&gt;: execute regular VFP code&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;web mode&lt;/strong&gt;: execute browser aware code&lt;/li&gt;
&lt;/ul&gt;

&lt;h5 id=&quot;1--display&quot;&gt;1- Display&lt;/h5&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;DO FORM ...&lt;/code&gt; → &lt;code&gt;[thisForm.]wForm()&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;MessageBox()&lt;/code&gt; → &lt;code&gt;[thisForm.]wMessageBox()&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;FAA replaces these instructions automatically.&lt;/p&gt;

&lt;p&gt;» &lt;a href=&quot;http://foxincloud.com/tutotest/bs/Modal.tuto&quot;&gt;FoxInCloud Live Tutorial Sample&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://foxincloud.com/tutotest/bs/Modal.tuto&quot;&gt;&lt;img src=&quot;/blog/image/FLT-bs-modal.png&quot; alt=&quot;FoxInCloud Live Tutorial Sample: modal form&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5 id=&quot;2--file&quot;&gt;2- File&lt;/h5&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;PutFile()&lt;/code&gt; → &lt;code&gt;thisForm.wFileSaveAs()&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code&gt;GetFile() | GetPict()&lt;/code&gt; → &lt;code&gt;xxxImgGetFile | xxxImgGetPict&lt;/code&gt; class&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;» &lt;a href=&quot;http://foxincloud.com/tutotest/bs/imgUpload.tuto&quot;&gt;FoxInCloud Live Tutorial Sample&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://foxincloud.com/tutotest/bs/imgUpload.tuto&quot;&gt;&lt;img src=&quot;/blog/image/FLT-bs-imgUpload.png&quot; alt=&quot;FoxInCloud Live Tutorial Sample: file upload form&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5 id=&quot;3--printer&quot;&gt;3- Printer&lt;/h5&gt;

&lt;p&gt;Printing requires generating a PDF report and send it to the browser using &lt;code&gt;wFileSaveAs()&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;As code depends on the PDF generator you prefer (eg. XFRX, FoxyPreviewer, FRX2Any, etc.), this adaptation is manual for now &lt;sup id=&quot;fnref:3&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;» &lt;a href=&quot;http://foxincloud.com/tutotest/bs/report.tuto&quot;&gt;FoxInCloud Live Tutorial Sample&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://foxincloud.com/tutotest/bs/report.tuto&quot;&gt;&lt;img src=&quot;/blog/image/FLT-bs-report.png&quot; alt=&quot;FoxInCloud Live Tutorial Sample: reporting form&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h1 id=&quot;c---address-multiple-users&quot;&gt;C - Address multiple users&lt;/h1&gt;

&lt;p&gt;When running on the desktop, an Application addresses one single user at a time; when running on a server conversely, the same application can address any user having the Web Application’s URL.&lt;/p&gt;

&lt;p&gt;Because the Web the application is shared by a number of users, it must ensure that serving a user does not affect the other users:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;never stops or hangs&lt;/li&gt;
  &lt;li&gt;cleans up the place after each user action&lt;/li&gt;
&lt;/ul&gt;

&lt;h5 id=&quot;1--split-questions-and-answers-into-separate-processes&quot;&gt;1- Split Questions and Answers into separate processes&lt;/h5&gt;

&lt;p&gt;One easy way to hang an application is waiting for an answer from the user:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-vfp&quot; data-lang=&quot;vfp&quot;&gt;procedure Click
...
IF MessageBox(&amp;quot;Question&amp;quot;, 4) = 6 &amp;amp;&amp;amp; application hangs here
  &amp;lt;process user&amp;#39;s choice&amp;gt;
ENDIF
ENDPROC&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;To avoid hanging the app. waiting for the answer – and this is the same for any Web Application – code needs be arranged as follows:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;user fires an event&lt;/li&gt;
  &lt;li&gt;server asks a question and provides to client an address where to send the answer&lt;/li&gt;
  &lt;li&gt;client sends the answer at the address specified&lt;/li&gt;
  &lt;li&gt;answer is processed by code at the address specified&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Using FoxInCloud, the above code becomes:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-vfp&quot; data-lang=&quot;vfp&quot;&gt;procedure Click
...
thisForm.MessageBox(&amp;quot;wFormCallBack&amp;quot;, &amp;quot;Question&amp;quot;, 4) &amp;amp;&amp;amp; code hangs in desktop mode only, not in Web mode
ENDPROC &amp;amp;&amp;amp; Question is the last instruction in method

procedure wFormCallBack &amp;amp;&amp;amp; Standard method provided by FoxInCloud &amp;#39;base classes&amp;#39;
LPARAMETERS tuUserChoice
IF tuUserChoice = 6
  &amp;lt;process user&amp;#39;s choice&amp;gt;
ENDIF&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;» &lt;a href=&quot;http://foxincloud.com/tutotest/bs/modal.tuto&quot;&gt;FoxInCloud Live Tutorial Sample&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Because the callback response processing code (above moved to &lt;code&gt;.wFormCallBack()&lt;/code&gt;) can have dependencies outside the original method (such as a ‘private’ variable), picking a call-back method and moving the code is a manual adaptation; FAA identifies the methods requiring your attention.&lt;/p&gt;

&lt;h5 id=&quot;2--stop-instructions-execute-in-desktop-mode-only&quot;&gt;2- Stop instructions execute in desktop mode only&lt;/h5&gt;

&lt;p&gt;Any instruction that stops application execution must be conditioned by desktop mode:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-vfp&quot; data-lang=&quot;vfp&quot;&gt;IF wlLAN() &amp;amp;&amp;amp; function provided by FoxInCloud under General Public License
  QUIT
ENDIF&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h5 id=&quot;3--save-and-restore-the-users-state&quot;&gt;3- Save and restore the user’s state&lt;/h5&gt;

&lt;p&gt;Because a user action should not be influenced by what the previous user has done, the app should be able to swap context from one user to another.&lt;/p&gt;

&lt;p&gt;FoxInCloud saves and restores the full user context automatically, provided 2 manual adaptations are performed:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;List the native properties (such as &lt;code&gt;.Visible&lt;/code&gt;, &lt;code&gt;.Enabled&lt;/code&gt;) affected by user action into a property that every object inherits from its FoxInCloud base class &lt;sup id=&quot;fnref:4&quot;&gt;&lt;a href=&quot;#fn:4&quot; class=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;:&lt;br /&gt;
&lt;code&gt;.wcPropSave = &quot;Visible, Enabled&quot;&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;Requery the parameterized views using &lt;code&gt;thisForm.wViewParmSet()&lt;/code&gt; inherited from FoxInCloud base class;&lt;br /&gt;
eg. with 3 parameters:&lt;/li&gt;
&lt;/ol&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-vfp&quot; data-lang=&quot;vfp&quot;&gt;thisForm.wViewParmSet(&amp;#39;viewAlias&amp;#39;, &amp;#39;parm1Name&amp;#39;, parm1Value)
thisForm.wViewParmSet(&amp;#39;viewAlias&amp;#39;, &amp;#39;parm2Name&amp;#39;, parm2Value)
thisForm.wViewParmSet(&amp;#39;viewAlias&amp;#39;, &amp;#39;parm3Name&amp;#39;, parm3Value, .T.)
&amp;amp;&amp;amp; adding .T. on last call runs Requery(&amp;#39;viewAlias&amp;#39;)&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;FoxInCloud handles all other user state bits automatically.&lt;/p&gt;

&lt;p&gt;» &lt;a href=&quot;http://foxincloud.com/tutotest/bs/dataUpdate.tuto&quot;&gt;FoxInCloud Live Tutorial Sample&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://foxincloud.com/tutotest/bs/dataUpdate.tuto&quot;&gt;&lt;img src=&quot;/blog/image/FLT-bs-dataUpdate.png&quot; alt=&quot;FoxInCloud Live Tutorial Sample: data updating form&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h5 id=&quot;4--setup-the-full-app-environment-at-server-startup&quot;&gt;4- Setup the full App environment at Server Startup&lt;/h5&gt;

&lt;p&gt;When running on the desktop, your application goes through predefined steps that you can easily predict: &lt;code&gt;start&lt;/code&gt;, &lt;code&gt;login&lt;/code&gt; form, &lt;code&gt;menu&lt;/code&gt;, &lt;code&gt;formA&lt;/code&gt;, &lt;code&gt;formB&lt;/code&gt; (modal), back to &lt;code&gt;formA&lt;/code&gt;, etc.&lt;/p&gt;

&lt;p&gt;Conversely, because browser and server execution are asynchronous, user actions can come in any order, especially after a server restart: some user actions can affect the &lt;code&gt;formB&lt;/code&gt; in the example above, while the calling &lt;code&gt;formA&lt;/code&gt; is not yet running.&lt;/p&gt;

&lt;p&gt;For this reason it is required that all application-wide settings like &lt;code&gt;SET PROCEDURE&lt;/code&gt;, &lt;code&gt;SET PATH&lt;/code&gt;, &lt;code&gt;PUBLIC&lt;/code&gt;, etc., are made right at server startup rather than throughout the application code.&lt;/p&gt;

&lt;p&gt;To help this adaptation, FAA &lt;code&gt;step 1&lt;/code&gt; identifies the corresponding instructions in the application code and &lt;code&gt;step 3&lt;/code&gt; builds an environment setting class &lt;code&gt;xxxSets&lt;/code&gt; where you can safely move them.&lt;/p&gt;

&lt;p&gt;The Desktop and Web versions of the Application should share this environment class:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-vfp&quot; data-lang=&quot;vfp&quot;&gt;modify command DesktopMain.prg

...
local oEnv
oEnv = newObject(&amp;#39;xxxSets&amp;#39;, &amp;#39;xxxSets.prg&amp;#39;)
...
do form mainForm
read events&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;» &lt;a href=&quot;http://foxincloud.com/tutotest/bs/fileDisplay.tuto?tutoLAN.prg&quot;&gt;FoxInCloud Live Tutorial Sample&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://foxincloud.com/tutotest/bs/fileDisplay.tuto?tutoLAN.prg&quot;&gt;&lt;img src=&quot;/blog/image/FLT-tutoLAN.prg.png&quot; alt=&quot;FoxInCloud Live Tutorial Sample: desktop main program&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-vfp&quot; data-lang=&quot;vfp&quot;&gt;modify command xxxServer.prg &amp;amp;&amp;amp; generated by FAA step 3

cAppSetsLib = &amp;#39;xxxSets.prg&amp;#39;
cAppSets = &amp;#39;xxxSets&amp;#39;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;» &lt;a href=&quot;http://foxincloud.com/tutotest/bs/fileDisplay.tuto?tutoServer.prg&quot;&gt;FoxInCloud Live Tutorial Sample&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://foxincloud.com/tutotest/bs/fileDisplay.tuto?tutoLAN.prg&quot;&gt;&lt;img src=&quot;/blog/image/FLT-tutoServer.prg.png&quot; alt=&quot;FoxInCloud Live Tutorial Sample: Web Server class&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;h1 id=&quot;pretty-simple-isnt-it&quot;&gt;Pretty simple, isn’t it?&lt;/h1&gt;

&lt;p&gt;When you take a fresh new look at what &lt;strong&gt;really&lt;/strong&gt; makes a difference between a Desktop and a Web application, you can easily isolate a handful of specific areas where an adaptation is needed, while most of the application code can run unchanged in both environments.&lt;/p&gt;

&lt;p&gt;And you soon realize that complex &lt;a href=&quot;https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller&quot;&gt;&lt;code&gt;MVC&lt;/code&gt;&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Representational_state_transfer&quot;&gt;&lt;code&gt;REST&lt;/code&gt;&lt;/a&gt; frameWorks &lt;sup id=&quot;fnref:5&quot;&gt;&lt;a href=&quot;#fn:5&quot; class=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt; that current Web Technologies tend to present as ‘mainstream’ are just another attempt to make what desktop applications have (wrongly) done for decades: maintain the user state on the browser, with code mixed up with the UI layer.&lt;/p&gt;

&lt;p&gt;Another caveat of these technologies is that most of the application code &lt;sup id=&quot;fnref:6&quot;&gt;&lt;a href=&quot;#fn:6&quot; class=&quot;footnote&quot;&gt;6&lt;/a&gt;&lt;/sup&gt; is in a readable form that anyone can download and copy.&lt;/p&gt;

&lt;p&gt;Hopefully this post has helped you understand that:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;You can have the same code running on the desktop and the Web: test new functionalities on the desktop and later deploy on the Web, get desktop developers work on the Web Application rapidly;&lt;/li&gt;
  &lt;li&gt;Reasons for code adaptations are pretty simple to understand and keep in mind, and easy to practise in later app development;&lt;/li&gt;
  &lt;li&gt;FoxInCloud keeps all the sensitive code on the server, protected from your competitors;&lt;/li&gt;
  &lt;li&gt;The Web can be simple and fun!&lt;/li&gt;
&lt;/ul&gt;

&lt;hr /&gt;

&lt;div class=&quot;footnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;Typical use case is a ‘fast event’ such as &lt;code&gt;.MouseEnter()&lt;/code&gt; or &lt;code&gt;.MouseLeave()&lt;/code&gt; that you can override using a CSS ‘pseudo-class’ such as &lt;code&gt;:hover&lt;/code&gt; &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot;&gt;
      &lt;p&gt;Even &lt;a href=&quot;https://en.wikipedia.org/wiki/WebSocket&quot;&gt;WebSockets&lt;/a&gt; (allowing full duplex communication between Browser and Server) require an initial handshake from the client browser &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot;&gt;
      &lt;p&gt;We plan to add standard functions for the most popular PDf generator: XFRX, FoxyPreviewer and FRX2Any &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:4&quot;&gt;
      &lt;p&gt;At design time or in &lt;code&gt;.Init()&lt;/code&gt;, &lt;code&gt;.Load()&lt;/code&gt; for forms &lt;a href=&quot;#fnref:4&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:5&quot;&gt;
      &lt;p&gt;&lt;strong&gt;MVC client-side FW&lt;/strong&gt;: &lt;a href=&quot;http://jquery.com/&quot;&gt;jQuery&lt;/a&gt;, &lt;a href=&quot;http://getbootstrap.com/&quot;&gt;Bootstrap&lt;/a&gt;, &lt;a href=&quot;https://angularjs.org/&quot;&gt;angularJS&lt;/a&gt;, &lt;a href=&quot;https://emberjs.com/&quot;&gt;emberJS&lt;/a&gt;, &lt;a href=&quot;https://reactjs.org/&quot;&gt;ReactJS&lt;/a&gt;, &lt;a href=&quot;https://vuejs.org/&quot;&gt;vueJS&lt;/a&gt;, etc. – &lt;strong&gt;REST server-side F/W&lt;/strong&gt;: &lt;a href=&quot;https://www.asp.net/&quot;&gt;asp.net&lt;/a&gt;, &lt;a href=&quot;http://rubyonrails.org/&quot;&gt;ruby-on-rails&lt;/a&gt;, &lt;a href=&quot;https://www.djangoproject.com/&quot;&gt;django&lt;/a&gt;, &lt;a href=&quot;https://www.telerik.com/&quot;&gt;telerik&lt;/a&gt;, &lt;a href=&quot;http://flask.pocoo.org/&quot;&gt;flask&lt;/a&gt;, &lt;a href=&quot;http://expressjs.com/&quot;&gt;expressJS&lt;/a&gt; &lt;a href=&quot;#fnref:5&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:6&quot;&gt;
      &lt;p&gt;Except the database layer &lt;a href=&quot;#fnref:6&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Tue, 17 Apr 2018 00:00:00 +0200</pubDate>
        <link>http://localhost:4000/blog/2018/04/17/why-how-adapt-your-app-for-web.html</link>
        <guid isPermaLink="true">http://localhost:4000/blog/2018/04/17/why-how-adapt-your-app-for-web.html</guid>
        
        <category>strategy</category>
        
        <category>technology</category>
        
        <category>development</category>
        
        <category>adaptation</category>
        
        
      </item>
    
      <item>
        <title>What do you need a Web App for?</title>
        <description>&lt;p&gt;Web Applications have been a hot topic since 2005 (more than 10 years ago…), when &lt;code&gt;AJAX&lt;/code&gt; was first coined in the post by Jesse James Garrett
 &lt;a href=&quot;http://adaptivepath.org/ideas/ajax-new-approach-web-applications/&quot;&gt;“Ajax: A New Approach to Web Applications”&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After many articles were written, posts blogged, questions discussed on StackOverflow, and many new tools and frameworks were launched with buzz, we haven’t seen that many Web Applications around, at least in the Business Application arena where VFP-based developers and companies have reigned for over 30 years.&lt;/p&gt;

&lt;p&gt;What’s the reason for that? Are Web Applications less efficient than Desktop Applications? Less demanded? Do they cost so much that no one has seriously invested to get a result similar to what Desktop Applications deliver?&lt;/p&gt;

&lt;p&gt;This post will discuss the pros and cons, and the future for both Desktop and Web Applications.&lt;/p&gt;

&lt;h1 id=&quot;pros-for-a-web-app&quot;&gt;Pros For a Web App&lt;/h1&gt;

&lt;h3 id=&quot;install-once-for-any-number-of-users&quot;&gt;Install once for any number of users&lt;/h3&gt;

&lt;p&gt;We put this first as it’s what companies running a Web App love best: no more installation hassle; yes installing and maintaining on a Web Server is a little more complex that a user desktop, but it’s far more simple than installing and maintaining 200 desktops!&lt;/p&gt;

&lt;p&gt;No more virus issue, no more disk crash; if you use FoxPro tables &lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, no more index or memo file crash because a power outage.&lt;/p&gt;

&lt;p&gt;No more “it works on my colleague’s computer but not on mine”.&lt;/p&gt;

&lt;p&gt;A new user comes in? Just create her/his account in the database, send her/him the URL and you’re done! A user leaves the company? Just close her/his account in the database and you’re done.&lt;/p&gt;

&lt;h3 id=&quot;reach-users-outside-the-company&quot;&gt;Reach Users outside the Company&lt;/h3&gt;

&lt;p&gt;It’s great to have suppliers and customers be able to log into your system and provide informations, download documents, pay invoices and so on. That’s a real productivity booster for your client company to get this kind of close interaction.&lt;/p&gt;

&lt;p&gt;Of course this interaction can be with human or machines: you can expose either or both an API (for machine-to-machine collaboration), or business forms eg. for customers to approve and/or pay invoices.&lt;/p&gt;

&lt;h3 id=&quot;serve-mobile-users&quot;&gt;Serve Mobile Users&lt;/h3&gt;

&lt;p&gt;Workers dealing with customers are often mobile: salesmen, inventory keepers, delivery personnel, doctors, teachers, and many other working categories need information on the field, away from their office. Because AJAX bandwidth requirements are low, a Web App can deliver the information they need anywhere using a 3G/4G connection.&lt;/p&gt;

&lt;h3 id=&quot;get-into-younger-peoples-habits&quot;&gt;Get into Younger People’s habits&lt;/h3&gt;

&lt;p&gt;Younger generations are used to do almost everything using their smartphone, from monitoring their bank account to dating… 6% of new such users enter the workforce every year, and they soon will be in a position to decide the kind of information technology they want to use.&lt;/p&gt;

&lt;h3 id=&quot;tightly-control-users-and-licenses&quot;&gt;Tightly control Users and Licenses&lt;/h3&gt;

&lt;p&gt;Many software companies struggle with protecting their source code and application from piracy using dongles, encryption, and many other methods against privacy.&lt;/p&gt;

&lt;p&gt;It’s obviously easier to protect a server than 2,000 copies of a software spread around.&lt;/p&gt;

&lt;h3 id=&quot;easily-debug-your-application&quot;&gt;Easily debug your application&lt;/h3&gt;

&lt;p&gt;Remember the headache remoting into a user’s machine, trying to understand why your application worked everywhere except on this very workstation, dumping memories, creating ad-hoc logs?&lt;br /&gt;
Do you remember the time it took to get the boss’ application work fine and get paid?&lt;/p&gt;

&lt;p&gt;With a Web Application you have full control: you can have any kind of log, anywhere, at any time, and update the application within minutes to add such additional precious debugging information… day and night, regardless whether users are connected or not.&lt;/p&gt;

&lt;h3 id=&quot;join-prospective-customers-anywhere&quot;&gt;Join prospective Customers anywhere&lt;/h3&gt;

&lt;p&gt;How do you reach the prospective customers for your application? And when you’ve reached one, how can he test your application? Do you have a demo version that can be downloaded? Are you sure this demo app will install correctly? Or do you visit him to make the demo and explain the benefits of your program? What if the prospective customer is 5,000 miles away?&lt;br /&gt;
What if the customer uses another platform, or has put ‘mobile’ on his selection check list?&lt;/p&gt;

&lt;p&gt;A Web App jumps over all these fences.&lt;/p&gt;

&lt;h1 id=&quot;cons&quot;&gt;Cons&lt;/h1&gt;

&lt;h3 id=&quot;development-cost&quot;&gt;Development Cost&lt;/h3&gt;

&lt;p&gt;One day you decide you’ll start developing a Web Application: you send your top devs to a conference, select a dev. environment, some frameworks, send your team to a training, build a mock-up as proof-of-concept, and start estimating the cost for the whole system.&lt;br /&gt;
Then come the trade-offs: you realize that some functionalities will either not be useful, or will cost too much to develop for the Web.&lt;/p&gt;

&lt;p&gt;When you decide to kick off, 2 years after the initial research, you read an article or a post somewhere saying that the framework X that you’d chosen initially is no longer hype: everyone now rushes on framework Y that is developed and supported by a larger company and a larger user community… back to square 1…&lt;/p&gt;

&lt;p&gt;It’s a known story: Web Technologies is an area where obsolescence beats any other industry: despite they’re based on standards, tools like JavaScript frameworks have a life expectancy of several years, and it’s quite common that their development effort stops after a couple of years just because the volunteer contributors have rushed away to a more recent project that gives more momentum to their carrier and speaking experience.&lt;/p&gt;

&lt;h3 id=&quot;response-time&quot;&gt;Response time&lt;/h3&gt;

&lt;p&gt;Web Applications require a request going through the wire, somehow restore the user’s context, execute the user request, deliver a response that goes back to the user through the wire.&lt;/p&gt;

&lt;p&gt;Even if a server is generally faster than an average user workstation, the overhead for request and response transport and for user state maintenance makes response time obviously slower than on the desktop.&lt;/p&gt;

&lt;h1 id=&quot;how-foxincloud-can-help&quot;&gt;How FoxInCloud can Help&lt;/h1&gt;

&lt;h2 id=&quot;value-your-experience&quot;&gt;Value your experience&lt;/h2&gt;

&lt;p&gt;FoxInCloud adapts your desktop application to the Web: you can deploy the same – adapted – code either as a ‘classic’ Desktop Application or a Web Application:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;FoxInCloud supports 99% of the features you have in your Desktop Application&lt;/li&gt;
  &lt;li&gt;You don’t need to ‘rethink’ your application to suit the Web and/or limit your functional scope to keep your budget under control&lt;/li&gt;
  &lt;li&gt;Your same development team can maintain both the Desktop App. and the Web App.&lt;/li&gt;
  &lt;li&gt;FoxInCloud sorts out the technologies for you, and supports the cost for keeping pace with the perpetual changes&lt;/li&gt;
  &lt;li&gt;You can sell the Web App. as a natural extension to the existing Desktop App, a much easier sell than a brand new app.&lt;/li&gt;
  &lt;li&gt;No one can tell what technology runs on the server: whether it’s &lt;code&gt;php&lt;/code&gt;, &lt;code&gt;asp.net&lt;/code&gt; or &lt;code&gt;VFP&lt;/code&gt;, the user experience will not change at all&lt;/li&gt;
  &lt;li&gt;You end up developing Web features without the hassle of going through the whole Web Tech stack.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You adapt less than 2% of your source code to make your application Web-aware; and these adaptations are not rewrite, just moving code, adding parameters, and/or calling different methods.&lt;/p&gt;

&lt;p&gt;You can adapt your application progressively, by functional block, rather than everything at once.&lt;/p&gt;

&lt;h2 id=&quot;control-response-time&quot;&gt;Control response time&lt;/h2&gt;

&lt;p&gt;As we’ve developed on VFP for 30 years, just like you, we are able to monitor anything that can possibly be monitored in your application (settings, data sessions, aliases, and much more), and in FoxInCloud itself; you have a complete view on the response time and which actions you can take to provide a smoother experience to your users&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://foxincloud.com/tutotest/bs/foxincloud-status.tuto?tab=FORMS&quot;&gt;&lt;img src=&quot;/blog/image/FWAD-app-form.png&quot; alt=&quot;FoxInCloud Web Application Dashboard: Monitoring Forms&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;take-full-advantage-of-web-technologies&quot;&gt;Take full advantage of Web Technologies&lt;/h2&gt;

&lt;p&gt;FoxInCloud builds full breed, not second range Web Applications: your VFP Web App. with FoxInCloud fully compares to, and often beat the best Web App around: functional coverage, response time, number of objects and events.&lt;/p&gt;

&lt;p&gt;You can even improve the HTML that FoxInCloud generates for you to please your users even more.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://foxincloud.com/tutotest/bs/Event.tuto&quot;&gt;&lt;img src=&quot;/blog/image/patient-lg.png&quot; alt=&quot;FoxInCloud Web Application: a Bootstrap Responsive Form&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;control-license-and-application-usage&quot;&gt;Control license and application usage&lt;/h2&gt;

&lt;p&gt;FoxInCloud provides a Dashboard (&lt;a href=&quot;http://foxincloud.com/tutotest/bs/foxincloud-status.tuto&quot;&gt;sample here&lt;/a&gt;) where you can see how many and which users your Application has had, for any period of time; you can be notified if the users count exceeds the number licensed, and take appropriate commercial action in a smooth manner with your clients.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://foxincloud.com/tutotest/bs/foxincloud-status.tuto?tab=CAShistory&quot;&gt;&lt;img src=&quot;/blog/image/FWAD-CAShistory.png&quot; alt=&quot;FoxInCloud Web Application Dashboard: Monitoring Concurrently Active Users&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;hr /&gt;

&lt;div class=&quot;footnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;a perfect fit for FoxInCloud by the way &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Fri, 30 Mar 2018 00:00:00 +0200</pubDate>
        <link>http://localhost:4000/blog/2018/03/30/what-do-you-need-a-wab-app-for.html</link>
        <guid isPermaLink="true">http://localhost:4000/blog/2018/03/30/what-do-you-need-a-wab-app-for.html</guid>
        
        <category>strategy</category>
        
        <category>installation</category>
        
        <category>user experience</category>
        
        
      </item>
    
      <item>
        <title>Challenges of developing a Web Application</title>
        <description>&lt;p&gt;When seeing the many attractive frameworks that have flourished on the web since 2005 &lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;, one could think that developing a Web Application is just a game of assembling components that you can pick here and there for free.&lt;/p&gt;

&lt;p&gt;The reality is very different: as of today (2018), and despite 2 decades of continuous efforts to make it more simple (from antique asp to ‘modern’ frameworks) web development still has not found a paradigm where any regular developer can become a ‘full stack’ web developer within a couple of years.&lt;/p&gt;

&lt;p&gt;Two main reasons for that:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;the client-server nature of the HTTP protocol&lt;/strong&gt;: with a desktop program, each user runs his/her private instance that is totally at his/her service; on the web conversely, a server can deal with any/many users, and a given user can deal with several servers; a shift from a simple 1-to-1 relation to many-to-many.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;the many standards&lt;/strong&gt;: after almost 20 years of a fierce battle between Microsoft willing to impose “his standards” through a quasi-monopoly of Internet Explorer as a browser, and the web designer community backed by Mozilla Firefox (heir of Netscape, only serious concurrent browser in the early 2000), the standards have finally won the battle.&lt;br /&gt;
Nice outcome having a little drawback: each component (&lt;code&gt;HTML&lt;/code&gt;, &lt;code&gt;CSS&lt;/code&gt;, &lt;code&gt;JavaScript&lt;/code&gt;) is maintained by a standard organization (&lt;code&gt;W3C&lt;/code&gt;, &lt;code&gt;ECMA&lt;/code&gt;), and developed by ‘volunteer’ third parties (thousands of contributors in discussion lists). Documentation depends on the goodwill of these parties: blog posts, discussions on &lt;a href=&quot;https://stackoverflow.com/&quot;&gt;stackoverflow&lt;/a&gt;, &lt;a href=&quot;https://caniuse.com/&quot;&gt;utility sites&lt;/a&gt; from service companies have replaced the good old documentation that developers used to have 20 years ago: maintained by a single source, consistent, accurate, etc.&lt;br /&gt;
Ironically, efforts from opponents to a world regulated by a de-facto monopoly have led us to a completely de-regulated world where free stuff is often a troyan horse to sell more services than what licenses used to cost.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Whatever language or framework you choose, you’ll meet 2 serious obstacles down the road to a Web Application:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Write responsive HTML/CSS/JS&lt;/strong&gt;: if you want to somehow clone the layout of the forms of your VFP desktop application, and render it as responsive HTML using - eg. - the Bootstrap framework, it’ll take you up to 10 levels of nested divs to get a proper layout; no GUI editor at the rescue for that: you’ll have to hard code using a text editor, and choose appropriate class and IDs without getting messed up; and it soon becomes very complex and difficult to handle, especially because CSS computes the layout for you based on the structure and rules you define. If you want a responsive layout, you can no longer set .left, .width, etc., you must let the browser compute positions and dimensions. Generating HTML is the area where your server code will mostly be used and, strangely, this is only the emerged part of the iceberg as point 2. below explains.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Maintain user state&lt;/strong&gt;: in your VFP code, each time you write &lt;code&gt;thisForm.…&lt;/code&gt; or &lt;code&gt;this.…&lt;/code&gt; or &lt;code&gt;alias.field&lt;/code&gt;, or read a &lt;code&gt;public&lt;/code&gt; variable, you query (without knowing or realizing it) the user state, as it results from the succession of user actions applied to an initial state. In VFP, as a single instance of the application serves a single user, everything can persist in memory: easy and painless. On the Web conversely, as the same application can serve any user in any sequence, the user state can exist only if you somehow maintain it (save and restore). No framework, whether it’s Python-based or C#-based, will ever do that for you. Then you have roughly 2 options to maintain the user state: &lt;strong&gt;on the client&lt;/strong&gt; or &lt;strong&gt;on the server&lt;/strong&gt;.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Maintaining the user state on the &lt;strong&gt;client&lt;/strong&gt; requires to:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;write a lot of JavaScript&lt;/strong&gt;, probably with some client-side framework such as jQuery, Angular or Ember (be aware that these frameworks are pretty conceptual and difficult to master properly; they at least require that you are very proficient in HTML/CSS/JS as they add several layers above these technologies). Whatever your choice, you write no Python, php or C# here, just HTML, CSS and JS.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;use client side storage&lt;/strong&gt; to create on the client something similar to a view that you’ll submit to the server once user decides to save. This requires a good knowledge of web storage API, another JavaScript-centric technology&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;expose all your business and presentation layer code&lt;/strong&gt; to the outside world; just like you would expose all the VFP code you have in *.scx and *.vcx, except queries. You can only obfuscate this code (eg. minify renames variables in alpha sequence such as “a”, “b”, “c”, “d”, etc.), concealing it is impossible as the browser &lt;strong&gt;must&lt;/strong&gt; be able to read it.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the solution that most developers use nowadays; exchange with the server are merely data conveyed in the JSON format.&lt;/p&gt;

&lt;p&gt;Maintaining the user state on the &lt;strong&gt;server&lt;/strong&gt; requires to:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;write double code&lt;/strong&gt;: client side code altering the user interface is almost the same, except it must query the user state from the server to take proper action; the amount of code is much higher, and client and server must somehow understand each other, this generally requires either being a ‘full stack developer’ or defining tight rules (eg. naming) between client and server.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;store user state on a server disk&lt;/strong&gt; so that any web server can retrieve the state for any user at any time (forget about assigning server instances to specific users like in the desktop world, it just does not work for high user counts; a typical web app serves 200 users and this figure can go up to several thousands)&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;choose or define a format to store user state&lt;/strong&gt;: could be a simple JSON string that the client JavaScript provides after each action (then you need to choose a scalable structure), or a table that you can easily query to, eg., find differences between states before / after user action.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;FoxInCloud helps you dramatically in these 2 critical areas:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;generates responsive HTML/CSS/JS code&lt;/strong&gt; from your VFP forms: FoxInCloud understand how controls are aligned and grouped on the page and builds the corresponding groupings (row, column, *-group) in the &lt;a href=&quot;http://getbootstrap.com/&quot;&gt;Bootstrap CSS system&lt;/a&gt;: eg. the &lt;a href=&quot;http://foxincloud.com/tutotest/bs/&quot;&gt;FoxInCloud Live Tutorial&lt;/a&gt;&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;maintains user state automatically&lt;/strong&gt;: as FoxInCloud runs your VFP forms on the server and these forms are object oriented, FoxInCloud is able to detect what the user actions change on the form and save these changes in a structured way; the same for the dataSession &lt;sup id=&quot;fnref:2&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; and the general environment &lt;sup id=&quot;fnref:3&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;. FoxInCloud maintains the user state on server side, in tables using a naming convention (&lt;code&gt;user\form\_[ante/post].dbf&lt;/code&gt;). The only thing you need to do is: declare the native properties (eg. &lt;code&gt;visible&lt;/code&gt;, &lt;code&gt;enabled&lt;/code&gt;) that the user action can affect (custom properties are saved by default); FoxInCloud compares the state before and after user action to identify the visual changes that the browser must apply: you have strictly nothing to code to make this happen.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As we already often wrote, FoxInCloud can be regarded either as a final, or just an intermediary step to a Web Application; you can:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;take advantage of the generated HTML/CSS/JS to save months of writing responsive HTML&lt;/li&gt;
  &lt;li&gt;judge whether the user state maintenance mechanism suits you and eventually recode a similar mechanism in Python, C# or other&lt;/li&gt;
  &lt;li&gt;mitigate between a server-side and client-side user state maintenance to save response time while protecting the code that you consider critical.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;At FoxInCloud we would be delighted if VFP developers would consider FoxInCloud as a community-inspired effort, and would like to cooperate towards a future suitable migration path to the Web, rather than like a “take or leave” product with the VFP stigmata.&lt;/p&gt;

&lt;p&gt;FoxInCloud does incorporate thorough software engineering thinking about running a Web Application while taking advantage of a Desktop Application background, going far beyond and above the mere language level which, in any case, does not and will never provide a complete solution to building a Web Application.&lt;/p&gt;

&lt;hr /&gt;

&lt;div class=&quot;footnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;&lt;strong&gt;client-side&lt;/strong&gt;: &lt;a href=&quot;http://jquery.com/&quot;&gt;jQuery&lt;/a&gt;, &lt;a href=&quot;http://getbootstrap.com/&quot;&gt;Bootstrap&lt;/a&gt;, &lt;a href=&quot;https://angularjs.org/&quot;&gt;angularJS&lt;/a&gt;, &lt;a href=&quot;https://emberjs.com/&quot;&gt;emberJS&lt;/a&gt;, &lt;a href=&quot;https://reactjs.org/&quot;&gt;ReactJS&lt;/a&gt;, &lt;a href=&quot;https://vuejs.org/&quot;&gt;vueJS&lt;/a&gt;, etc. – &lt;strong&gt;server-side&lt;/strong&gt;: &lt;a href=&quot;https://www.asp.net/&quot;&gt;asp.net&lt;/a&gt;, &lt;a href=&quot;http://rubyonrails.org/&quot;&gt;ruby-on-rails&lt;/a&gt;, &lt;a href=&quot;https://www.djangoproject.com/&quot;&gt;django&lt;/a&gt;, &lt;a href=&quot;https://www.telerik.com/&quot;&gt;telerik&lt;/a&gt;, &lt;a href=&quot;http://flask.pocoo.org/&quot;&gt;flask&lt;/a&gt;, &lt;a href=&quot;http://expressjs.com/&quot;&gt;expressJS&lt;/a&gt; &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot;&gt;
      &lt;p&gt;views and parameters, cursor and contents, table/alias states, cursorAdapters, etc. &lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot;&gt;
      &lt;p&gt;public variables, _Screen and _VFP custom properties, aliases in the default datasession, _sysmenu, etc. &lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Sun, 18 Mar 2018 00:00:00 +0200</pubDate>
        <link>http://localhost:4000/blog/2018/03/18/challenges-of-developing-a-web-application.html</link>
        <guid isPermaLink="true">http://localhost:4000/blog/2018/03/18/challenges-of-developing-a-web-application.html</guid>
        
        <category>architecture</category>
        
        <category>strategy</category>
        
        <category>productivity</category>
        
        
      </item>
    
      <item>
        <title>FoxInCloud adapts your Web App to any screen size.</title>
        <description>&lt;h1 id=&quot;classic-or-bootstrap-your-foxincloud-web-app-is-responsive&quot;&gt;Classic or Bootstrap, your FoxInCloud Web App. IS responsive&lt;/h1&gt;

&lt;p&gt;FoxInCloud offers you 2 HTML rendering: &lt;strong&gt;Classic&lt;/strong&gt; or &lt;strong&gt;Bootstrap&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Classic&lt;/strong&gt; rendering uses absolute positioning like VFP: each element has a fixed &lt;code&gt;.Left&lt;/code&gt;, &lt;code&gt;.Top&lt;/code&gt;, &lt;code&gt;.Width&lt;/code&gt; and &lt;code&gt;.Height&lt;/code&gt;, the HTML form looks and feels very close to your VFP application.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Bootstrap&lt;/strong&gt; rendering generates HTML that automatically adjust to the screen’s area by taking advantage of the Bootstrap framework: controls are distributed within columns that flow on large screens, stack on smaller screens.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In &lt;strong&gt;Classic&lt;/strong&gt; mode, if the form members have their &lt;code&gt;.Anchor&lt;/code&gt; property set, FoxInCloud automatically implements the &lt;code&gt;form.resize()&lt;/code&gt; event on the client side. When the form or the browser is resized, the server &lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; recursively calculates the new size and position of each control (based on &lt;code&gt;.Anchor&lt;/code&gt;), and sends the corresponding resize and move orders to the browser. Browser animates the changes for user’s comfort.&lt;/p&gt;

&lt;p&gt;In &lt;strong&gt;Bootstrap&lt;/strong&gt; mode, the generated HTML and CSS is responsible by design, regardless of the .Anchor property; however some CSS might be needed to enhance the default rendering.&lt;/p&gt;

&lt;p&gt;In short, you can get a responsive Web App just by implementing the &lt;code&gt;.Anchor&lt;/code&gt; property on your form control, which you can very easily test in desktop mode as it works exactly the same in both modes. The Bootstrap mode provides, on top of responsiveness, a more modern look to your application, that you can easily extend using CSS.&lt;/p&gt;

&lt;p&gt;This video shows this feature in action:&lt;/p&gt;

&lt;iframe width=&quot;740&quot; height=&quot;415&quot; src=&quot;https://www.youtube.com/embed/odbJtO9C2go&quot; frameborder=&quot;0&quot; allow=&quot;autoplay; encrypted-media&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;hr /&gt;

&lt;div class=&quot;footnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;we plan to implement the same logic on the client side (in JavaScript); this will avoid the slight response time after resizing the form, especially for users with a slow connection. &lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;
</description>
        <pubDate>Tue, 20 Feb 2018 00:00:00 +0200</pubDate>
        <link>http://localhost:4000/blog/2018/02/20/resize-form-to-screen-size.html</link>
        <guid isPermaLink="true">http://localhost:4000/blog/2018/02/20/resize-form-to-screen-size.html</guid>
        
        <category>usability</category>
        
        <category>user experience</category>
        
        <category>responsive</category>
        
        
      </item>
    
  </channel>
</rss>
