Release Notes for Alpha Anywhere (Alpha Five Version 12)

This document describes the updates and fixes made to Alpha Anywhere since its initial release.

To see the 'What's New in V12' document (which describes all of the new features in Alpha Anywhere's initial release) please click here.

 

Please note that Alpha Anywhere patches are only available to users with a current subscription.
 

You can verify your subscription status from within Alpha Anywhere by going to Help, About, or by clicking this link shown here (https://activation.alphasoftware.com/subscriptionStatus.aspx). If you install an update for which your subscription is not entitled, you will need to uninstall the update and rollback to an older version that you are authorized to use in order to continue using Alpha Anywhere.
 

The 'Pre-Release' Build

In addition to the official updates that Alpha Software makes available from time to time (which are described in this document), we also make available our internal pre-release builds that allow you to see what features have been added and what bugs have been fixed since the last official update. The features and bug fixes in the pre-release build will be part of the next official update. To see the pre-release notes, please click here.

 

Alpha Anywhere V4.3.1  -Build 3962-4772 14-Nov-2016

KNOWN ISSUES: If you have a UX component that has been set to 'pre-rendered', and the UX has arguments, and the UX has an onDialogInitialize event which sets control values, and emits Javascript, the control values will not be set and the Javascript will not be executed. A hot fix is available for this issue. Download the hotfix and apply it using these instructions.

 

 

Videos

UX Component - Ink Control Image Annotation using the Ink Control in a Data Bound UX Component The ink control allows you to create sketches by 'drawing' with your mouse, any type of pointing device, or with your finger (on a device that supports touch). A common use of the ink control is to annotate images. The image you want to annotate is shown as the background to the ink control and then you can draw 'on top of' the image. When the data are saved the ink is stored separately from the image in a long text field.

In this video we show how a data bound UX component that allows a user to upload images can be configured to allow the user to annotate the images that are uploaded.


Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3
Watch Video - Part 4

Download Component
Download SQL Table Definition

Date added: 2016-10-30
UX Component - ControlBar Control Defining Disclosure Forms using the Disclosure Form Builder In the video 'Displaying a Modal Pop-up Form using a Disclosure' we show how a modal pop-up form can be displayed using a Disclosure. The definition of the HTML for the form is fairly tedious because it is completely hand coded.

In this video we show how the Disclosure Form Builder can be used to make it easier to define the form HTML.


Watch Video - Part 1
Watch Video - Part 2

Download Component

Date added: 2016-10-30
UX Component ControlBar Control Display Modal Message Dialogs using Disclosures Modal messages (such as confirmations, progress, feedback) as commonly used when designing the user interface for an application. ControlBar disclosures make displaying these messages particularly easy.

In this video we show how the ControlBar can be configured to display three different types of message dialogs: basic information dialogs (one button), confirmation dialogs (two buttons) and wait dialogs (no buttons).

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

Download Component

Date added: 2016-10-30
UX Component - List Control Specifying Sort Criteria when Filtering a List Action Javascript allows you to easily define fields on a UX where the user can specify search criteria for a List control on the UX ( much like the Search Part in a Grid). Now you can also define sort criteria.

In this video we show how the Filter Records in a List action in Action Javascript can be configured to allow sort criteria to be specified.

Watch Video

Download Component

Date added: 2016-1-03
UX Component - ControlBar Control Adding List Navigation Buttons to a ControlBar When you define a List control, you can specify that the List should be paginated. If you set the pagination method to 'Navigation Buttons' then you must define buttons to move to the next and previous page of records. In a mobile application that uses a ControlBar in a Panel header or footer, it is desirable to place these navigation buttons in the ControlBar.

In this video we show how you can quickly add List navigation buttons to a ControlBar by selecting the 'Pre-defined buttons' option when adding ControlBar items to your ControlBar definition.

Watch Video

Date added: 2016-11-05
UX Component - FormView Control Using a FormView Control to Edit Data in a List Control - Master-Detail Forms - Very Large Forms By default, when you configure a List with a Detail View (so that edits can be made to the List data), the Detail View is composed using individual controls (e.g. Textbox, Textarea, Dropdown, etc). If the Detail View has a large number of fields, then composing the Detail View using individual controls will be inefficient and will result is a very large UX component that may not perform well.

An alternative approach is to use the FormView control to implement the List's Detail View. This is extremely efficient and will allow you to build UX components that edit very large forms but still perform very well.

In this video we show how a master-detail Form is built using a FormView control to edit the fields in the Master table and a second FormView control to edit the fields in the Detail Table. The master table has 100 fields and the detail table has 100 fields, so in total, the UX component is editing 200 fields.

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3
Watch Video - Part 4

Download Component

Download Script to Create SQL Tables

Date added: 2016-11-08
UX Component - FormView Control Tutorial - Building a Mobile Master-Detail Form using The List, FormView and ControlBar Controls - In this video tutorial we show how a mobile app can be built to implement a master-detail form using the FormView control. The app will allow users to edit data from the Customers and Orders table in the sample Northwind database. This is a classic master-detail form: Each customer has multiple orders. The UX component uses two Lists joined in a parent-child relationship. The parent List displays data from the Customer table and the child List display the related orders from the Orders table.

Each List has a Detail View, but in both cases, the Detail View is implemented using the FormView control.

Once the basic functionality of the app has been built, the app is 'mobilized' by wrapping the various sections of the component in PanelCards and a ControlBar is added to implement navigation between the various parts of the application.

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3
Watch Video - Part 4
Watch Video - Part 5
Watch Video - Part 6
Watch Video - Part 7
Watch Video - Part 8
Watch Video - Part 9
Watch Video - Part 10

Download Components

Date added: 2016-11-10

 

 

 

 

UX Component - ControlBar Control - Buttons - Bubble Help - You can now define bubble help for all button types (button, button-list, button-toggle, disclosure-button) in the ControlBar control.

PhoneGap App Builder - Passcode Check Plugin - A new plugin for iOS has been added that allows the developer to verify that a passcode has been set on an iOS device. This an important security consideration if you are planning to store data on the device. If a passcode has been set on an iOS device, then the contents of the device are encrypted when the device is locked.

When the plugin is installed, a JavaScript PasscodeCheck object is automatically created after the PhoneGap ready event fires. You do not need to create this object. To use the plugin, call the isDevicePasscodeSet function.


PasscodeCheck.isDevicePasscodeSet(successCallback, failureCallback);


The successCallback and the failureCallback functions are required.

Success callback (called if device passcode is set with value of true)
Failure callback (called if the passcode is not set, with a value of false or on error or if the device does not support the LocalAuthentication framework)


Example:
 


PasscodeCheck.isDevicePasscodeSet(function() {
        alert('Passcode is set);
    },
    function() {
        alert('Passcode not set);
    }
);

 

PhoneGap App Builder - File Transfer Plugin - In early September, we detected a problem on Android devices with the latest version (as of 11/7/2016 : v1.6.0) of the File Transfer Plugin. A change was made to the PhoneGap Builder to load version 1.5.1 of the File Transfer Plugin, which is working reliably. If you have any Android apps that fail to upload media files, make sure version = "1.5.1" has been included in the project's config.xml file. If you do not feel comfortable editing the project's config.xml file, you can remove the file-transfer plugin, save the changes and then add the file transfer plugin once again and save. This will load the new plugin definition string that includes the version 1.5.1 specification. 


Action JavaScript - Stripe Checkout - Locale Property - Stripe has added support for a new locale property. The locale property is used to display the Stripe Checkout dialog in the native language of the user. The default value is auto and that will display Checkout in the users preferred language, if available. English is used by default. Supported languages include Simplified Chinese (zh), Danish (da), Dutch (nl), English (en), Finnish (fi), French (fr), German (de), Italian (it), Japanese (ja), Norwegian (no), Spanish (es) and Swedish (sv). Checkout also uses the locale to format numbers and currencies. 

PhoneGap Shell V2 - Overlay Button Position - You can now adjust the position of the overlay icon that shown when you are running a UX component in the PhoneGap shell. By default, the overlay button is shown bottom right. However, in some cases the overlay button will obscure an important part of the component you are testing and you will want to move it. To do so, click on the overlay button to show the bottom toolbar and then click the menu icon (left hand button).

 

This will show a dialog where you can adjust the overlay position.

 

UX Component - ControlBar - Pre-Defined Buttons - List Control Pagination Buttons - When you define a List control, you can specify that the List should be paginated. If you set the pagination method to 'Navigation Buttons' then you must define buttons to move to the next and previous page of records. In a mobile application that uses a ControlBar in a Panel header or footer, it is desirable to place these navigation buttons in the ControlBar.

When you add 'button' Items to a ControlBar, the Pre-Defined Buttons hyperlink opens a genie that makes it easy to add List control navigation buttons to the ControlBar.

Watch Video

 

UX Component - List Control - Action Javascript - Filter Records in a List Action - You can now specify sort criteria when using the Filter Records in a List action in Action Javascript.

Watch Video

 

UX Component - List Control - afterSelect Client-side Event - A new event has been added to the List control. The afterSelect event fires after a row in the List has been selected.

The afterSelect event is essentially the same as the onSelect event except in the case where the List has a Detail View and is the parent of a child List and the child List has been set to pre-fetch data. In this case the onSelect in the parent List will fire after the row in the parent List has been selected and the List's detail View has been populated, but before the child Lists have been populated. The afterSelect will fire after the child Lists have been populated.

 

UX Component - Client-side Events - onAjaxCallbackNotAllowed - The onAjaxCallbackNotAllowed client-side event fires if the server-side canAjaxCallback event does not allow the Ajax callback. I.e. the canAjaxCallback event sets:

e.authorized = .f.

 

UX Component - Client-side Data Cache - Deleting Items From Cache - You can now delete items from client-side data cache using the {dialog.object}.deleteFromDataCache() method.

 

Syntax:

{dialog.object}.deleteFromDataCache(itemName, onSuccessIn,onError)

 

Where

UX Component - Client-side Data Cache - Listing Files from the Cache that have been saved to disk - A new method allows you to list the files in the client-side data cache. These are the cache-items that are defined to persist to the filesystem and that have been retrieved. The syntax is:

{dialog.object}.listFileInDataCache([onSuccess [, onError]);

Where

 

UX Component - Client-side Data Cache - File Location - You can now specify where the client-side data cache files should be persisted in the file system (when running in PhoneGap).

To specify the location open the Client-side Data Cache editor and set properties on the Other Settings tab.

 

 

For backward compatibility select <default> for both the Filesystem and the Directory. This will store the files in the persistent filesystem (as specified by the PhoneGap constant LocalFileSystem.PERSISTENT). The files will be stored in a folder called __AADataCache/A5SessionFile.

If you specify an explicit Directory name or a Filesystem other than <default>, the A5SessionFile sub-folder in the target folder is not used.

The Filesystem and Directory can be dynamically set at run-time by calling a Javascript function.

For example, you could set the Directory to:

javascript:getDirectory

 

This would call a Javascript function called getDirectory. This function must return the name of the directory (with a trailing slash).

To specify an explicit location for storing the files in the client-side data cache, set the Filesystem property to the name of a Javascript function (for example javascript:getFilesystem). Your Javascript function should return the fully qualified URI of the folder where the cache files should be stored, prefixed with the string explicit: . For example:

function getFilesystem() {

    //return full path to folder with trailing /

    return 'explicit:file:///dir1/dir2/dir3/';

}

 

UX Component - ControlBar Control - Disclosure Form Builder - A new genie has been added to make building the HTML for simple Disclosure forms easier.

 

Watch Video - Part 1
Watch Video - Part 2

 

Xbasic - JWT - JSON Web Tokens - New methods have been added to create and decode JSON Web Tokens (JWT)

 

Example:

 

dim secret as c = "thisismykey"

dim token as c = extension::JSON::JWTSign(json_sanitize("{ fname : 'john' , lname : 'smith'}"),secret)
?token

= "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJmbmFtZSI6ImpvaG4iLCJsbmFtZSI6InNtaXRoIiwiaWF0IjoxNDc3ODMzMDgwfQ.RJ7vNIYtUaC5DNXiJtiQpxKYUO2TRW2U9bpFZMPypw4"

? extension::JSON::JWTVerify(token,secret)

= {"fname":"john","lname":"smith","iat":1477833068}

 

UX Component - List Controls - Events - The way in which events are handled for buttons, hyperlinks and dynamic images in a List control has been changed to use 'items' (i.e. the 'a5-item' attribute), rather than binding events to the buttons, hyperlinks and dynamic images in each row. This new method is substantially more efficient than the previous method and will result in less memory utilization and better performance. The performance differences in large lists with several buttons, hyperlinks etc. in each List row should be especially noticeable.

 

UX Component - Image Annotation using Ink Control in a Data Bound UX Component - A great use case for the Ink control is to annotate images. This is done by displaying the image you want to annotate as the background to the Ink control and then the user can 'draw' on top of the image.

New properties have been added to the UX to allow you to easily configure the Ink control to use an image as its background. The image is and the ink annotation are stored in separate fields in a database.

The image below shows an Ink control with an image as its background.

When you configure the UX you specify that it is data bound to the table that contains the images and the ink annotation. You bind the image field in the table to an image control on the UX and you bind the annotation field in the database to the Ink control on the UX. The in the Ink control's Data Binding section you specify the name of the image control to use as the ink background.

 

 

Application Server - a5w_info() Function - Changes have been made to the a5w_info() function to give additional information under IIS and the AlphaCloud. The changes are summarized below:

 

1. The System section at the bottom now includes values that tell you the operating system and version of the server.

For example:

 

Server Product                         ApplicationServerIIS
Platform                               Windows
Operating System Name                  Microsoft Windows Server 2008 R2
Operating System Version               6.1
Operating System Is Server Edition     True
 


The XBasic required to generate those values is below.


? Context.ApplicationConfiguration.ServerProduct
= “ApplicationServerClassic”

?OSPlatform()
= "Windows"

?OSName()
= "Microsoft Windows Server 2008 R2"

?OSVersion()
= "6.1"

?OSIsServerEdition()
.t.
 

 


2. The ServerSetting section is specific to the Classic edition of Alpha Anywhere Application Server. This section is no longer generated unless the value of Context.ApplicationConfiguration.ServerProduct is ApplicationServerClassic; which apples to Live Preview as well.

The full set of values available is currently:

 

 



3. There is an Alpha Cloud section that is displayed only when the server product is AlphaCloud.

This section shows the application constants generated by Alpha Cloud on deployment, including the subscription, account, application, deployment, published version and publication creation date/time and the deployment date/time..

4. On the Request section, many of the values on a5w_info() showed the names of object properties and functions rather than the values of interest.


For all servers Session.Keys was not working. It now displays the keys for session values.

For IIS (and Alpha Cloud), the following were not showing values, but object function and property names instead. These now display the keys and values in nested tables:

 

 


 

Bugs

UX Component - Javascript Error in _numberStringSanitize Function - In certain cases a UX would give Javascript error when loading. The reported error was in the _numberStringSanitize method of the UX component.

UX Component - Caching - A bug in the way the UX component was being cached was fixed. This bug could, in certain cases, lead to a server crash.

Desktop Forms - Supercontrols - Google Maps - Because of a change Google made to their Maps API, the Google Maps supercontrol will no longer work. However, the Bing or Mapquest supercontrols can be used as alternatives.

Reports - Layout Table Reports - Fixed an issue with high order characters.

Web Applications - Web References - Fixed an issue with the proxy generator.

 

Tips

Grid Component - Alpha Theme - Icons - When you use the new 'Alpha' theme in a Grid, the toolbar icons for the Detail View can be a little hard to see  in their default state (see first image).

However, you can make the icons much clearer by applying some CSS to the SVG icons used in the toolbar (see second image)

 

 

To define the necessary CSS select the Local CSS definitions property.

 

 

Specify the following CSS:

.grid .link .icon { 
    fill: #333;
    stroke: #333;
}
 

 

 

 

Alpha Anywhere V4.3  -Build 3922-4757 26-Oct-2016

VERY IMPORTANT: As of build 3898 if the regional settings on your server do not use a period as the decimal character and if the client-side number format that users will use when entering numbers does not use default settings  (period for decimals and comma for thousands separator) then you must set the new Number format - decimal character  and  Number format - thousands separator properties in each UX component. See the UX Component - Number Formats topic below for more information.

 

Summary: V4.3 is packed with new features. Perhaps the single most important new feature is the ControlBar control in the UX component. If you are building Mobile apps, the ControlBar will give you a huge productivity boost and allow for much more professional looking applications. It is an essential tool for Mobile app developers! Other new features of note include the new 'Alpha' stylesheet, new PhoneGap shell for quickly testing PhoneGap applications, Built-in SVG icons for all themes, Google address auto-complete

Videos

UX Component - FormView Control Capturing Signatures using the SignatureInk Editor A common requirement when using the FormView control is capturing a signature. Alpha Anywhere has a Signature control, but this control captures signatures as bitmaps and is not ideal for use in a FormView control. The Ink control is better suited for this use case.

In this video we show how a FormView control is configured to use the built-in SignatureInk editor.

Watch Video

Download Component
Date added: 2016-06-30
 
Node Installing a Node Module from NPM and then Creating a Node Service to Call Methods in the Node Module The Xbasic code you write in your Web applications can call methods in Node.js modules that are installed from NPM (the Node Package Manager).

In this video we show how a Node module is installed into the Web Project folder and then how a Node Service is created so that methods in the Node module can be called.

The particular Node module that we install in this video is called Tinify and we show how a Node Service is defined so that we can call into this module from Xbasic using the Node_request() function.


Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

Date added: 2016-07-06
 
UX Component - Ink Control Customizing the Ink Control Overlay The Ink control 'overlay' displays a number of tools that are used by the Ink editor (such as the Pen selector, Eraser, etc.). You can customize the appearance of the 'overlay' and add your own tools (i.e buttons).

In this video we show how you can add a new button to the Ink editor overlay.

Watch Video


Date added: 2016-07-08
UX Component - Ink Control Setting the Ink Control Background Image Setting the background image in the Ink Control is a common practice. In this video we discuss various aspects of how you can set the Ink control image background and control whether the UX goes dirty when the Ink background is set.

Watch Video - Part 1
Watch Video - Part 2


Date added: 2016-07-06
UX Component - Ink Control Using the Ink Control to Capture Signatures The UX Component has always had a built in Signature Capture control. However, it is also possible to use the Ink control to capture signatures. The primary benefit of using the Ink control to capture signatures is that the signature is captured using the Ink format, which is an ascii format, rather than as a PNG image, which the Signature Capture control uses.

In this video we show how to configure the Ink control to capture signatures.

Watch Video


Date added: 2016-07-08
UX Component - ViewBox Using a ViewBox as the List's Detail View A common pattern when building mobile applications is to use a List control with a Detail View. When the user taps on a row in the List, the Detail View shows the details for the selected row. This pattern is used extensively, especially for offline applications where the data in the List is intended to be updateable.

However, there are many cases where the List is not intended to be  updateable and a much 'lighter weight' solution can be achieved but not turning on the List's 'Has Detail View property' and instead, using a ViewBox to display details for the selected row in the List.

An even lighter weight solution can be achieved by using a ViewBox to replace the List. So you end up with a ViewBox to display a list of records and another ViewBox to display details for the selected record.

Watch Video - Part 1
Watch Video - Part 2

Download Component

Date added: 2016-07-09
UX Control Building a Custom Image Gallery using the List and Ink Control The List and Ink Control can be used to build a custom Image Gallery in which the List is used to display thumbnails of the available images and when the user taps on a particular image, the full size image is shown in the Ink control. The advantage of using the Ink control to display the image is so that you can take advantage of the Ink controls pinch-zoom features and pan features to scale the image and to pan around to see details of different parts of the image. The ability to actually draw ink (which of course is the primary purpose of the Ink control) is not used in this case.

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

Download Component

Date added: 2016-07-16
UX Component - List Control Options for Handling Write Conflicts when Syncing Data When you build a disconnected mobile application, there is always a chance that the user will get a write conflict when they sync data that was edited while they were offline. This could  happen because some other user has committed a change to a record before another user could commit their change.

By default, when a write conflict occurs, the information about the conflict is sent to the user and the user can resolve the conflict by selecting 'Their value' or 'My value'. However, there are other powerful programmatic options for handling write conflicts. In this video we discuss the various techniques for handling write conflicts.

Watch Video - Part 1
Watch Video - Part 2


Date added: 2016-07-21
Grid Component Preventing User from Closing Pop-up Window if Grid or a Linked Child Grid is Dirty It is common in web applications to have buttons that open a Grid component in a pop-up window. The Action Javascript builder when you build this action has a built-in property that allows you to prevent the user from closing the window if the Grid shown in the window is dirty. But what if the Grid shown in the window has Linked child Grid components? You might want to also check that the child Grids are not dirty before the window can be closed.

In this video we show how this can be done.

Watch Video

Date added: 2016-08-04
UX Component - FormView Control Creating Complex Form Layouts using the Flow and Column Layout Containers When you lay out a Form using the FormView control, by default, the controls on the form are rendered with one control per line and each control taking up the full width of the FormView control. If you want to create a more complex Layout you can either switch from Genie mode to the Freeform mode, or you can use Flow and Column Layout Containers to control the layout of your Form.

In this video we show how a complex Form layout is achieved using Column and Flow layout containers.

Watch Video - Part 1
Watch Video - Part 2

Download Component

Date added: 2016-08-27
UX Component Adjusting Colors and Fonts in a Stylesheet Alpha Anywhere has always allowed you to edit a stylesheet used by a component to change any of the CSS defined in the stylesheet. But when you simply want to change some colors in a stylesheet, using the style editor may be more than you need.

In this video we show how you can easily adjust colors and fonts in a style.

NOTE: This option is only available for 'new' styles (AndroidLight, AndroidDark, iOS7, Alpha) as these styles are based on SASS.

Watch Video

Date added: 2016-09-14
UX Component - ControlBar Control Introduction to Basic Concepts This video demonstrates basic concepts of the ControlBar control.

Watch Video - Part 1
Watch Video - Part 2

Date added: 2016-09-14
UX Component - ControlBar Control Updating ControlBar Data - Dynamic Text This video demonstrates how you can update the data in the ControlBar's data. This allows you to put dynamic text in the Controlbar. We also show how the ControlBar can be animated when it is refreshed.

Watch Video - Part 1
Watch Video - Part 2


Date added: 2016-09-14
UX Component - ControlBar Control Using Watch Events to Update ControlBar Data The ControlBar data can be updated automatically in response to certain events in the UX (such as the UX going dirty, a List going dirty, etc.) or by a change in the value of one or more controls.

In this video we show how you can configure watch events to automatically update ControlBar data.


Watch Video

Date added: 2016-09-14
UX Component - ControlBarControl Adding a Button to a ControlBar In this video we show how you can add a button to a ControlBar and then associate an action (i.e. some Javascript code) to run when the button is tapped.

Watch Video
Download Component

Date added: 2016-09-14
UX Component - ControlBarControl Adding a Button-Toggle to a ControlBar In this video we show how you can add a Button-Toggle to a ControlBar. Toggle buttons can either be two-state (switching between a true and a false state), or multi-state (each click advances to the next button state).

The video shows how the state of a Button-Toggle is used to control what action a button performs when clicked.

Watch Video
Download Component

Date added: 2016-09-14
UX Component - ControlBarControl Adding a Button-List to a ControlBar A common pattern in mobile apps is to have a button bar at the bottom of the screen with a series of buttons that allow you to select the active Panel that is shown on the device. Typically, these buttons are spread out so that they fill the width of the screen.
The button-list control is ideal for implementing this pattern.

In this video we show how a Button-List can be configured to fill the width of the screen and to select a Panel Card in a Panel Layout when one of the buttons in the Button-List is tapped.

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3


Download Component

Date added: 2016-09-14
UX Component - ControlBar Control Selecting the Active ControlBar Layout A ControlBar can have multiple Layouts. In this video we show how you can dynamically select the Layout to show.

Watch Video - Part 1
Watch Video - Part 2


Download Component

Date added: 2016-09-14
UX Component - ControlBar Control Showing a Disclosure A disclosure can be some explicitly defined HTML, or it can be another Layout. In this video we show how a disclosure, defined as a ControlBar layout, is shown.

Watch Video
Download Component

Addendum: One of the more unusual disclosure types is Outside-After (and Outside-Before) which display the disclosure perpendicular to the parent Layout. In this video we show how the disclosure is rendered when the Outside-After type is selected.

Watch Video - Part 2

Date added: 2016-09-14
UX Component - ControlBar Control Showing a List in a Disclosure You can display standard UX controls (such as Lists, Buttons, Input controls, etc.) in a disclosure. In this video we show how a list is displayed in a disclosure.

Watch Video - Part 1
Watch Video - Part 2


Download Component

Date added: 2016-09-16
UX Component - ControlBar Control Setting the Selected Button in a Button List using Javascript The selected button(s) in a ControlBar Button List can be set programmatically using Javascript. It is also possible to completely change the buttons shown in a Button List programmatically.

In this video we show how this is done.

Watch Video

Download Component

Date added: 2016-09-21
UX Component Google Address Auto-complete A commonly seen feature in many web and mobile applications is address auto-complete. As the user starts typing an address into a textbox, a list of suggested address is shown and the user can select from the list. This feature is powered by Google Maps.

In this video we show how you can turn on the Address Suggest feature for any textbox control on a UX.

NOTE: Textbox controls in Repeating Sections are not supported.

Watch Video - Part 1
Watch Video - Part 2


Date added: 2016-09-16
UX Component - ControlBar Control Defining Javascript in a ControlBar - Understanding the 'This Object' Option. Using Javascript function in a template. When you define Javascript functions in a ControlBar (and also a ViewBox and FormView control), you can specify where the Javascript should be stored. The options are: At the control level, at the UX level and 'This object'.

This video explains the options and discusses why the 'This object' option is best. It also describes how functions defined at the 'This object' level can be referenced in templates.


Watch Video
Download Component

Date added: 2016-09-28
UX Component - ControlBar Control Dynamically Showing and Hiding Lines in a ControlBar Layout A ControlBar layout can have multiple Lines. Each Line in a Layout can be dynamically shown or hidden.

This video shows how a show expression can be defined for a Line in a ControlBar Layout


Watch Video
Download Component

Date added: 2016-09-28
UX and Grid Component Sending SMS Messages using the Twilio Service You can send SMS messages from the Grid and the UX. The messages are sent using the Twilio service, so you will need a Twilio account. You can use Action Javascript to define the action which sends the message.

There are a large number of options for customizing the message, such as sending messages in different languages, depending on the user preference.

In this video we show how a button was defined in the UX to send a message. The phone number and message body are read from controls on the UX.

Watch Video

Date added: 2016-09-29
UX Component Creating Offline HTML5 Applications using the Application Cache The Application Cache (an HTML5 feature widely supported by various browsers) allows you to build 'offline' applications - i.e. applications that can be loaded into the browser even if there is no internet connection. In order to load the application initially an internet connection is obviously needed. But once the application has been loaded initially, all of the files (e.g. CSS.Javascript, images, etc.) referenced by the application are cached in the browser and an internet connection is not needed to load the application subsequently.

If the application is updated, then if an internet connection is available when the app is loaded, the new version of the app is downloaded and cached in the browser.

In this video we show how offline HTML5 applications can be created using the Application Cache feature.

NOTE: These 'offline' HTML5 applications do not require PhoneGap!

Watch Video - Part 1
Watch Video - Part 2

Date added: 2016-09-29
UX Component - List Control Saving and Restoring List Settings to Quickly Define New Lists The List control is one of the most commonly used controls in a UX component. But because of the richness of the List, there can be many properties that need to be set to configure a List. After you have configured a List, you can save all of the settings for the List in a named file. Then when you define your next List, you can restore the settings from the named file - saving a lot of time.

This video demonstrates how List settings can be saved and restored.

Watch Video

Date added: 2016-109-02
UX and Grid Component Using the Javascript Code Library The Javascript Code Library is available in all contexts where Javascript can be edited. The Code Library is ideal for storing snippets of code that can then be pasted into the Javascript you are editing.

In this video we walk through the various features of the Javascript Code Library.

Watch Video

Date added: 2016-109-05
UX Component - ControlBar Control Adding an Edit ControlBar Item to a ControlBar A ControlBar typically contains text and buttons, but a common use case is to build a Search ControlBar that uses an edit control in the ControlBar.

In this video we show how the edit ControlBar item type can be used to build a Search feature.


Watch Video
Download Component

Date added: 2016-10-08
UX Component - ControlBar Control Displaying a Modal Pop-up Form using a Disclosure A common pattern in many applications (both Mobile and Desktop web) is to display pop-up modal forms to collect some information from the user. Displaying pop-up modal forms using the ControlBar is very easy and extremely powerful.

This video shows how a ControlBar 'disclosure' is used to display a pop-up modal form. The 'a5-action' attribute in the Disclosure HTML is used to invoke actions defined in the ControlBar's Action pane.


Watch Video - Part 1
Watch Video - Part 2

Download Component

Date added: 2016-10-08
UX Component - FormView Control Displaying Calculated Values on a FormView Control When you design a FormView control you may want the form to display calculated values (typically computed from other fields in the form). Since the Form is really just an HTML template that is rendered using Alpha Anywhere's client-side templating features, this is easily done.

In this video we show how a calculated field is added to the FormView control.

Watch Video
Download Component

Date added: 2016-10-10
     

 

 

 

Features

UX Component - ControlBar Control - A new control type is available in the UX component. The ControlBar is primarily intended for creating the content that appears in Panel headers and footers and it is a much easier and vastly more flexible way for populating a Panel header or footer compared with the previous technique of adding standard UX controls (such as buttons and static text controls) to the header or footer.

For more information on ControlBars, please see the User Guide documentation here.

You can also refer to the API documentation here.

To see videos on the ControlBar refer to the Videos section of this document.

 

UX Component - ControlBar Control - Modal Dialogs - A new property (Auto-hide disclosure) for disclosure-buttons allows the disclosure opened by the disclosure-button to be modal. This means that the user will not be able to tap anywhere off the disclosure to close the disclosure, but must tap a button on the disclosure itself in order to close the disclosure. To make a modal disclosure:

For example, in the image shown below when the user taps the Settings button, the disclosure (a modal dialog) prompting for two input fields is shown. The user cannot close the disclosure by clicking off the disclosure. The only way to close the disclosure is by tapping the OK or Close buttons.

 

 

UX Component - ControlBar Control - Miscellaneous Improvements

When you define HTML for a Disclosure you can now use the a5-actions attribute in your HTML to bind to ControlBar Actions. For example:

<div a5-action="action1">

    Tap here to do some task

</div>

A new type of ControlBar Item is available. The Edit item allows you to display an input control in the ControlBar.

The button-disclosure ControlBar item now supports user defined events such as click, downhold, etc.

 

UX Component - ControlBar Control - Samples - When you open the ControlBar builder you can now get a quick start by loading a sample ControlBar. On the 'Home' tab in the ControlBar builder, click the Load Sample ControlBar hyperlink.

 

 

UX Component - ControlBar, ViewBox and FormView Controls - Defining Javascript - In the builder for the ControlBar, ViewBox and FormView, you can define Javascript functions.

When you define you Javascript functions, you can specify where the Javascript should be stored. The options are:

Now, a new option is available:

When you select the 'With the control' option, the Javascript is stored in the control definition, (which means that if you copy the control to another UX component, the Javascript you define comes along - this would not be the case if you use the 'With the UX' option). However, at render-time for both the 'With the control' and 'With the UX' options, the Javascript functions you define are global functions. That means that if you have a UX with multiple ControlBar, ViewBox or FormView controls, and they each define a different function called (say) 'func1' at the 'With the control' option, the definition of the global func1 function will be whatever definition exists in the last control that was rendered.

However, if you define the Javascript at the 'This object' level, then your Javascript functions become method of the ControlBar, FormView or ViewBox object and a definition in one control cannot overwrite a definition in another control.

To invoke a function defined at the 'This object' level, you must use a pointer to the object as a prefix.

For example

this.func1()

(assuming that the this object is a reference to the ControlBar, FormView or ViewBox object).

 

In cases where the this object does not reference the ControlBar, FormView or ViewBox object, you can still call the function by first getting a pointer to the ControlBar, FormView or ViewBox object. For example

var obj = {dialog.object}.getControl('myViewBox1');

obj.func1()

 

The ControlBar, FormView and ViewBox controls allow you to use client side templates. If you templates you can reference a Javascript function defined at the 'This object' level as follows:

{@[scope].func1}

 

The [scope] keyword is a reference to the object.

 

 

 

UX Component - ControlBar Control - Show/Hide Lines in a ControlBar Layout - You can now dynamically show or hide lines in a ControlBar layout.

 

Watch Video

 

To define a Show expression for a Line, click the Line Properties button on the ControlBar layout editor.

 

 

 

UX Component - PhoneGap Shell V2 - A new PhoneGap shell template is now available. When developing a PhoneGap application, a shell is a huge productivity boost because you can test new versions of the app you are developing by quickly loading the app into the shell that is running on your device. You do not have to submit your app to PhoneGap build every time you want to test a new version of your app.

The V2 shell improves on the previous PhoneGap shell that shipped with Alpha Anywhere in several key areas.

To create a new PhoneGap shell, open the UX builder and create a new UX component. Select PhoneGap-Shell-V2 from the list of templates.

Once you have created the UX component using the template, save it and submit it to PhoneGap build using the PhonGap build genie (accessed from the PhoneGap button on the Web Control Panel). Then load the shell onto your device.

 

 

Key benefits of the V2 shell include

 

 

The various screen shots shown below illustrate various of the new V2 features of the PhoneGap shell.

 

 

1. PhoneGap Shell V2 - Main Screen

 

2. PhoneGap Shell V2 - Main Screen Menu

 

 

3. PhoneGap Shell V2 - Adding a new component to the list

 

 

 

 

4. PhoneGap Shell V2 - Generating a QR code for the component name from the dropdown menu in the UX builder

 

 

 

5. PhoneGap Shell V2 - QR code type

 

 

 

6. PhoneGap Shell V2 -  Showing a running component - Back and Refresh buttons are hidden

 

7. PhoneGap Shell V2 -  Showing a running component - Back and Refresh as hidden shown after tapping on the menu icon

 

 

 

8. PhoneGap Shell V2 -  Settings screen menu

 

9. PhoneGap Shell V2 -  Adding a new server address

 

 

 

 

10. PhoneGap Shell V2 -  Generating a QR code for the server address and description to avoid having to type into the dialog prompting for server address

 

 

11. PhoneGap Shell V2 -  Testing a server address

 

 

UX and Grid Component - Javascript Library - Date Arithmetic - A new method has been added to the date object prototype. The .addTime() method is now a built-in method of the date object. This method takes two arguments:

The possible values for interval are:

Units is a number.

 

Examples:

 

//add 1 year to a date object
var d1 = new Date();
d2 = d1.addTime('year',1);

//add 1 year, 3 months, 10 days to a date value
var d1 = new Date();
d2 = d1.addTime('year',1).addTime('month',3).addTime('day',10);

 

UX Component - .getDateValue() Method - When you use the .getValue() method to retrieve the value of any control, a string is returned, regardless of the control's defined data type. In the case of numeric and logical types, casting the value to the required Javascript type is easy (using the $u.s.toNum() or $u.s.toBool() ) functions, but casting to a date value is harder because the data value has to be parsed. Therefore a new method has been added to get the value in a control as a date object.

For example:

var d = {dialog.Object}.getDateValue('dateofbirth')

 

The date string in the control is parsed into a date object using the client-side date and time format defined in the UX component.

 

 

UX Component - List Control - Server-side beforeQuery Event - This event fires before the query to retrieve the List data is executed.

The Xbasic function that handles this event gets passed the SQL statement that will be executed and the SQL arguments that will be used in he query.

Now, your Xbasic code can modify the SQL statement that the query will execute.

Previously your Xbasic could only change argument values.

 

UX Component - Action Javascript - PhoneGap - Scan Barcode - A new action in Action Javascript allows you to scan barcodes in a PhoneGap application.

The action is called PhoneGap - Scan Barcode. The builder for the action is shown in the image below.

You can define an onSuccess Javascript event handler that gets called if the scan was successful. You Javascript code can reference:

 

 

 

IMPORTANT: When you build the PhoneGap application be sure to select the Bar Code Scanner plugin in the Third Party PhoneGap Plugins section.

 

 

 

UX Component - PhoneGap - Android - onAndroidBackButton - When running in a PhoneGap shell the client-side onAndroidBackButton event will fire when the user taps on the system back button. If you do not define an event handler for this event, then when your app is running and user taps on the Android Back button, your app will exit.

If you define a handler for this event, then when the user taps on the Android Back button, the app will not exit and the code in your event handler will execute. You can typically use this event to move to the previous 'state' of your app. For example, if the user had just opened a window, you would close the window.

An approach that you might take is to add a new item to a 'stack' every time the user executes an action in your app that should be undone by pressing the back button.

Then when the user presses the Back button you can execute the top action on the stack and then pop that action off the stack. When there is nothing left on the stack and the user presses the Back button you can exit the app. To do this your event handler would execute this code.

e.event.preventDefault();
navigator.app.exitApp();

 

UX Component - List Control - AfterRefreshData Event - A new event has been added to the List control After the List control's data has been refreshed (using the {dialog.object}.refreshListData() method) the AfterRefreshListData event will fire. This event is defined in the Events section in the List Builder.

 

UX Component - Action Javascript - Image Capture - Camera/Photo Library Action - Videos - This Action Javascript action can now let the user select a Video from the Photo Library. This only works in a PhoneGap application.

The Type property in the image shown below is visible if the Image capture method is set to PhoneGap and the Picture source property is set to Photo Library.

 

Once the user has selected a video from the Photo Library, the Javascript defined in the Javascript to execute when image has been captured property is executed.

Your code can reference e.fileSystemURL, the filename of the video file. You could use this value to set the value of the VideoPlayer control so that the video can be played back, or you might want to upload the video to your server, or to Amazon S3.

For example

{dialog.object}.setValue('myvideoplayer',e.fileSystemURL)

 

UX Component - Google Address Suggest - Address Filtering - You can now specify a filter to filter the addresses shown. For example, you might want to restrict address to a certain country.

For example, in the image below, addresses in New Zealand are shown.

 

 

You can also use a Javascript function to specify the filter. For example:

javascript:myfunction

 

In the above example, the Javascript function myfunction should return the Filter as an object. For example:

function myfunction() {

    return {country: 'NZ'};

}

 

Note: The Javascript function is called when the auto-complete field is initialized. It is not called every time the user types an address into the field.

UX Component - Number Formats - Two new properties in the UX allow you to specify the format that users will use when entering numbers.

The Number format - decimal character allow you to specify what character the user will use when entering decimal places.

The Number format - thousands separator allow you to specify what character the user will use when entering formatted numbers above 999.

You can enter the explicit character to use or 'period' (which is simply a symbol for a period) or 'comma' (which is simply a symbol for a comma).

These properties can also be set automatically, and dynamically, using session variables. The values in these session variables could be set when a user logs in by referring to some user preference setting stored in a table on the server.

The session variables are:

 

IMPORTANT: If the regional settings on your server do not use a period as the decimal character then it will be important to update existing UX components and set the value in these two properties if the defaults (period for decimals and comma for thousands separator) are not correct.

 

Build 3892

 

Technical Note

This change is  made necessary by an internal change to the {dialog.object}.getValue() method. Previously, if a user in (say) Spain (where the decimal character is a comma) entered a value (say 234,34) into a numeric textbox, and then used the .getValue() method to read the value in the control, the .getValue() method returned:

234,34

Now, if the user has specified that the  Number format - decimal character property is a comma, .getValue() will now return this (a string value)

234.34

This is an important change because if you wanted to perform a numeric calculation using this number you can simply use the Javascript Number() function to convert the string to a number and then do the calculation. For example

var newVal = Number({dialog.object}.getValue('NUMBER1')) * 12

 

 

UX Component - Internationalization Helper - The Internalization Helper (accessed from the   button in the UX builder), now has a new option to perform all actions at once, rather than requiring actions to be executed individually.

 

 

UX and Grid Component - Javascript Editors - Code Library - A code library is available in all contexts where Javascript can be edited.

Watch Video

To open the Code Library, click the Code Library icon (shown highlighted in yellow below) on the toolbar.

To add a code snippet to the library, highlight the code in the editor and then click the 'Add' button (left most button on the button bar at bottom of the Code Library window)

To insert a code snippet into the code you are editing either double click on the item or click the 'Insert' button (3rd from left on button bar).

Features of the Code Library include:

 

UX Component - System SVG Icons - Alpha Anywhere now comes with a set of pre-defined SVG icons that can be used with any style. These SVG icons are the same icons that the new Alpha stylesheet uses.

When you are using a stylesheet other than the the Alpha stylesheet, when you open the SVG Icon picker you will see that the system SVG icons are shown in a category called System SVG Icons.  In addition, the Class dropdown will have three special auto-generated classes that can be applied to the SVG icons. These are

The definition of these classes are shown below.

If you do not select any class, some of the images will not render properly because the stroke color of the SVG icon is not defined.

You must select either icon or iconSizeable for the icons to render correctly.

You will notice that the icon class defines a explicit size for the icon (26 x 26 px). Therefore changing the size using the slider on the dialog will have no effect.

If you would like to be able to size the icon, you should select the iconSizeable class.

You can also define your own classes in the component's Local CSS, or Linked CSS to apply to the SVG icon.

 

 

 

 

 

.icon {
    vertical-align: middle;
    width: 26px;
    height: 26px;
    fill: #333;
    stroke: #333;
}


.iconSizeable {
    vertical-align: middle;
    width: auto;
    height: auto;
    fill: #333;
    stroke: #333;
}
.iconDisabled {
    opacity: .25;
}

 

 

 

 

UX Component - Text Area - Mobile Devices - If you have a Text Area control on a mobile device, it can be difficult to scroll the text in the text area without scrolling the Panel that the Text Area is in,

On iOS devices you can scroll the text in the Text Area using a two finger drag. However, this is a cumbersome and not obvious gesture.

A new pre-defined control is available to create a Text Area that is optimized for mobile devices.

 

The image below shows the Text control with a special slider on the right hand side that will allow you to easily scroll the text in the Text Area control.

 

 

SQL Server LocalDB - Alpha Anywhere now automatically installs SQL Server LocalDB when you install Alpha Anyhwere. SQL Server Local DB is installed. This means that as soon as Alpha Anywhere has been installed, developers will be able to start building applications that use a SQL database, even if they don't access to a SQL database of their own.

According to the Microsoft documentation:

LocalDB installation copies a minimal set of files necessary to start the SQL Server Database Engine. Once LocalDB is installed, you can initiate a connection using a special connection string. When connecting, the necessary SQL Server infrastructure is automatically created and started, enabling the application to use the database without complex configuration tasks. Developer Tools can provide developers with a SQL Server Database Engine that lets them write and test Transact-SQL code without having to manage a full server instance of SQL Server.

When AlphaAnwhere is started it automatically creates a named instance of LocalDB called AlphaAnywhere

To build a connection string to the LocalDB databse, use the SQL Server driver and specify the Version as 2016 and the Server Name as (localDB)\AlphaAnywhere.

When you select a connection string in the various genies and builders, a hyperlink appears at the bottom of the dialog that allows you to automatically create a LocalDB version of the sample Northwind database that is uses in many of the Alpha Anywhere tutorials and videos. When you click the hyperlink a named connection string called AADemo-Northwind is created.

 

 

 

UX Component - Starter Templates - Two of the starter templates listed when you create a new UX component have been recreated using ControlBars in the Panel headers and footers rather than individual UX controls. The versions created using ControlBars are smaller than the corresponding versions that do not use ControlBars.

 

Grid Component - HTML Editor - Customize Toolbar Icons and Layout - You can not choose your own icons for the HTML toolbar editor and you can customize the layout of the editor, rearranging the buttons, and leaving off buttons for features you don't want to expose.

 

 

UX Component - List Control - Save/load Settings -  After you have defined the settings for a List control, you can now save the settings to a file on disk. Then when you begin defining a new List, you can restore previously saved settings. This can save a lot of time when setting up a List that is similar to a previous List you have created.

Watch Video

 

To save, load or manage your settings file, click on the Save/load Settings... button at the bottom of the List builder.

 

Select an option from the sub-menu that appears.

 

 

If you select the Manage saved settings option, Windows Explorer will show the folder where the settings files are stored and you can delete, or rename any of the files.

NOTE Saved settings are common to all web projects and all Workspaces. That means that it is possible to load a saved setting that will not work in your current context. For example, if you restore a saved setting for a SQL list that specifies a particular connection string, and that connection string is not present in the current Workspace, your List will not work until you fix the problems.

 

UX Component - Application Cache - Building Offline HTML5 Applications - You can now create a static HTML page for a UX component. This static HTML file can include a cache manifest. This will enable the static HTML page to work 'offline'.


Watch Video - Part 1
Watch Video - Part 2

 

Offline enabled HTML pages can be loaded into a browser even if no internet connection is available.

To turn on this feature, click the smart field for the Create a static HTML page with an application cache property, as shown in the image below.

When this property is checked, when you save the UX component, a special sub-directory in the Web Project folder is created. This directory is called StaticHTMLFileset and it contains the static HTML page with the rendered UX component and all of the files referenced by this page (e.g. Javascript, CSS and image files). The directly also contains an application manifest file which lists all of the files reference by the static HTML page. The application manifest file is linked in the head of the static HTML page by specifying  a value for the manifest attribute in the <html> tag. For example:

<html manifest="cache_myuxcomponent.appmanifest">
 

 

 

When a static HTML page that includes a manifest is loaded, all of the files listed in the manifest are stored in the browser's ApplicationData storage area.

When a static HTML page is loaded, the browser checks to see if a cached version of the page and all of the files it references exists in the browser's ApplicationData storage area. If so, the page is loaded from the ApplicationData storage area. To determine if the cached version is stale or not, but browser will attempt to contact the server (if an internet connection is available) to check if a newer version of the manifest is available.

If a newer manifest is available, the browser will download and cache the new version of the static HTML page and its referenced files.

While the browser is downloading files listed in the manifest, a series of events will fire. You can specify event handlers for these events in your  UX component.

When you click the smart field for the  Create a static HTML page with an application cache property, you can automatically generate default code for the error, updateready and progress Application Cache events:

 

 

UX and Grid Component - Action Javascript - Send SMS Message using Twilio - A new action has been added to Action Javascript to allow you to send an SMS message. You will need an account with Twilio to use this feature.

 

Watch Video

 

The action allows you to:

To specify the message text you can:

You can also specify Javascript code to execute after the message has been sent.

You can either explicitly specify your Twilio credential, or you can reference a NamedResource which contains your credentials. You will need your Twilio SID, Token, and Phone Number (the phone number from which the SMS message is sent).

If you use the NamedResouce option, you can change specify different values for the SID, Token and Phone Number in your publishing profile.

To create a NamedResource, open the Web Project Properties dialog.

 

The screen below show the Action Javascript builder for the action.

 

reversearray() Function - You can reverse the order of items in an array with the reversearray() function.

Examples:

 

dim p[3] as n

p[1] = 1

p[2] = 2

p[3] = 3

reversearray(p)

?p.dump()

= 3

2

1

 

dim p[2] as p

p[1].name = "alpha"

p[2].name = "beta"

reversearray(p)

?p.dump_properties("name")

= "beta"

"alpha"

 

 

UX Component - List Control - Layout - Copy Property Value - In the Layout tab of the List Builder, when you are editing a column layout, you can now copy a property value from one column and paste it to multiple columns.

 

 

 

 

UX Component - List Control - Render Columns in Reverse Order - If you are using a right-to-left language (such as Hebrew), then you might want the columns in a Column layout to be rendered in reverse order. A new property in the List Properties allows you to reverse the column order.

 

Xdialog - Caption Fields - You can now define a caption (i.e. a watermark) for an input control on an Xdialog. When there is no text in the input control the caption shows. As soon as the user begins to type in the field, the caption is replaced by the user entered text.

 

To define a caption for an input control, use the caption directive within the %...% delimiters.

For example:

 

 

ui_dlg_box("Captions",<<%dlg%
[%caption=Enter Name%.60name];
[%caption=Enter City%.60city];
%dlg%)

UX Component - Google Address auto-complete - afterGoogleAddressSelect Client-side Event - A new client-side event is defined. This event is called after the user makes a selection from the Google address auto-complete list. The event gets the Google 'place' object with a wealth of information about the address the user selected. You can use this event to define a custom mapping of data from the 'place' object to controls on your component.

 

UX Ccomponent - ViewBox Control - Sample iOS Settings Screen - A new sample ViewBox can be loaded into the ViewBox builder.

 

 

 

 

The iOS Settings screen example is loaded by clicking the Load Sample ViewBox link on the Home tab of the ViewBox Builder.

 

The entire contents of the settings screen (i.e. each of the properties prompted for and the type of editor used for the property) is driven by the ViewBox data. For example, the settings screen in the above image is created using this data:

 

[
{text: 'Name', type: 'edit', editor: ['EDITORSET_1','EDITOR_1'], name: 'name', value: 'John Smith'},
{group: 'Group 1', icon: 'svgIcon=#alpha-icon-home:icon', text: 'Item 1', type: 'switch', name: 'item1', value: true},
{group: 'Group 1', icon: 'svgIcon=#alpha-icon-shield:icon', text: 'Item 2', type: 'switch', name: 'item2', value: false},
{group: 'Group 1', icon: 'svgIcon=#alpha-icon-envelopeSolid:icon', text: 'Item 3', type: 'switch', name: 'item3', value: true},
{group: 'Group 2', text: 'Notifications', type: 'disclosure', name: 'disclosure1'},
{group: 'Group 2', name: 'passFail', value: 'Pass', values: ['Pass','Retry','Fail'], type: 'radio'},
{group: 'Group 2', name: 'colors', value: ['Red','Green'], values: ['Red','Blue','Green'], type: 'checkbox'},
{text: 'Phone', type: 'edit', editor: ['EDITORSET_1','EDITOR_1'], name: 'phone',value: '123 456-7890'}
]

 

The ViewBox 'value' is a JSON string of the setting values. The settings can be initialized by using the .setValue() method and setting the ViewBox value to a JSON string of setting values.

NOTE: This control is must be used with the Alpha style as the icons in the data are SVG icons, used in the Alpha style.

NOTE2: The edit the text properties in the dialog you will need to add an editor set called EDITORSET_1 with a text box editor called EDITOR_1.

This sample ViewVox is a good example of how very rich user interfaces can be built very easily and efficiently using a ViewBox. For example to add a new setting to the ViewBox, simply add the definition to the ViewBox data.

 

UX Component - Google Visualization Libraries - When using the Google Visualization library in a UX component, it is no longer necessary to go to the Web Project Properties dialog to specify that the Google JSAPI library should be loaded. The Visualization libraries are now loaded automatically by the UX as needed.

UX Component - Goggle Address Auto-complete - In many applications (both web and mobile) it is common when typing in an address to get auto-complete suggestions, as shown in the image below.  In the image shown, the user has begun typing an address into the Address control ('70 blanc') and a drop-down list of possible addresses is shown.

This is achieved using a feature of the Google Maps API.

You can now add this functionality to your any textbox in a UX component.

Watch Video - Part 1
Watch Video - Part 2
 

NOTE: In order to use this feature you will need an API key from Google. You can get an API key for Google Maps Javascript from the Google site. This API key is the same key needed for Google Maps.

 

When the user makes a selection from the drop-down list, you can also specify that the individual parts of the address should populate other controls on the UX. For example, if the user were to select the first entry in the drop-down list shown above, you might want to insert '70' into a 'StreetNumber' control on your UX, 'Blanchard Road' into a 'Street' control, 'Burlington' into a 'City' control, and so on.

The genie that allows you to configure this feature makes it easy to set up these mappings.

To turn on GoogleAddressSuggest for any textbox control, set the Special type property to GoogleAddressSuggest.

 

 

Next click the smart field for the Special type settings property. This will open a builder appropriate for the special type you selected.

 

The builder allows you to specify how the address parts from the selected address should be mapped to individual controls on the UX component. You do not have to define any mapping if you don't want to map address parts to individual controls.

For each address part that you choose to map, you can specify if you want the 'long' or 'short' form of the string. For example, the long form of a state field might be 'Massachusetts', while the short form might be 'MA'.

 

 

 

You can also specify your API key.

NOTE: If you leave the API key blank then Alpha Anywhere will read it from the setting in Web Project Properties. If there is no setting in Web Project Properties then it will look for a file called GoogleMapsAPIKey.txt. This file should have the API key in it.

The Bias address suggestions to the user's current location prompt allows you to bias the address suggestions to the user's current location. So, for example, if the user is in Paris, the suggestions displayed by Google will show Paris addresses at the top of the list.

 

NOTE: Address auto-complete for textbox controls in Repeating Sections are not supported.

 

 

UX and Grid Component - Customize Style Colors and Fonts - Editing the colors and fonts used in a style has always been possible by editing the style sheet. For example, if you are using the iOS7 style, you could edit this style and customize all colors and fonts.
 

However, if you edit the style, you create your own copy of the style. That means that if Alpha subsequently modifies this style (for example, by adding new CSS classes for some new control type that is added to the UX), your style will not see these new classes unless you manually add them to your copy of the style.

Also, bringing up the style builder just to change one of the colors in the style seems like overkill.

A new option is now available for 'version 3' (e.g. iOS7, AndroidDark, AndroidLight) and 'version 4' (e.g. Alpha) styles.  These styles use SASS variables to define the colors and fonts used in the stylesheet.

Watch Video

 

To edit colors and fonts, click the smart field for the Customize style colors and fonts property.

The dialog in the image shown below will be displayed.

 

 

When you edit the colors and fonts using this builder, you are not editing the base style sheet. Instead you are storing your adjustments to the style in a separate file. This means that if the style sheet is changed by Alpha, you will get all of the edits applied to the style by Alpha, and you will still get your color and font changes.

To see the file in which your edits are stored click the Manage files hyperlink at the bottom of the dialog.

NOTE: When you customize the colors and fonts for a style, the edits apply to all components in your project that use the style. So, even though you might be in UXComponent1 when you edit the colors, UXComponent2 (for example), if it uses the same style as UXComponent1, will get the same edits to the colors and fonts.

If you want to delete the custom colors you have defined, open the editor, and click the Manage files hyperlink and then delete the styleTweaks.json file that contains the settings.

 

 

 

Xbasic Functions - sha512() function - Creates a hash using the SHA512 algorithm.

Syntax

result = sha512(c text [, L flagBinary])

If flagBinary is .t. the result is a blob.

 

Web Applications - Style Sheets - Alpha style - A new style sheet called Alpha has been released.

The Alpha style (which is a 'version 4' style) uses SVG icons (as opposed to CSS Icons which 'version 3' styles - such as iOS7, AndroidLight and AndroidDark used).

The Alpha style is primarily intended for use with UX components.

When you select the Alpha style (or any 'version 4' style), the builder displays a prompt allows you to select the 'compact' version of the style. For mobile applications the standard version of the style is appropriate. For desktop web applications, you might find the standard version of the style to be too large. Selecting the compact version of the style will render the component using smaller text, buttons, icons, etc.

 

 

The images below show a grid using the Alpha style. The first image is using the compact version of the style.

 

 

 

A notable feature of the new 'version 4' styles is the change in the naming convention for the CSS selectors. In 'version 3' and older style sheets, the CSS selectors include the style name in the selector. For example, in the iOS7 style sheet there is a selector called:

iOS7Button

In 'version 4' style sheets, the CSS selectors do not include the style name. So, the CSS selector for a button is now simply

button

As a result of this change, when using a 'version 4' style, it will not be possible to have a page with two different components, each of which uses a different 'version 4' style. On the other hand it will now be possible to dynamically change the style of a component from one 'version 4' style to another 'version 4' style without having to re-render the component.

 

UX Component - ViewBox Control - Capture Focus property - The ViewBox has a new property that allows you to specify if the ViewBox can capture focus. Be default, this property is set to true. However, in cases where you ViewBox contains standard HTML controls (such as INPUT or TEXTAREA controls) and you want the user to be able to type into these controls you should set the Capture Focus property to false.

PhoneGap App Builder - User Defined PhoneGap Plugin Library Manager - When you use the PhoneGap Builder to build a PhoneGap project, the Builder gives you a list of PhoneGap plugins to choose from. However, there are many more PhoneGap plugins than those that are listed in the Builder. The plugins that are listed in the Builder are those specially chosen by Alpha Software and they are a small subset of the available plugins.

You may have a need for a plugin that is not listed in the Builder.

The User Defined PhoneGap 3rd Party Plugins Library Manager has been added to the PhoneGap App Builder. This allows users to easily include any publicly available PhoneGap plugin within a PhoneGap Project. The Plugin Manager allows you to easily add, edit and delete the PhoneGap plugin resource definitions.

 

To open the User Defined PhoneGap 3rd Party Plugins Library Manager click the Manage My PhoneGap Plugins button at the bottom left of the Builder screen.

 



 

This will open the Library manager where you can add the plugins that you want.





For more information on this feature, please refer to the documentation. See User Defined PhoneGap Plugin Library Manager
 

 

 

 

 

UX Component - Client-side Templating - New Directives - Several new directives have been added to the client-side templating syntax.

The new directives are listed below:

 

Comments - You can now add comment to your templates.

 

Syntax:

{/* comment */}

 

Note: Comments must have white space after the first "*" and before the last "*".

 

When the template is expanded, any space taken by comments is ignored. Comments are useful for the obvious use case of adding explanations to your templates.

But another less obvious use case for comments is to make templates more readable. For example, in certain cases your templates should not include any line breaks because the space taken by the line break will affect how the expanded template appears. However, this makes the template difficult to read. In the example below, an empty comment that spans two lines is used to insert a line break into the template for readability. This line break is ignored, however, when the template is expanded.


Example


{/* this is the firstname field */}
<div class="item">{/*
*/}<div class="label">Firstname</div>{/*
*/}<div class="field">{firstname}</div>{/*
*/}</div>
 

 

Arbitrary iterator - Allows you to iterate over dynamically created data.

Syntax:

 

{*@functionName}
...
{/*}


The iterator is useful for inserting external data into the template when it is expanded.

Example:



{orders}
{id} {total} {date}<br />
{*if !delivered}
{*@tracking}
{location} at {date}
{/*}
{*endif}
{/orders}
 

Where tracking is a Javascript function that might be defined as follows:


function tracking(data,temp,root,parent,path){
    /*

    data is the current parent data context - in this case the current order

    assume code here that goes to a separately stored tracking array and

    returns an array of locations and dates
    return [

        {location: 'Boston MA', date: '9/4/2016'},

        {location: 'Albany NY', date: '9/5/2016'}

    ];
}

 

Escape - Allows you to escape a long string of template characters.

 

Syntax:


<escape<{some template code'}>>


In some cases you need to include special functions in a template (such as A5.map.staticMap() - a function that generates a static HTML map). The function call may include characters such as a colon and curly braces, which must be escaped because they have special meaning in a template.


Example:


{A5.map.staticMap(<escape<{
width: 400,
height: 300,
center: 'Boston MA'
}>>)}
 

Before the escape directive was available, this above template would have had to be written as (escaping the : { and } characters in the function arguments):

 

{A5.map.staticMap(\{width\: 400,height\: 300,center\: 'Boston MA'\})}

 


Ensure - Allows you to ensure that certain properties exist in the Data.

 

Syntax:

{*ensure a,b,c}
 

 Where a, b and c are data variables that you want to define so that if they are referenced in an {*if} block, the {*if} block will evaluate correctly.



Example:


Assume the data passed to the template is:

{bar: 'world'}


Template


{*if foo == 'hello'}
...
{*elseif bar == 'world'}
...
{*else}

...

{*endif}

 

Without {*ensure foo}, the {*if} block will not execute correctly,  as foo doesn't exist.

Here is how the template could be rewritten to ensure that it works as expected:

 

(*ensure foo}

{*if foo == 'hello'}
...
{*elseif bar == 'world'}
...
{*else}

...

{*endif}
 

 



Defined / Undefined - Provides a shorthand syntax for checking if a list of variables are either defined, or undefined.

 

It is common in the logical expressions in a {*if} block to check that certain variables are defined or undefined. The code to do this can be cumbersome and the <defined<variableList>> and <undefined<variableList>> directives make your template more readable.

For example, imagine you had the following template:

{*if typeof variableName1 == 'undefined' || typeof variableName2 == 'undefined'}

...

{*endif}

The syntax in the template is cumbersome and can be simplified as:

 

{*if <undefined<variableName1,variableName1>>}

...

{*endif}
 

Similarly, an expression that tests if variables are all defined might previously have been written as:

{*if typeof variableName1 != 'undefined' && typeof variableName2 != 'undefined'}

...

{*endif}

 

can now be written as


{*if <defined<variableName1,variableName2>>}

...

{*endif}

 



Expression escapement - The ":" and "|" characters have special meaning in a template and therefore, if they are used in an expression, they must be escaped.

 

If a logical expression in an immediate if expression is enclosed in ( ... ), the special : and | characters do not need to be escaped.

NOTE: The : character in a template is how a formatter is defined and the || character sequence is now text for null values are defined.

For example consider the following template code:

 

{a ? b \: c:uppercase}

If a is true, then the expression will return b. However, if a is false, the expression will return c. The returned value (either b or c) will then be uppercased because the formatting directive (:uppercase) is applied to the result of the expression.

 

The above template can now be rewritten as:

 

 {(a ? b : c):uppercase}

 

Expression escapement is not limited to logical expressions. For example, the following template expression concatenate strings, one of which is a string containing a : character.

{(a + ':' + b):uppercase}

 

 

UX Component - AudioPlayer and AudioRecorderPlayer Control - onError event - The onError event fires when an audio file does not load.

 

UX Component - AudioPlayer and AudioRecorderPlayer Control - onChange event - These controls now support an onChange event. This event can be used to create a custom progress display while an audio is playing back.

 

UX Component - FormView Control - Form Layout - Flow and Column Containers - When you are laying out a Form in a FormView control using the Genie mode, there are two new Layout Container types that allow you to create complex form layouts without forcing you to switch from Genie mode to Freeform mode.

The two new Layout Containers are


Watch Video - Part 1
Watch Video - Part 2

 

The flow container allows you to lay out controls that flow from left to right and then start a new line when an explicit break is inserted, or the sum of the widths of the control on a line equals 100%.

The column container allows you to lay out the controls in multiple columns in which the controls flow from top to bottom and then start a new column.

Flow and Column containers can be nested, allowing you to create extremely complex layouts, all from within the Genie.

In the image below, the form has been laid out using a column container. The container has been divided into two equal width columns and a vertical line spacer has been inserted between the columns.

 

 

 

In the next image, the controls have been laid out using a flow container. Notice that explicit breaks to start a new line have been inserted after some of the controls and the width of each control has been explicitly set (using a percentage, although explicit widths are also supported).

For example, the Customerid control width was set to 25% and a break was inserted after the field to start a new row.

The City Region and Postalcode fields all have a width of 33.33%. The Phone and Fax field are each 50% and the Thumb and Thumb2 fields are also 50% each.

 

In the next image a more complex layout is created by nesting Flow and Column layout containers.

At the top level a Column container is defined with column widths of 50%, 25% and 25%.

Within the first column a nested Column container is defined. This container has two columns showing Companyname and Contactname in the first column and Contacttitle in the second column.

Also within the first column a nested Flow container is defined. This flow container has Address (with a width of 100%) and City, Region ad Postalcode, each with a width of 33.33%.

In the third column a nested Flow container is used to put Thumb and Thumb2 on the same line (each with a width of 50%).

 

Here is how this layout is defined in the FormView Builder:

 

Using the Column Container

To insert a Column Container into the Form Layout click the Add Item button and select a Layout Container and set the Layout type to 'Column'. All of the controls that should be laid out in columns should be placed inside this container.

You can start a new column at any time by inserting a break after a control. In the above example, the nested Column layout container has two columns because only one control in the container (LAYOUTCONTAINER_5) has a break (i.e. ContactName).

The outer Column container has three columns because there is a break on [LayoutContainer End: LAYOUTCONTAINER_3], and Phone.

You can control whether there is a line between columns, how much space to leave to the left of the first column and the right of the last column and how much space to insert above the the columns and below the columns.

You can also control the spacing between columns.

The columns can either be equal sizes. or you can specify explicit widths for each column (using either percentages or absolute sizes). To specify explicit sizes for each column, enter a comma delimited list of sizes. The first size in the list applies to column 1, the second size in the list applies to column 2 and so on.

 

Using the Flow Column Container

To insert a Flow container into the Form Layout click the Add Item button and select a Layout Container and set the Layout type to 'Flow'. All of the controls that should be flowed should be placed inside this container.

You can assign an explicit width to each control and you can add breaks after certain controls to force a new line.

NOTE: If you are using percentage widths and the sum of the widths of the controls on a line equals 100% a new line is implicitly started for the next control. It is not necessary to put a break after the last control on the line. However, if you do not put an explicit break on the last control in the line, the control spacing setting (defaults to 4px) will still get added to the end of the line even if you have unchecked the 'Add spacing after last control on each line' property.

You can control the horizontal spacing between each control on a line. You can also specify if the spacing should be added before the first control on a line or after the last control on a line.

 

 

 

Grid and UX Component - Google Maps - Icon Sequences - Icon sequences previously used URLs that pointed to remote images for each image in the sequence. Some of these remote URLs are now broken and as a result certain icon sequences were no longer working. All icon sequences have now been converted to use internal images and therefore all icon sequences will now render correctly.

Development Server - Default Port - The default TCP port for HTTP communications is 80. As such, the Alpha Anywhere Application Server and Development Server have both used port 80 as their default server setting. However, this port is not always available on non-server systems because of other software using it (e.g. Skype) and conflicts sometimes arise. To address this, the Development Server no longer defaults to port 80. The Application Server is unchanged and still defaults to port 80/

When the Development Server does not already have a server configuration file available (e.g. a new install), Alpha Anywhere will find an available TCP port for the server to run on instead of simply defaulting to port 80. The search for an available port begins at 1580. If no available port is found (ports go up to 65535 so this is extremely unlikely), the configuration will fall back to 80.

Because this port search is only done when there is no existing configuration file, a developer may specify a port at any time and that setting will be maintained. Similarly, this change does not impact existing installations of Alpha Anywhere where the Development Server has been configured or run at least once.

 


Application Server - HTTP Strict Transport Security - The Alpha Anywhere Application Server now supports HTTP Strict Transport Security (HSTS). HSTS is a security mechanism that allows a server to indicate that clients should only communicate with it using using HTTPS connections. For more information on HSTS, see https://wikipedia.org/wiki/HTTP_Strict_Transport_Security

HSTS can be enabled on your server by simply checking the box on the SSL tab of the Application Server Settings. The HSTS maximum age may also be specified here.

With the default SSL Cipher List, HTTP Strict Transport Security enabled, and a valid SSL certificate, the Alpha Anywhere Application Server can achieve an A+ rating on the Qualys SSL Labs SSL Server Test at https://www.ssllabs.com/ssltest/index.html (as of August 3, 2016).

 

 

UX Component - List Control - Detail View - onSQLExecute Error Event - A new server side event has been added to the List to allow you to translate database error messages into friendlier error messages.

To define the Xbasic function to process database error messages, go the Detail View tab in the List builder, and edit the Table Properties.

 

XBasic - Twilio - Sending SMS Messages - twilio_send_sms() Function - You can now send SMS messages from XBasic to a mobile phone.

 

NOTE: In order to use this function you must first set up an account with Twilio an purchase a phone number that is authorized to send SMS messages. Go to www.twilio.com for more information.

 

When you create your twilio account you will get the following items, which you will need in order to use the twilio_send_sms() function:

When you use the twilio_send_sms() function you can either pass in the values for the AccountSID, the AuthorizationToken and the 'From' phone number directly, or you can create an entry in the Named Providers property in Project Properties to store these values and then just pass in the name of the stored settings to the function.

NOTE: Using Named Resources is the preferred method because you can redefine any of the parameter values in the stored setting when you define a publishing profile.

 

Syntax:

L result =  twilio_send_sms(pResult as p, to as c, message as c, namedResource as c , from = "", accountSID = "", authCode = "" )
 

If you want to explicitly set the accoundSID, authCode and from arguments, set the namedResource argument to an empty string.

pResult is an object that contains return information provided by Twilio. For example, if the SMS fails ( result  = .f.) the pResult object will have a property explaining why the SMS failed.

 

To define a Named Resource, click the Project Properties button on the Web Control Panel. The click the smart field for Named Providers.

 

 

Example:

 

dim to as c
to = "+15551111"
dim message as c = "Sent from Xbasic at: " + now()

dim namedResource as c = "MyTwilioSettings"
dim pResult as p
dim flag as l
flag = twilio_send_sms(pResult,to,message,namedResource)

 

'to see what's in the pResult object

showvarscript(pResult, "" + flag)

 

UX Component - ButtonList Control - Fill Width - If a ButtonList control is set to render horizontally, a new property allows you to force the ButtonList control to fill with width of the ButtonList's defined width. So, if the ButtonList's defined width is set to 100% and the Fill width property is checked, the ButtonList will fill the width of the screen.

 

 

The Fill width property is also available for RadioButton and CheckBox controls that are set to render as ButtonLists.

 

ButtonList, RadioButton and CheckBox controls set to fill the width of the screen.

 

IIS Application Server - Application Pre-load - The first time a page in an IIS application is loaded, it can be slow because the application needs to be initialized. A new option allows you to pre-initialize the application. This options is accessed in the IIS Publish Profile. The option is called Enable application preload and is checked by default. This setting uses the IIS "Application Initialization" feature to automatically load and initialize an application so that it is more likely that the first request to an application is serviced much quicker.

Note that this option will default to enabled for existing publish profiles and that the "Application Initialization" feature must be installed on IIS. The installation guide recommends that application initialization is installed, but stops short of requiring it. Because of this, publish will check if application initialization is installed or not and will prompt the user if it is not installed and preload is enabled.

 


 

UX Component - List Control - Detail View - Write Conflicts - When you sync data that was edited in a List with a Detail View, there is always a chance that an update will fail because of a write conflict. When a write conflict does occur, the error is bubbled back to the user to allow the user to resolve the conflict. However, the developer can also define a server-side onWriteConflict event that fires when a write conflict occurs. The code in the event can programmatically resolve the conflict and no write conflict error will be bubbled back to the user.

If your event handler programmatically resolves a write conflict you can now specify Javascript code that will execute on the client after the sync is complete. The typical use case for this new property would be to inform the user that there was a write conflict, but that the write conflict was resolved programmatically on the server.

 

For example, your Xbasic code in the onWriteConflict event might set e.javascript as follows:

e.javascript = "alert('Write conflict in row [rowNumber] was automatically handled on the server.')"

 


The [rowNumber] placeholder in the message will be replaced with the zero based row number in which the conflict occurred. If you are working with hierarchical data (i.e. there is a parent-child relationship between Lists), then [rowNumber] will be replaced with the full path to the List where the conflict occurred. For example,

0,'__LIST__ORDERS',3

This would indicate that the row in which the conflict was handled programmatically is the first row in the parent List, then the 4th row in the 'Orders' list.


 

 

PhoneGap App Builder - Icon and Splash Screens (Android) - Added support for Android xxxhdpi icons and splash screens. When building an Android app, the PhoneGap App Builder now includes default images for a xxxhdpi icon and xxxhdpi splash screens in portrait and landscape mode. When generating the icon or splash screens for an Android app, the xxxhdpi icon and splash screens will be generated.

PhoneGap App Builder - Configuration Options - Launch PhoneGap App Manager After App Submission to PhoneGap Build - By default, the PhoneGap App Manager is launched after an app is submitted to PhoneGap Build. Uncheck this option to disable this behavior.



PhoneGap App Builder - Third Party Plugins (Android, iOS) - Media Capture With MP4 Video - Added support for the Alpha Media Capture With MP4 Video plugin. This plugin requests a MPEG/MP4 video file when run on an Android device (not all Android versions/devices support MP4 video) and converts the recorded mov file to an MPEG/MP4 file on an iOS device. This provides file uniformity across all devices. The videos that are recorded with this plugin can be played back on iOS, Android, Windows and OSX devices.

For the full Media Capture With Mp4 Video plugin documentation, see cordova-plugin-media-capture-mp4video.
 

UX Component - Form View Builder - Enhancements to the FormView builder now allow for a new container type - HTML Element. This allows you to use the Layout genie to construct HTML tables.

Connecting to MySQL using AlphaDAO - A new MySQL driver is used in build 3732 and above. There are some things to be aware of when using build 3732 or above.

  1. If you have any problem connecting to MySQL with the new driver, you can roll back to the old driver by selecting the MySQLV4 API when you build your connection string.
  2. The connection string builder for MySQL now has a new property that allows you to specify the version of MySQL that you are using.
  3. The connection string builder for MySQL and Maria DB now has a new property to specify if you want to use ipv4 or ipv6. The property is only enabled if the database version is specified and is 5.6 or above.

Google Maps - Map overview and Pan control properties removed from the builder as Google has deprecated these features. For more information, click here.

 

Image Gallery Component - Google MAPS APIKey - Now allows you to specify your Google Maps API key.

Grid Component - JSON Format - The Grid component file (i.e. the .a5wcmp file) can now be saved in a JSON format. Previously the Grid was always saved as a binary file. The ability to save the UX in JSON format was introduced some time ago.

Web Components - Default File Save Format - The default component save format for all new components that support multiple file formats can now be set in the Web Project Properties.  This is set in the Design-time Properties under 'Component File Save Format'. Most components can be saved in 'Binary' or 'Formatted JSON' formats. Formatted JSON saves the properties in clear text. This is useful if you are using some type of source or version control system and the system has a method to show differences between versions.  The 'Binary' format creates smaller files and can be used if source control is not used.  The option can be left blank to use the default file format set for each component type in the component builder.
 

AlphaDAO - Oracle - Oracle TLS/SSL Support - Alpha Anywhere now supports Oracle TLS/SSL connection definitions without the requirement of a tnsnames.ora file (containing a TNS name definition). This can make deploying to an application server easier in cases where a secure connection is required and you do not want to maintain individual TNS names.

Oracle Connection String Changes

In the Oracle connection string dialog, there is now an additional tab labeled TLS/SSL that includes a checkbox for enabling SSL.

There is also a text box for optionally entering the distinguished name of the server certificate. Providing this entry results in the clause (SECURITY=SSL_SERVER_CERT_DN=...) being added to the connection description. The distinguished name you provide is used to verify the server certificate.

The connection string dialog sets the following connection string attributes:

Note: If you are connecting to an Amazon RDS server, leave the Distinguished Name entry blank. Alpha Anywhere will provide it automatically.

Be sure to import the Amazon RDS certificate on your application server (the client for Amazon RDS). You can download the certificate bundle from Amazon at rds-ca-2015-root.pem For more information on Amazon RDS SSL support for Oracle see Options for Oracle DB Instances

For help on importing a certificate on Microsoft Windows Servers see Import a Certificate

sqlnet.ora

Important: Oracle requires the configuration file sqlnet.ora for the most common SSL settings. The example entries below show the most common values. Consult Oracle documentation for details.

Notes:

  1. The TLS/SSL port will NOT be 1521 as Oracle requires multiple ports. The TLS/SSL port is typically 2484, but this is configurable.
  2. If you select TLS/SSL (A5SSL=Y) and a connection cannot be established securely, SQL::Connection::Open will fail.
  3. If you do not select SSL or do not provide a distinguished name, no value will be added to the connection string.
  4. A new property of SQL::Connection objects called IsSecurelyConnected will return true (.t.) if an SSL connection has been established.

 

 

Alpha Anywhere connection strings may support only encryption, or both client and server certificates. Connection string properties for TLS/SSL support include:
 

    a) SSL -  If A5SSL is set to 'Y', and the connection cannot be established securely, an error is returned.

    b) A5TLSCertificateAuthorityFile - Contains name of a file that contains one or more certificates PEM format with which to verify the server certificate.

 

    c) A5TLSTrustedCertificatePath - Contains a path name to be used for walking the certificate chain. If this property is used, Individual certificates are stored in individual PEM files.

    d) A5TLSClientKeyFile, A5TLSClientCertificateFile - These properties are used to identify the file containing the Client private key and the client certificate for verification of the client. They are used together. As explained above, they are less commonly used.

    e) A5TLSCipherList - An optional list of ciphers to be passed to the server. This list establishes a limit on the ciphers that can be negotiated.

3. A new property IsSecurelyConnected will return true (.t.) if a connection for one of the drivers below confirms a secure connection. Note that ODBC drivers or Oracle TNS connections may in fact connect securely, but if Alpha Anywhere does not know this has happened, the value of IsSecurelyConnected may still return false (.f.).
 

 

 

UX Component - Ink Control - Capturing Signatures - The Ink control can now be easily configured to capture signatures. When you open the Ink Control builder to edit the settings for the Ink Control, the genie now has a new option for Signature Capture.

Watch Video

 

 

Json_sanitize() Function - Converts a JSON string to 'strict' JSON syntax - Javascript objects can be created from literal definitions that do not follow the strict JSON syntax.

For example:

 

var obj = {name: 'Fred'}

 

 

However the JSON.parse() function can only parse strict JSON strings.

Similarly, on the server-side, the Xbasic json_parse() function can parse JSON strings that do not follow the strict syntax. However, many of the other Xbasic JSON functions (e.g. Json_extract() ) require strict syntax.

The Json_sanitize() function will convert a JSON string to strict syntax. For example:

 

dim json as c = "{name: 'Fred'}"

?json_sanitize(json)
= {"name": "Fred"}

 

json_delete() Function - Deletes attributes from a JSON string that match a certain pattern -

For example, consider the following JSON string:

 

dim json as c = <<%json%
{
    one : 1 ,
    two : 2 ,
    arr : [
        { __deleted : true , fname : "joe" },
        { __deleted : false , fname : "jim" }
    ],
    arr2 : [
        { __deleted : false , fname : "joe" },
        { __deleted : true , fname : "jim" }
    ],
}
%json%

 

Assume that you want to remove all 'rows' in the JSON that contain the attribute:

__deleted: true

 

Using json_delete() we can do this:

 

json = json_sanitize(json)  'convert to strict syntax

dim json2 as c

json2 = json_delete(txt , "{ \"__deleted\" : true }")

json2 = json_reformat(json2)

?json2


{
    "one": 1,
    "two": 2,
    "arr": [
        { "__deleted": false, "fname": "jim"}
    ],
    "arr2": [
        {"__deleted": false,"fname": "joe"}
    ]
}

 

 

AlphaDAO - Database Drivers - New and Updated Alpha Anywhere Database Drivers - Alpha Anywhere now include two new SQL database drivers.

The existing MySQL driver has been renamed MySQLV4 and will be available as a fallback for those running older databases. The MySQL library was last updated around 2005 and still uses version 5.0.18 of MySQL Connector/C, so it has no support for SSL, prepared statements and other mainstream features. MySQL version 5.0 was in beta at that time. The current release of MySQL is 5.7 and was released in October of 2015.

Note: Alpha Anywhere now ships with libmysql.dll version 6.1.6.

There are a couple of potential configuration issues on some instances of MySQL that may require attention:

Because MySQL Connector 6.1.6 supports IPV6 as well as IPV4, you may experience slow connect times if one of the following is not set in your MySQL configuration file:

 

  1. Bind-address =* - Add this keyword on its own line under the section [mysqld] and restart the server. For versions before 5.6.6 use :: rather than *. This enables servers to accept IPV6 connections.
  2. skip-name-resolve - Add this keyword on its own line under the section [mysqld] and restart the server. This entry will stop the lookup of hosts by name. Note that you may be required to secure clients by IP address rather than host name. This is recommended. If you have already enabled clients to access your server by host name, your clients may no longer be able to connect.

Instead of
 

CREATE USER 'root'@'localhost' IDENTIFIED BY 'root-password';


use


CREATE USER 'root'@'127.0.0.1' IDENTIFIED BY 'root-password';
CREATE USER 'root'@'::1' IDENTIFIED BY 'root-password';



Note: For Windows servers the configuration file is currently found in the folder "C:\ProgramData\MySQL\MySQL Server 5.7", but your other versions may store it in a different location.

For more information, see the MySQL documentation:

Alpha Anywhere support for SSL:


1) Each database client has a different implementation of TLS/SSL. The most common features are:

    a) Secure/encrypted communication. Here TLS/SSL is used as a vehicle to guarantee a secure communication link with the server. Data is considered to be 'encrypted in transit'.

   b) Verification of the server.

        i) X509 certificates are issued by a certificate authority who vouches for a certificate by signing it with their private key. Using the public key of the certificate authority, a client can verify that they have 'signed' the server certificate.

        ii) A certificate authority can delegate to another authority. As a result, a certificate from a server may actually have a 'chain' of authorizations that go back to a well-known certificate authority. One that our system trusts. When a server returns a certificate to the client, it will generally include the chain of authorities - one of which should match a certificate you trust.

        iii) You can, and in some cases need to, install any certificate as a trusted certificate to verify that a server certificate matches the host name you requested.

    c) Verification of the client.

        i) The same process of verification can also be used to authenticate an SSL client. A certificate is installed on the client (along with a private key) that is then sent to the server to verify that the client is who they say they are. This is less common, but is used in some applications - especially those with a greater need for security and for which there is a manageable number of clients..



2) Alpha Anywhere connection strings may support only encryption, or both client and server certificates (see the driver by driver explanation below). Connection string properties for TLS/SSL support include:

    a) A5SSL - can be Y or N. If A5SSL is set to 'Y', and the connection cannot be established securely, an error is returned.

    b) A5TLSCertificateAuthorityFile - Contains name of a file that contains one or more certificates PEM format with which to verify the server certificate.

    c) A5TLSTrustedCertificatePath - Contains a path name to be used for walking the certificate chain. If this property is used, Individual certificates are stored in individual PEM files.

    d) A5TLSClientKeyFile, A5TLSClientCertificateFile - These properties are used to identify the file containing the Client private key and the client certificate for verification of the client. They are used together. As explained above, they are less commonly used.

    e) A5TLSCipherList - An optional list of ciphers to be passed to the server. This list establishes a limit on the ciphers that can be negotiated.

3. A new property IsSecurelyConnected will return true (.t.) if a connection for one of the drivers below confirms a secure connection. Note that ODBC drivers or Oracle TNS connections may in fact connect securely, but if Alpha Anywhere does not know this has happened, the value of IsSecurelyConnected may still return false (.f.).
 


TLS/SSL Support by Database Driver

MySQL

MariaDB

Oracle


 


PostgreSQL

 

SQL Server

 


Note: Install any certificate authority files as trusted certificates in the Windows store. The Microsoft SQL Server native client will find them there.


Connecting Securely to Amazon RDS Database Instances from Alpha Anywhere



Amazon RDS (Relational Database Service) currently includes the following databases: Aurora, MariaDB, MySQL, Oracle, PostgreSQL and SQL Server. In order to secure communication to these databases, Amazon generates a certificate for the database and instance that is presented by the server when a secure link is requested.

Alpha Anywhere ships a copy of the certificate authority files for Amazon and it is installed under the installation directory for Alpha Anywhere (and application servers) in a folder with the path <installation directory>\SQLDatabases\Certificates\Amazon RDS.

We recommend the following when attempting to communicate securely with an Amazon RDS instance:

 

 

 

UX Component - Caching - When a UX component makes an Ajax callback, the UX Component file (the .a5wcmp file) must first be de-serialized before the callback is handled. If the UX component is very large, de-serializing the file can be relatively slow and it imposes a significant 'tax' on every callback. Now, the first time the UX component file is de-serialized, it is cached. As a result, Ajax callbacks (in the case of large components) can be significantly faster.

This caching technique was first introduced in version 4.0, but was subsequently pulled in version 4.2 when it was found that under some circumstances, the caching logic was introducing errors.

Now, a much more robust caching technique has been developed and UX caching is again turned on by default.

If you notice any odd behavior in a UX that was previously working, you can turn caching off by creating this file (does not matter what's in the file):

c:\debug\nocaching2.txt

 

 

 

REDIS - Alpha Anywhere now has built-in support for REDIS. Redis is a very popular database for storing name/value pairs, working with queues and many other use cases. Alpha Anywhere ships with a local Redis database. Xbasic now has a Redis client object that allows you to interact with Redis databases. For more information on this feature, see the documentation.

 

http://www.alphasoftware.com/documentation/pages/Guides/Services/Redis/index.xml

 

PDF Printing - Amyuni Printer Driver - Multilingual Support - The default setting for the MultilingualSupport flag in the PDF Options dialog has been changed to true (checked). This was done because many users were reporting 'bugs' when then high order characters in their reports were not rendering correctly. The issue was they did not have the MultilingualSupport flag turned on.

If you are certain that your reports do no contain any high order characters and you are concerned about the size of the PDF files generated by the Amyuni printer driver, you can turn this flag off.

 

Xbasic Arrays - .Net data types - You can now dim Xbasic arrays using .Net types. This makes working with .Net assemblies from Xbasic easier to do.

 

For example:

dim myarr[10] as system::int32

For more information, see:

http://www.alphasoftware.com/documentation/pages/Guides/Dotnet Integration/Arrays/index.xml
 




Application Server - Performance - AEX Files - An option has been added to preload AEX files into memory on the first request for any code in the AEX file. The maximum size of the AEX file to load into memory can be set. The default behavior is to create a copy of the AEX in the user's temporary folder and load code from the temporary file. However, if any utility is run to clean up temporary files, it is possible this copy could be deleted causing a problem. This option does not impact performance and is only needed when cleanup programs are removing the temporary AEX file after the application server has started.

 



Grid Component - File Save Format - JSON - Grid Components can now be saved as formatted JSON instead of binary (the default). This option was added to UX components some time ago. Formatted JSON saves the properties in clear text. This is useful if you are using some type of source or version control system and the system has a method to show differences between versions. The save format can be selected in the Grid Properties under 'Advanced-> Save component format'.

The compiled file used to publish the Grid is still saved as binary as a binary file size is smaller.

You can do a bulk conversion of the storage format by selecting the 'Edit, Bulk Operation, Change Component storage type' menu option when the Web Control Panel has focus.


 

UX Component - FormView Control - Signature Editor - A new predefined Editor for use in an Editor Set has been added for capturing signatures.

 

Watch Video
Download Component

 

UX and Grid Components - Google Maps - API Key - Google has made a change to Google Maps and they now require you to specify an API key when using the Google Maps Javascript API. This release allows you to specify your API key. There are three different ways in which you can specify the API key - described below.

NOTE: To obtain your Google Maps you will need to visit the Google site. Do a Google search for 'Google Maps API key'. You will need an API key for Google Maps Javascript API.

You can specify the Google Maps API key as follows:

  1. When you add a Map control to a UX or Grid there is a new property called Google Maps API key where you can set the key for just the selected Map control
  2. You can open the Project Properties dialog when the Web Control Panel has focus and specify the API key in the Project Properties dialog. If you specify the API key here, it will apply to all Map controls (in both the UX and Grid) defined in the current project. It will not be necessary to specify the API key in the properties each Map control. However, if you do specify an API key at the individual Map control level, that key will be used in preference to the key specified in Project Properties.
  3. You can create a file called GoogleMapsAPIkey.txt in the executable folder of the Alpha Anywhere Development version that contains the API key. This key will be used for all Map controls in both UX and Grid components if you don't specify the key at the individual Map control level, or in the Project Properties.

NOTE: If your Developer version of Alpha Anywhere is installed in the "Program Files (x86)" folder you will need Administrator privileges in order to create the GoogleMapsAPIkey.txt  file.

 

UX Component - Client-side Events - onServerSideEventHandlerError - This event is fired when there is an error in some user defined Xbasic function that handles an AJAX callback.

 

UX Component - AudioPlayer, AudioRecorderPlayer, VideoPlayer, and VideoPlayerRecorder Controls - New methods - These controls all have these new methods:

 

 

In addition, the Audio controls also have .stop() method.

 

Example

var Obj = {dialog.object}.getControl('MYVIDEOPLAYER');

Obj.pause();

 

Bugs

AlphaDAO - MariaDB - Timestamp Fields - When retrieving timestamps with microseconds from MariaDB, the milliseconds part was not retrieved.

Notes:

  1. XBasic Time values (type 'T') do not store the full precision in microseconds, so only the most significant digits are retained.
  2. To retrieve a raw value including the microseconds use this  SQL expression: cast(<column> as char(50))
     

UX Component - Local Storage - Version Number - In the Local Storage section of the UX builder you can specify the version number of the Local Storage settings. If the version number is increased and the application is republished, then any existing data in Local Storage should not have been restored (because it was stored with a version number less than the current version number). The version number was not being honored and the data in Local Storage was being restored. Now, if the version number is increased, the existing data in Local Storage will NOT be restored.

 

UX Component - Numeric Fields - Client-side Formatting - Submitting Data  - If you have a numeric control that is formatted using client-side formatting rules (for example 123456.78 gets formatted as $123,456.78 ) when the data in this control was submitted, it was previously submitted in its formatted form. Now, the data are converted to an unformatted number. So in the case of this example, the data submitted to the sever would be 123456.78 and NOT $123,456.78.

The same comments here also apply to the {dialog.object}.getValue() method.

 

UX Component - List Control - Export to Excel - Fixed an issue where data was not exported correctly if the list had group breaks.

UX Component - Video Recorder Player Control - A bug was fixed. If you have an existing UX with this control you must edit the control properties and resave to regenerate the control with the fixed code.

Reporting - SQL Reports against tables with fieldnames longer than 32 characters caused a problem.

Temporary Folder - The system stores temporary files in special folders under the users folder such as in "C:\Users\<userName>\AppData\Local\Temp\AlphaAnywhere\p_1234". Under certain conditions, a cleanup utility could remove these folders and saving a temporary file would fail. Now saving any file to the temporary folder using an xbasic method will recreate the folder if it has been deleted.

UX Component - List Control - Auto-fetch more Mode - When pagination was turned on for a List, and the pagination method was set to 'AutoFetchMore' - the Ajax callbacks that were firing to fetch additional records were firing too early.

 

Tips

UX Component - List Control - Right to Left - When creating a List control for a right-to-left language (e.g. Hebrew, Arabic), you typically want:

To achieve this:

  1. Set the Control flow direction property on the UX properties page to rtl.
  2. Edit the List and check  the Reverse column order property on the List Properties pane.
  3. If the List uses a column layout, go to the Layout tab and add this to the in-line style for the header and the data: text-align: right; direction:rtl;
  4. To change the position of the sort icons, edit the Local sub-themes definitions - Javascript property and paste in this code:

    {
        "listbox": {
            "base": {
            "columnLayout": {
                "header": {
                    "item": {
                        "order": {
                                    "style": "position: absolute; left: 25px; top: 50%; margin-                                top: -5px; display: none;"
                                   }
                            }
                        }
                }
            }
        }
    }
  5. To change the language for the List column headers, wrap the heading text in either language or text dictionary tags. E.g. <a5:r>..</a5:r> or <a5:t>..</a5:t>. Use the Internationalization Helper Utilities... on the More dropdown menu when you are editing the UX layout.
  6. To right align the text in group headers (or footers), open the Group breaks definition dialog and add an additional class (say 'rtl') to the class name for the header or footer. For example: {dialog.style}ListTitle rtl
     
  7. Define the rtl class in the UX Local CSS definitions property as:

    .rtl {direction: rtl;}



     

UX Component - Text Area - Scrolling - iOS - If you have a text area control in a Panel Card and you have more text in the control than can be seen, drag scrolling on the text in the text area control will not allow you to scroll the text.

You can however enable two-finger drag scrolling on the text by defining a local CSS class as shown below and then setting the text area class to this class.

 

.scrollTextBox {
    overflow-y: scroll;
    -webkit-overflow-scrolling: touch;
}

 

 

UX Component - Changing the Background Image of a Panel at Run-time - When you add a Panel Card to a UX component, you can specify a background image for the Panel Card. In some situations you might want to dynamically change the background image for the Panel Card. For example, you might want to use one image when the device is in portrait mode and another when in landscape mode. The following Javascript code shows how you can do this

 

//get the id of the 'body' part of the Panel Card

var id = {dialog.ob ject}.panelGetId('PANELCARD_1','body');

//set the background image to 'image2'
$(id).style.backgroundImage = 'url("image2.png")'
 

 

 

Alpha Anywhere V4.2  -Build 3670-4684 13-Jun-2016

Videos

UX Component - List Control Tutorial - Building a PhoneGap Application to Capture Images and Audios while Disconnected from the Network A common requirement when building mobile applications is to capture data that includes photos and audio recordings. The application must work while offline and then be able to synchronize the data and the media files (photos, audios, videos) when a connection is available. In order to implement this application it is necessary to use PhoneGap.

Note: Because PhoneGap is used the, data that are captured includes the filenames of pictures, rather than the base64 data for each picture. As a result many more images can be captured while the device is offline than would be possible if images were captured as base64 encoded data.

In this video we show how a UX component with a List/Detail View is configured to capture data and media files and then sync with a server.

Watch Video - Part 1 - Configuring the Data Source
Watch Video - Part 2 - Configuring the List control and its associated Detail View
Watch Video - Part 3 - Configuring the List control and its associated Detail View
Watch Video - Part 4 - Configuring the List control and its associated Detail View
Watch Video - Part 5 - Configuring the List control and its associated Detail View
Watch Video - Part 6 - Running the app on a Device (Note: This is a large video file. It will take some time to download)

Download Component
(Note: See the component's 'PhoneGapDefaultSettings' property for a list of plugins that the PhoneGap app should use)

Date added: 2016-06-05
Reports HTML-Paged Output Option When you render reports in a Web application you can choose whether the report should be rendered as PDF or HTML. The HTML option is only available for Layout Table reports - not Freeform reports.

The HTML-Paged option will work with all report types -- Freeform and Layout Table and can be rendered in any browser (including mobile device browsers that do not have the ability to render PDF files.

This video contrasts the different report output options.

Watch Video

Date added: 2016-06-10
UX Component - ViewBox Control Dynamically Setting Data Displayed in the ViewBox The ViewBox control is often used as a very light weight alternative to the List control when all you need is a scrollable list of data and not the full functionality of a List.

When used as an alternative to the List, a common pattern is to populate the data shown in the ViewBox dynamically, based on some search criteria entered by the user.

In this video we show two different techniques for doing this.

Watch Video - Part 1
Watch Video - Part 2

Download Component
Date added: 2016-06-10

 

Features

UX Component - Video Recording - PhoneGap Applications - It is now possible to add video recording to your PhoneGap applications. Video recording will work in disconnected application. You can record as many videos as you want, and then when you sync you data with the server, the video files can be uploaded to the server. In this respect, syncing video files is identical to the way pictures and audio recordings are synced when the user has an internet connection.

When you sync data on your mobile device you can specify that media files (pictures, audio recordings and videos) should be uploaded to Amazon S3, rather than the Alpha server. Since media files can be quite large, uploading media files to S3 is often preferable to uploading these files to an Alpha server.

To support video recording a playback, two new UX controls are available:

The Video Player control is used when you only want to allow users to play back previously created video files. The Video Recorder/Player control will allow playback of previously created videos and recording of new videos.

To add a Video Player or Video Recorder/Player control to your UX component select the [More...] option in the list of Data Controls.

 

 

Both the Video Player and Video Recorder/Player controls are standard 'data controls'. This means that they have .setValue() and .getValue() methods, like all other data controls.

The .setValue() method is used to set the control to the URL of a video file.

The .getValue() method is used to read the current value of the control.

For example, in a PhoneGap application, after you end a video recording, if you called the .getValue() method for the control, the filename of the video that had just been recorded would be returned.

 

You can also convert the type of an existing control to a Video Player or Video Recorder/Player control by clicking on the smart field in the Control type prompt.

 

 

In the image below, the Video Player control is shown. Since the Player does not support recording, the control is not limited to applications that are running under PhoneGap.

The VCR buttons allow you to start, pause and resume playback. The fast forward and back buttons behave as follows:

The double sided arrow icon at the right edge will allow you to switch into full screen mode.

 

 

The control also shows a progress indicator and how long the video has been playing

 

The appearance and behavior of the Video Recorder/Player control is essentially the same as the Video Player control, except that the Recorder/Player control include a button to switch from Playback mode to record mode:

 

 

Configuring the Video Recorder/Player and Video Player Controls

To configure the Video controls, click the smart field for the Control Properties property.

 

 

The Properties dialog for the Video Recorder/Player controls is shown below.

You can set the maximum allowed length (in seconds) of the video and you can specify code for the various events that the control fires.

 

 

How to Configure a PhoneGap Application To Support Video Recording/Playback

 

Let's assume you want to build a PhoneGap application that will allow users to enter/edit data and record videos. The application must work offline and when a connection is available the data must be synced to a SQL database on the server and the videos must be uploaded to S3.

This tutorial will highlight the key configuration settings you will need to make as you build the UX component.

Let's assume that the underlying schema of the table in which data must be stored is as follows

If the videos are being uploaded to Amazon S3 when data are synced, the videofilename field will contain values like:

http://alphamediacapture.s3.amazonaws.com/video1.MOV

On the other hand, if the video are being uploaded to the Alpha server, the videofilename field will contain values like:

videofiles/video1.MOV

(assuming that the video files are uploaded to a folder called 'videofiles' in the Webroot).

 

Step1 - Create a UX control with a List/Detail view showing data from the SQL table. You can use the List Control Quick Setup genie to quickly create the List/Detail view.

 

 

Step 2 - Configure the fields in the List. After you have created the List you must edit the List and on the Fields tab, set the control type of the videoFilename field to Video.

In addition, if the video files are going to be uploaded to the Alpha server (as opposed to Amazon S3) you will also need to specify the folder on the Alpha server where the video files should be stored. To do this, click the smart field for the Video capture and storage properties.

 

 

The Video Capture Properties dialog is shown below. The Upload folder is where you specify the folder name.

For example, if you specify:

myVideos

The videos will be stored in a folder called myVideos that is relative to the Webroot. It is recommended that you specify a folder that is relative to the webroot. This will allow you to upload videos from the server to the device for storage in the device's file system so that videos are available for playback on your device even when you have no internet connection.

 

 

In addition to specifying the Upload folder you should also specify the Stored filename transformation expression. This property defines what gets stored in the videofilename field in the database.  The builder for this property allows you to use 2 special placeholders: <Filename> - the fully qualified video filename, and <ShortFileName> - the name of the video file with no drive and path information.

You will typically want to store a filename that is relative to the Webroot. For example, if the Upload folder was set to myVideos then you should set this property to:

"myVideos/<shortFileName>"

 

With this setting, the actual data stored in the vidoefilename field in the database will look something like this

myVideos/video1.MOV

 

NOTE: If your videos are being uploaded to Amazon S3, it is not necessary to specify Video Capture Properties.

 

Step 3 - Specify if media files (pictures, audios and videos) should be uploaded to the Alpha server or Amazon S3 when data are synced.

To do this, edit the List properties and go to the Detail View tab. Then click the smart field for the Media files (photos, videos, audio recordings, other) settings property.

 

 

 

This dialog will allow you to specify if media files are uploaded to the Alpha server or to Amazon S3.

The dialog will also allow you to specify if media files should be downloaded to the device when data are loaded into the List control. If you download media files to the device the media files are stored in the file system on the device and will be available even when there is no connection.

 

Step 4 - Set the control type for the videoFilename control in the List's Detail View to a Video Recorder/Player control. When the List Quick Setup Genie created the List's Detail View, it set the control type of the videoFilename field to a textbox. To change the control type to a Video Recorder/Player, click the Control type smart field and select the Video Recorder/Player control.

 

 

Having configured the List control and its Detail View, you are now ready to build your PhoneGap application.

TIP: To see a list of PhoneGap plugins that you should enable when you build your PhoneGap application, download the sample component using the link shown below and then examine the setting in the component's PhoneGap default settings property.

Download Component

 

 

Grid, UX and Tabbed UI Component - Reports - HTML-Paged Output Option - A new option (HTML-Paged) is available for how reports should be rendered in web applications.

When you use Action Javascript to display a report, or you add a Report to a Tabbed UI, or you embed a report into a UX component, the output options are now:

 


Watch Video

 

The PDF Option

The PDF option will render the report as a PDF file using the bundled Amyuni PDF printer driver. The PDF file will then be displayed in your browser (in a window in the component, a tab pane in the Tabbed UI or in a div on the current page). The manner in which the PDF will be displayed depends on the browser you are using. For example, if you are using IE, the Adobe Acrobat PDF viewer is used as IE does not have a built-in ability to render PDF files. Chrome and Firefox, on the other hand, have a built in ability to render PDF files, so the Acrobat reader is not used.

Unfortunately, the situation on mobile devices is more complicated because on many mobile devices there is no option to render PDF files in a browser.

When you choose the PDF option, the resulting report is properly paginated and is ready for printing, should the user want to print the displayed report.

The PDF option works with both type of Alpha Anywhere reports: Freeform and Layout Table.

 

The HTML Option

The HTML option will render the report as HTML. This option does not use the Amyuni PDF printer driver. However, this option is only available for Layout Table reports. The advantage of Layout Table reports over Freeform reports is that they render much more quickly than Freeform reports, and they can be exported to Excel with very high fidelity (because the cells in the Layout Table report can be directly mapped to cells in the Excel spreadsheet). The HTML produced by this option is not paginated. The report does not render any Page Headers, Page Footers, or page breaks defined in the report. When the HTML is printed, the page breaks are controlled by the printer -- i.e. a new page is started when the current page is full.

 

The HTML-Paged Option

The new HTML-Paged output option can be used for both Freeform and Layout Table reports. This output option does not use the Amyuni printer driver, but unlike the HTML option, the report is properly paginated and all Page Header, Footers and breaks defined in the report are honored. When the output from the HTML-Paged report is printed, the printout is properly paginated -- just like the output from the PDF option.

Since the output from HTML-Paged option is pure HTML (technically it is HTML with embedded SVG), no special plugins or viewers are needed by the browser. This means that the reports will render in all mobile browsers (unlike the PDF output option).

When you display a report in your web application the uses the HTML-Paged output option, the display window has buttons that allow you to create a PDF version of the report, to print the HTML, to export to Word, or to export to text.

Another benefit of the HTML-Paged output option is the way image with an Alpha channel (images with transparent backgrounds) are rendered. The HTML-Paged option will render these images correctly, while the PDF option (which uses the Amyuni printer driver) will not render these images correctly.

 

Bugs

A5ws_SaveValidateUser() Function - A bug was introduced in build 3633 that broke the A5ws_SaveValidateUser() function.

Grid Component - Export to Excel - Computed Fields - If a computed field in the SQL SELECT statement for the grid contained a colon in the field expression, the field was not exported to Excel.

 

 

 

Alpha Anywhere V4.12  -Build 3633-4676 26-May-2016

Bugs

UX Component - Panel Navigator - A bug was introduced in build 3629 that resulted in a child Panel not displaying correctly after a command that set focus to the child Panel without animation.

UX Component - Slider Control - Show/Hide - If a slider control had the message area turned on, when the control was hidden using a client-side show/hide expression, the message area was not hidden.

UX Component - Slider Control - Set Value -  If a slider control had the message area turned on, when the value in the control was set using the .setValue() method, the slider message was not updated. The message was only updated when you dragged on the slider.

Application Server - Performance - Made a change to the algorithm used to reduce priority on busy threads.

 

 

Alpha Anywhere V4.12  -Build 3629-4676 25-May-2016

Videos

UX Component - PhoneGap Sending Push Notifications using the Pushwoosh Service A common feature in mobile applications is push notifications. In a PhoneGap application, this can be be done, utilizing the Pushwoosh plugin, which integrates the Pushwoosh service.

This video shows an example application that uses push notifications.

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3


Documentation - PhoneGap Push Notifications

Date added: 2016-04-28
UX Component - FormView Control Specifying Display Formats for Numbers and Dates You can specify display formats for numbers and date values that are displayed in the FormView control.

Watch Video

Date added: 2016-05-22

 

Features

Font-Awesome - Version 4.6.3 - Updated to a new version of Font-Awesome. In order to see new icons in Working Preview when using Internet Explorer you will need to install the new font. To do this, open Windows Explorer and navigate to the cssIcons\font-awesome\fonts folder and double click on the the .ttf file.

PhoneGap App Builder - PhoneGap Version -  Added support for PhoneGap 6.1.0 which is now supported by PhoneGap Build.

PhoneGap App Builder - Third Party Plugins (Android, iOS) - Secure Local Storage For Cordova. Added support for the nl-afas-cordova-plugin-securelocalstorage plugin. This plugin stores local data encypted using the iOS Keychain or the Android keystore. The data is NOT stored to the webview localstorage resource. It is stored in the keychain of the keystore.

For the full nl-afas-cordova-plugin-securelocalstorage plugin documentation, see nl-afas-cordova-plugin-securelocalstorage

UX Component - FormView Control - Display Format for Numeric and Date Values - You can now specify a display format property for fields displayed in the FormView. This allows you to apply formatting directives to number and date values.

Watch Video

 

 

 

PhoneGap - Android - Build Tool - A new option has been added to the PhoneGap Builder that allows you to specify the Android build tool to be used by PhoneGap Build when creating Android apps. The default setting is gradle, which is required by many of the newer plugins. If you run into any issues when building Android apps using older plugins, you can set the Android build tool to ant, which was used in older versions of PhoneGap.

 

 

 

Web Security - Action Scripting  - You can now completely customize the messages used by security action scripting in a UX component.  The Action scripting genie shows a list of messages used by the action and information about the conditions that will show the message.  You can also use language tags (<a5:r>..</a5:r> ) to translate the messages into different languages.
 

UX Component - List Control - Export - Select Columns to Export - A new option has been added to the 'Export List data to Excel/Ascii' action to allow selection of the List columns to export.

To export only selected List columns you must first specify settings for the 'Customize field sizes and column headings in export file' property and then ton the 'Only export columns for which customize options are defined' property.

 

 

PhoneGap App Builder - Generate App Zip File - A new option has been added to the PhoneGap Builder to create a zip file that contains all of the files and assets required to build an iOS, Android or Windows Phone app on PhoneGap Build.

The use case for this option is that in some organizations, access to the API that Alpha Anywhere uses to communicate with the PhoneGap build service is blocked and therefore, in order to build a PhoneGap project it is necessary to visit the PhoneGap site in a browser and then upload a .zip file from the user interface presented by the browser.

When you select this option, you can specify the folder location to allow easy access to the file. The zip file is named with the app name specified in the PhoneGap Builder.
 

The zip file can be uploaded directly to https://build.phonegap.com to update an existing project or to create a new project on PhoneGap Build. The ability to easily upload the app zip file is helpful when the development machine is located behind a secure firewall that does not allow access through to PhoneGap Build through the PhoneGap Build API which is used by the Alpha Anywhere PhoneGap App Builder.

 

Bugs

UX and Grid Component - Javascript Functions - Hang when Saving Component - if you had done a fresh install of Build 3603 (rather than install the Build 3603 update over an existing build), the node.exe program file was not installed in the executable folder as it should have been. (If you ran the update, to update an existing build, node.exe was already installed in the executable folder and so you would not have been affected by this issue).

When a component that contains Javascript is saved, Alpha Anywhere automatically validates the Javascript syntax. To do this is uses a node.js module. However, if node.exe was not present in the executable folder, Alpha Anywhere would hang. This is now fixed and the installers (both full and update) will install the required 32 bit version of node.exe in the executable folder.

Printing - Windows 10 - Under some circumstances, only on Windows 10, requesting 2 copies of a report would print 4 copies.

UX/List Control - Grid Component - Dynamic Images - SVG Icons - Fixed several issues when the Dynamic Image control referenced SVG Icons.

UX Component Crash - An error was introduced in the previous build that, under certain circumstances, would cause a UX to crash. The pattern for the error message shown when the crash occurs was:

wfNew.<some variable name> = wfOrig.<some variable name>

 

Alpha Anywhere V4.12  -Build 3603-4668 13-May-2016

Features

UX Component - List Control - Export - Select Columns to Export - A new option has been added to the 'Export List data to Excel/Ascii' action to allow selection of the List columns to export.

To export only selected List columns you must first specify settings for the 'Customize field sizes and column headings in export file' property and then ton the 'Only export columns for which customize options are defined' property.

 

 

PhoneGap App Builder - Generate App Zip File - A new option has been added to the PhoneGap Builder to create a zip file that contains all of the files and assets required to build an iOS, Android or Windows Phone app on PhoneGap Build.

The use case for this option is that in some organizations, access to the API that Alpha Anywhere uses to communicate with the PhoneGap build service is blocked and therefore, in order to build a PhoneGap project it is necessary to visit the PhoneGap site in a browser and then upload a .zip file from the user interface presented by the browser.

When you select this option, you can specify the folder location to allow easy access to the file. The zip file is named with the app name specified in the PhoneGap Builder.
 

The zip file can be uploaded directly to https://build.phonegap.com to update an existing project or to create a new project on PhoneGap Build. The ability to easily upload the app zip file is helpful when the development machine is located behind a secure firewall that does not allow access through to PhoneGap Build through the PhoneGap Build API which is used by the Alpha Anywhere PhoneGap App Builder.

 

Bugs
 

UX Component Crash - An error was introduced in the previous build that, under certain circumstances, would cause a UX to crash. The pattern for the error message shown when the crash occurs was:

wfNew.<some variable name> = wfOrig.<some variable name>

 

Alpha Anywhere V4.11  - Build 3596-4665 10-May-2016

Features

SVG Icons - Slow Loading - If you defined a large number of SVG icons in a component, the component was slow to load.

 

Bugs

Security Framework - A recent change in a security function broke the security show /hide on legacy components built in early versions of Alpha Anywhere and previous Alpha versions.  A workaround was to use the bulk update process to Update component security settings and republishing.  It is now not necessary to use the workaround.
 

 

 

Alpha Anywhere V4.1  - Build 3583-4662 03-May-2016

UX Component - List Control Search Highlighting When you perform a server-side search to filter records in a List you can highlight the matching characters in each record. This makes it easy to see why the record was included in the search result.

Watch Video

Date added: 2016-04-24
SVG Icons Introduction to SVG Icons SVG Icons have many benefits over bitmap images and font icons. In this video we introduce you to SVG icons and show how they can be used in your components.

Watch Video

Date added: 2016-05-01
SVG Icons Search the Web for SVG Icons and Importing into Components There are a large number of free SVG icons available for download on the web. In this video we show how you can download SVG files from a site that specializes in SVG images and then import the SVG files for use in your components.

Watch Video

Date added: 2016-05-01
SVG Icons Converting Locally Defined SVG Icons to Linked SVG Files SVG icons can either be defined within a component, or they can be stored in physical files that are linked by your components. The advantage of using linked files is that  many components can share the same SVG icon definitions. In this video we show how you can easily convert locally defined SVG into a file of SVG icons that can then by linked by many components.

Watch Video

Date added: 2016-05-01
SVG Icons Using SVG Icons in a List Control on a UX Component A common pattern in mobile applications is to use a List control as the menu for the application. It is common to use icons in the menu List. In this video we show how SVG icons can be used in these menu Lists.

Watch Video

Date added: 2016-05-01
UX Component - PhoneGap Sending Push Notifications using the Pushwoosh Service A common feature in mobile applications is push notifications. In a PhoneGap application, this can be be done, utilizing the Pushwoosh plugin, which integrates the Pushwoosh service.

This video shows an example application that uses push notifications.

Watch Video - Part 1
Watch Video - Part 2


Documentation - PhoneGap Push Notifications

Date added: 2016-04-28
     

 

Features

 

 

SVG Icons - The Grid, UX and TabbedUI components now support SVG icons.

 

Introduction to SVG Icons -  Video

 

SVG icons have several very important advantages over traditional bitmap icons. Namely:

While the same advantages are also true of font icons, which Alpha Anywhere has supported for some time now, SVG icons are easier to work with than font icons.

An additional benefit of SVG icons over font icons is the ability to support colored icons. With a font icon you can specify a color for the entire icon - but not for different aspects of the icon. In other words, a font icon is always green, red, yellow, or whatever color you specify. Whereas an SVG icon can be mostly green, red, yellow, or whatever color you specify for the 'fill' and 'stroke' color, but certain parts of the icon can be hard-coded as a particular color.

There are a large number of freely available SVG icons on the web. A particularly good source of free SVG icons is http://www.flaticon.com/

 

In the screen shot below, two different icon sets are shown in the SVG Image picker. These icons were imported from icon sets on www.flaticon.com. As the image shows, the second icon set is richly colored.

 

 

 

 

In this next screenshot the icons are shown at a much larger size. As you can see, the icons scale smoothly.

 

 

 

 

There are two ways to use SVG icons in a component:

To use locally defined SVG, you set the Local SVG definitions property in the CSS/SVG section in the component builder. To use linked SVG files you set the SVG Linked files property in the CSS/SVG section in the component builder.

 

 

Locally Defined SVG

When you open the builder for Local SCG definitions you get a screen where you can enter the SVG definitions. For example:

 

 

As you can see, the SVG definition looks quite formidable, but this is largely irrelevant because the SVG will, in almost all cases, be generated by importing SVG files that you have downloaded, or will have been created by an SVG authoring tool that you use.

 

 

How to Import SVG Files

 

Watch Video

 

Once you have found a source of SVG icons on the web that you want to use in your components, you will need to import the SVG. To import SVG files:

  1. Open the builder for  Local SVG definitions
  2. Click the Import folder of SVG files hyperlink
  3. Specify the name of folder where the SVG files that you downloaded are stored
  4. Specify an icon prefix name. This name will be used as the prefix for each SVG icon in the SVG Icon Selector.

After you import the SVG into the builder, you might want to manually edit the SVG. The most common type of edit you might want to perform on the imported SVG is to change the fill and stroke color on the SVG icons. Click the Understanding SVG Icon colors hyperlink for more information on this subject.

 

Converting Locally Defined SVG to Linked SVG

 

Watch Video

 

After you have imported SVG files into Local SVG definitions, you might want to convert the SVG that is locally defined, into a SVG file that is linked. The main reason for doing this is so that other components can use the same SVG icon definitions.

To do this, click the Convert to Linked SVG hyperlink on the dialog while you are editing the local SVG definitions..

 

Syntax for Specifying an SVG Icon

When you use a SVG icon in a component (for example as the image on a button, or in a List control, or as the image to display in a Dynamic Image control), you use a special syntax (generated automatically by the image picker). For example:

svgIcon=#svg3_safebox:52 {fill: red}

 

This syntax is very similar to the syntax used for CSS font icons. For example:

cssIcon=fa fa-heart fa-2x

 

In the case of the SVG icon, the prefix is 'svgIcon' and in the case of the CSS font icon, the prefix is 'cssIcon'

In the above example, the SVG icon is being displayed with a size of 52px and a fill color of red. The icon name being displayed is 'svg3_safebox'. Notice that the icon name is prefixed with a hash character.

 

 

Printing Ink Annotation over a Picture in a Report - a5_composite_picture_and_ink() Function -

If your database has picture fields and ink fields that were used to annotate pictures you might want to print a picture field with the ink annotation shown directly over the picture.

This is done by creating a calculated field that uses the special a5_composite_picture_and_ink() function.

This function takes the name of the field that contains the picture, the name of the field that contains the ink and (optionally) a base path. The base path is only needed if the picture field contains relative a relative filename. The base path is used to convert the relative image filename into an absolute filename.

a5_composite_picture_and_ink(c pictureFieldName, c inkFieldName [, c basePath])

For example, assume that your database has fields called picture1 and annotation1 and you want to print the ink in annotation1 over the picture in picture1. You could create a calculated field called compositeImage, defined as shown below, and then add this calculated field to your report.

compositeImage = a5_composite_picture_and_ink("picture1","annotation1")

 

 

 

 

PhoneGap - UX Component Template - Secure Login With Location Tracking And Pushwoosh Notifications -  This new UX component template is a mini-app that is designed to introduce developers to the power of using native push notifications with Alpha Anywhere and the Pushwoosh service.



The app offers user login and location check in and check out for a mobile worker. When the user logs in or out, an admin user is sent a push notification that includes the user name and the date and time the user logged in or out of the app. When the user checks in or out of a location, a marker is placed on a map, the lat/lon is reverse geocoded with the Google Geo-location API to determine the exact address and a push notification is sent to the admin user. The admin user is identified in a Pushwoosh filter called Admin. This allows the admin user to receive push notifications to track all activity within the app.

For a video overview of this component template, click the link below.
Video overview of the Secure Login With Location Tracking And Pushwoosh Notifications

To view the help documentation click the link below.
PhoneGap Push Notifications

 

 

UX Component - List Control - Search Highlighting - When you perform a server-side search on the records in a List control (using the 'Filter records in a List' action in Action Javascript), or you apply a filter from a List's Search Part (either server-side or client-side) you can now highlight the characters in each record that were matched by the search. This makes it easy to see why a particular record was included in the search result.

Watch Video

 

For example, in the image shown below, the table were searched for all records that contain the string 'manager' in the 'Contacttitle' field.



To turn on search highlighting, edit the List and check the Search highlight property, as shown in the image below. You will then be able to set the class name and in-line style to apply to the highlight characters.

 

 

 

UX Component - AudioPlayer and AudioRecordAndPlayer Controls - Events - Added event hooks to these controls.

 

 

 

Action Javascript - PhoneGap - File System Actions - A new action is now available in Action Javascript. The PhoneGap - File System Actions (Fire URI Based) is similar to the  PhoneGap - File System Actions action in that they both allow actions such as read file, write file, create directory, delete directory, read directory, etc.. The key difference is the the File URI Based actions give you explicit control over which part of the device's file system the operations are performed in.

The PhoneGap - File System Actions  actions operate on files in a default location, whereas the PhoneGap - File System Actions (Fire URI Based) actions allow to specify an explicit file location.

 

 

 

SQLite Database  - Indexes - PhoneGap - When you use Action Javascript to construct a SQLite database you can now specify that indexes should be build for each table in your SQLite database. You can add as many indexes as you want. For each index you can define the columns used in the index.

Sending E-mail Using the SparkPost Service - email_send_SparkPost() Function - You can now use an Xbasic helper function to send e-mail using the SparkPost service. This service is similar to the Mandrill service. You must first go to sparkpost.com to get an API key. You will also be required to verify your ownership of you sending domain.

Once you have your API key and you have verified your domain ownership you can send e-mail in much the same way that you may have used the email_send_mandrill() function.

NOTE: Currently the email_send_sparkPost() function does not expose the ability to use merge variables in the HTML message. If you need this functionality, you must compose the message JSON manually. Refer to the SparkPost documentation.

 

Syntax

p Result = email_send_sparkpost( c key, A message)

 

Where

 

Example:

 

dim ms as p
ms.send_to = "john@acme.com:Optional friendly name for John Smith,sally@acme.com"
ms.from_email = "sendername@acme.com"
ms.from_name = "Sales at Acme" 'friendly name - optional
ms.subject = "Information You Requested"
ms.message_html = "Here is the <b>information</b> you requested."
ms.message_text = "Plain text version of the message"
ms.attachments = "c:\alphasports\invoice.pdf,c:\alphasports\vendorlist.pdf"
dim key as c = "your sparkpostkey"
pp = email_send_SparkPost(key,ms)

 

 

You can optionally define attachments using an array syntax. Instead of defining a property called ms.attachments which has a comma delimited list of files to attach, you can define an array as shown in the example below::

 

dim ms.attachmentsArray[1] as p
ms.attachmentsArray[1].name="report.pdf"
ms.attachmentsArray[1].type=resolve_mime_type("pdf")

ms.attachmentsArray[1].content=base64encode(file.to_blob("c:\myfiles\invoice.pdf"))
 

 

In the body of your HTML message you can optionally include in-line images. To define in-line images you can either use a property that specifies a comma-delimited list of image filenames, or you can use an array syntax:

 

Array syntax:

dim ms.inlineImagesArray[1] as p
ms.inlineImagesArray[1].name = "myimage1.jpeg"
ms.inlineImagesArray[1].type = resolve_mime_type("jpg")
ms.inlineImagesArray[1].content = base64encode(file.to_blob("C:\Images\4296.JPG"))
 

Comma delimited filenames syntax:

 

ms.inlineImages = "c:\movieImages\4296.jpg|myimage1.jpeg"

 

Notice that the comma delimited names syntax specifies the image name (the name by which you will refer to the image in the HTML body) with a | delimiter. In the above example, the image name is 'myimage1.jpeg'

 

To use the in-line images in the HTML message body, you use this syntax:


Here is your inline image!<br><img src="cid:myimage1.jpeg">

 

Signature Control - Reports - PDF - If you print a report that contains a signature control bitmap image using the Amyuni PDF printer driver, the bitmap previously showed up with a black background. This is due to a bug in the Amyuni Printer Driver which does not properly render transparent image backgrounds.

Now, Alpha Anywhere will automatically convert the transparent background on the image to white. If you want an explicit background color, then set the image fill style to 'solid' and pick the background color you want to use. The transparent background on the image will be converted to the specified color.

 

PhoneGap - Custom Window onerror Event Handlers - By default, the Alpha Anywhere Javascript libraries add window.onerror handlers to certain functions in the Alpha Anywhere libraries. This can interfere with any window.onerror event handlers that you might want to add to your code.

You can now prevent Alpha Anywhere from adding system window.onerror event handlers by adding the following code to the client-side onRenderComplete event.

{dialog.object}.customWindowErrorEvents = true;

Bugs

Grid Component - Search - 'Is blank' and 'Is not blank' - Were generating SQL statements that used the Length() function rather than the StringLength() function (which is the portable SQL function for string length).

Application Server - Xbasic Error Log - A change was made in how thread usage is calculated in the Application Server to reduce false thread error messages which could occur under rare conditions.

 

 

 

Alpha Anywhere V4.01  - Build 3550-4650 18-Apr-2016

Videos

UX Component - Map Control Adding Multiple Markers to a Map - Customizing the Marker Icon for Each Marker Using Action Javascript, it is easy to add multiple marker to a map control on the UX. However, in some cases you might want to use a different icon for each marker. In many cases the decision as to what icon to use for a particular marker should be based on some data about the marker.

In this video we show how the marker icons used for markers on a map can be dynamically specified.

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

Date added: 2016-04-15

Features

UX Component - Map Control - Action Javascript - Adding multiple markers to a map - Customizing the marker icons - When you add multiple markers to a map you can now dynamically set the icon used for each marker based on data in the Data Series for each marker. You can also use image sequences.

 

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

 

To customize the marker icons, click the smart field for the Marker icon property, shown below.

 

 

This will bring up a dialog that offers three different methods for specifying the marker icons:

 

 

 

UX Component - Calendar Control and Date Picker - Disabled Days - When configuring the Calendar control or the Date Picker you can now explicitly disable certain dates.

 

 

 

You can either explicitly specify certain dates to disable (or call a Javascript function that returns an array of explicit date values), or you can specify more general Javascript code that gets called before each date value is drawn to determine if the date is disabled or not. For example to disable every December 25th date (regardless of year), you could specify the following Javascript:

 

Note: The Javascript is referencing a variable called 'd' -- the date value of the entry being rendered.

if(d.getMonth() == 11 && d.getDate() == 25) return true; //month is 0 based

return false;

 

You can also set the disabled dates programmatically (using Javascript) after the calendar has been rendered. For example:

 

 

//create an array of disabled dates

var disabledDates = [];

disabledDates.push('12/25/2016');

disabledDates.push('12/26/2016');

 

//get a pointer to the calendar control

var obj = {dialog.object}.getControl('MYCALENDAR1');

 

//set the calendar's disabledDates.dates property
obj.datePicker.disabledDates.dates = disabledDates;

 

//refresh the control
obj.refresh();

 

Bugs

AlphaDAO - MySQL - Commands out of sync Error - If you executed code that returned a resultset from MySQL, but did not read all of the rows in the resultset before executing a new SQL command you would get a 'Commands out of sync' error from MySQL. This is now fixed.
 

AlphaDAO - SQL::Resultset - .NextResult() Method -- Under some circumstances, when there was no next result set, would return an Xbasic error, rather than .f..

 

AlphaDAO - Oracle - CLOB Fields - Fixed an issue with Oracle CLOB fields if the data in the field contained high order characters.

UX Component - List Control - Search Part - Keyword Searches - Keyword searches now honor the search type setting for individual character fields. This means that if you had set the search type for a field to (say) '12' -- a case in-sensitive 'contains' search -- and you preformed a keyword search that included this field, the field search would be performed using search type of '12'.

Grid Component - Row Expander and Linked Content Section - Fixed an issue if the child component was a UX or Custom Component.

Grid Component - Excel Import - Under some circumstances empty data in the Excel file did not import correctly.

Forms - Desktop Applications - Button Labels - A bug was introduced in the previous build the caused button labels on forms to not display correctly if the button text included the & character.

Application Server - Session Variables - Null Values -- A bug was introduced in the previous build that prevented a session variable from being set to a null value if it had previously been set to a non-null value.

UX Component - Default Value - Page Variables - If you set the default value of a variable to an expression that used the PageVariable prefix, the expression did not evaluate. For example:

 

=PageVariable.var1

This bug was introduced in build 3522-4647. However, an easy work around is to change the default value expression to:

=request.variables.var1

 

 

 

Alpha Anywhere V4.0  - Build 3522-4647 05-Apr-2016

 

Videos

UX Component PhoneGap - Storing Large Amounts of Data for Off-line Use in Files on a Device When you build an application for disconnected usage, the data you want to have available while you are disconnected is stored in List controls in the UX which are persisted to Local Storage on the device. Local Storage is, however, limited in size. In some cases your application will need to have a large amount of read-only data available (such as price lists, etc.) and instead of storing this information in Local Storage you would like to store the data in files in the file system of the device.

If your application is a PhoneGap application, then you can store large amounts of data in files on the device as shown in this video tutorial.

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3
Watch Video - Part 4
Watch Video - Part 5
Watch Video - Part 6
Watch Video - Part 7
Watch Video - Part 8
Watch Video - Part 9

Download Component

Date added: 2015-08-01
UX Component PhoneGap Shell Building and testing PhoneGap applications can be tedious because every time you want to test a change to your application you have to submit the application to the PhoneGap build service and then load the app onto your device for testing.

This process can be dramatically shortened by building a PhoneGap shell application and then testing your application inside the shell. Every time you make a change to the component you are working on, you no longer have to submit it to PhoneGap build - you simply click the refresh button inside the shell, where the component is running.

In this video we show how you can easily build a PhoneGap shell component.

Watch Video - Part 1
Watch Video - Part 2

Date added: 2015-08-01
UX Component PhoneGap - Using the Image Picker Plugin To Select Multiple Images from the Photo Library The List control allows you to use the camera on a mobile device to take a picture and then when the List data are synchronized, upload the picture to a server (such as Amazon S3 or the AlphaAnywhere server) and store the picture filename in the database. However, there are situations where you want to capture multiple pictures and adding one record at a time to a List and then using the camera to get the image for each record would be tedious. It would be preferable to be able to open the Image Library (i.e. the Photo Roll) on the device and select as many images as you want. Each selected image would add a new row to a List control.

This video shows how the PhoneGap Image Picker plugin can be used to do this.

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

Date added: 2015-08-09
UX Component Setting the Height of an Object to 100% Setting the height of to 100% might seem like a natural thing to want to do, but in reality it is complicated because while it is clear what you MEAN by this, the HTML layout engine may not know what the height of the containing element is. or put more accurately, when the the element you want to size at 100% height is initially rendered, its container may not have been properly sized yet.

This is especially true with Panels which need to be resized after initial render so that they fit the device.

Fortunately, Panels have an onSize event that exposes a height property, which you can use to set the absolute height of an element so that it fills a Panel, as shown in this video.

Watch Video
Download Component

Date added: 2015-08-25
UX Component Building 'Real-time' Applications Using Web-Sockets In a typical web-application the client makes a request to the server and the server responds. The server cannot send information to any client unless the client first requests it. However, in 'real-time' applications the server maintains a connection to the client and there is a two way channel for sending and receiving messages. When the server, or any of the connected clients, sends a message, the message is broadcast to all of the connected clients and an event will be triggered on each client when a message is received. The event handler can choose to handle the message, or to ignore it.

A common pattern (which is discouraged because it does not scale) is to user timer events on a Grid or UX to make periodic callbacks to the server to see if there is any 'new information' that is of interest to the client. Real-time applications built on web-sockets are much more efficient than the pattern of executing Ajax callbacks on a timer.

This video demonstrates how a real-time application can be built. The video demonstrates a chat application where any client can post a message that is instantly seen by all of the other clients.


Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

Download Component

Date added: 2015-09-03

(Requires build 4540 or above)
UX Component Client-side Data Cache The client-side data cache allows you to retrieve data from the server. Once the data has been loaded into the data cache, you can use the data  in your UX component. The data in the client-side data cache can be persisted (either to Local Storage or to the file system in a PhoneGap application) so that the data is available even when you no longer have a connection.

The client-side data cache is particularly useful in PhoneGap applications that are designed for disconnected usage because you can store a large amount of data on the device and have this data available to your application.

In this video we show how the client-side data cache is set up and we demonstrate how it persists data to Local Storage and to the file system in a PhoneGap application.


Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3
Watch Video - Part 4
Watch Video - Part 5
Watch Video - Part 6


Download Component

Date added: 2015-09-05

(Requires build 4541 or above)
UX Component Map Control - Adding Multiple Markers to a Map using Client-side Data Action Javascript has a method (in Map Control Actions) to add multiple markers to a map. However, this action assumes that you will be making an Ajax callback to the server to do a query to get the list of latitude/longitude values for each marker you want to add to the map. But what if you already have a list of data on the client-side with latitude/longitude values? Making an Ajax callback to the server under these circumstances is unnecessary.

In this video we show how a List control, which has latitude/longitude values for each row, can be used as the data source for the markers and how a marker for each row in the List can be added to the map without having to make an Ajax callback.

Watch Video
Download Component

Date added: 2015-09-10
Xbasic Calling into Node.JS from Xbasic - Node Services Defined at the Project Level You can define global Node services (i.e. services that can be called from any application on your server), or you can define Node services at the individual project level. Node services defined at the project level get 'published' like any other components, or pages in your application when you publish your applications.

In this video we show how you can define and consume Node services in a web project.

Watch Video - Part 1
Watch Video - Part 2
Download Component

Date added: 2015-09-12
UX and Grid Component Using OData Data Sources OData is a standard method of access data using a REST api. Alpha Anyhwere allows you to easily consume data from OData services.

In this video we show how a connection string is defined to connect to an OData service and then how a Grid component is built to go against the OData service.


Watch Video - Part 1
Watch Video - Part 2

In the next video we show how a UX component with a List can be built using the OData data source:
Watch Video - Part 3


Date added: 2015-09-12
UX Component Finding Controls in a Large UX Component When editing a UX component with a large number of controls, finding the control that you want to edit can be difficult. The Quick Find genie makes it very easy to locate the control that you want to edit.


Watch Video

Date added: 2015-10-07
Xbasic Validating and Reformatting JSON Data Xbasic has many functions that make working with JSON data easy. Two particularly useful functions are json_validate() and json_reformat(). These functions are described in this video.

Watch Video

Date added: 2015-10-22
UX Component - List Control Converting a List that uses a Static Data Source to a SQL Data Source and Vice-Versa It is common when building a UX component that uses List controls to start off with Lists that are based on static data (because setting up a List to use static data is so easy). Once you have your UX working, you might then want to convert the List to be based on a SQL database. A genie allows you to easily export the data from your static data source to a new table in a SQL database, or to link your List to an existing table in a SQL database.

You can also easily convert a List that uses a SQL data source to a static data source by importing the data from the SQL table.

Watch Video

Date added: 2015-11-04
UX Component - List Control Opening a Pop-up Window with a Button in a List Row - Positioning the Window Relative to the Button When you create pop-up windows in a UX control, a common pattern is to open the window positioned relatively to the button that displays the window. If the button is in a row of a List control, then it is a little trickier to position the window relative to the the button that was clicked.

This video shows how you can position a dropdown window relative to a button in a List row.

Watch Video - Part 1
Watch Video - Part 2

Date added: 2015-11-09
UX Component - List Control Dynamically Changing Page Size of a Paginated List at Run-time In this video we show how you can dynamically change the page size of a paginated List that is based on SQL data.

Watch Video
Download Component


Date added: 2015-12-29
UX Component Executing Client-side Validation Rules Programmatically When you define validation rules for controls on a UX, the rules are evaluated when the UX is submitted. However, there may be cases where you want to explicitly (programmatically) evaluate the validation rules for a set of controls.

For example, you might not want to allow the user to go to a different Panel Card if there are validation errors on the current Panel Card.

In this video we show how you can programmatically execute the client-side validation rules for a series of controls.

Watch Video
Download Component

Date added: 2015-12-30
UX Component - List Control Displaying Hierarchical Data in a List A common requirement in many mobile applications is to display cascading data in a List control (such as a list of menu choices). Some of the items in the List will have sub-choices. When an item in the List that has sub-choices is selected, the List is repopulated with the sub-choices and a 'back' button is enabled to go back to the previous level.
There is no limit as to how deep this hierarchy of nested Lists can be. Typically, when an item in the List that has no sub-choices is selected, an action associated with that List item is executed.

In this video we show how you can build a UX component that uses a List to display an hierarchical menu system. We show how a genie can help you generate the JSON data for the hierarchical menu system and how the List's 'Quick Setup Genie' can be used to configure the List to display the nested Lists defined by the List's JSON data.


Watch Video - Introduction
Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

Watch Video - Showing Animation for List Transitions


Date added: 2016-01-04
UX Component - List Control Displaying Hierarchical Data From a SQL Table in a List In the 'Displaying Hierarchical Data in a List' video we show how hierarchical data can be displayed in a List. In that example the data shown in the List is defined statically. In this video we show how the data hierarchical data for the List can be retrieved from a SQL table.

The video shows a List with Country names. When the user selects a Country, the List is repopulated showing the Cities in the selected Country and a 'back' button is enabled. When the user selects a City, the Contacts in that City are shown.

Watch Video
Download Component

Addendum:
In this next sample component the Xbasic commands that are executed to get the JSON data are replaced with a built-in helper function. When the user clicks on a List 'endpoint', the selected record is shown and can be edited.

Download Component

Date added: 2016-01-05
UX Component Structure Explorer When you are working with a complex UX component that has many different Panel Layouts, Navigators and Cards as well as many Window containers and Panel Overlays, it can be difficult to get a sense of the component's underlying 'structure'.

In this video we show how the Structure Explorer can help in getting an overview of how a UX component is structured.
 
Watch Video

Date added: 2016-01-05
UX Component Client-side Data Cache - Populating Dropdown Boxes From the Client-side Data Cache - PhoneGap In a PhoneGap application, if your UX contains Dropdownbox controls, the choices shown in the Dropdownbox controls will be defined at design time (when the PhoneGap application is built).

However, in your application you might want the choices in the Dropdownbox controls to be defined at run-time. Your app should make a callback to the server to get current data for the Dropdownbox controls and then persist that data locally so that the next time the app is loaded it already has the data for the Dropdownbox controls. The client-side data cache is ideal for this scenario.

In this video we show how you can define client-side data cache items for the data to populate Dropdownbox controls.

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

Download Component

Date added: 2016-01-12
UX Component - PanelOverlay PanelOverlay Windows The UX component allows you to display PanelOverlays that 'float' on top of a Panel. By showing and hiding the PanelOverlay you can make the PanelOverlay behave much like a 'window'.

In this video we show how the 'PanelOverlay is window' property is used to turn a PanelOverlay into a window that is initially hidden and shown on demand by executing the 'PanelOverlay window show' action in Action Javascript.

Watch Video
Download Component

Date added: 2016-01-13
UX Component - Custom Controls Understanding CustomControls The UX Component allows you to define two types of CustomControls - data bound and non-data bound. In both cases the HTML and Javascript for the custom control can either be specified at design-time, or (much more powerfully) generated by Xbasic at run-time.

In this video we introduce the CustomControl found in the 'Other Controls' category of the UX Builder (as opposed to the 'CustomControl' found in the 'Data Controls' category).

After introducing the basic concepts of the CustomControl, the video shows how a UX form can be dynamically generated at runtime from a definition that could be read from a database.


Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3
Watch Video - Part 4
Watch Video - Part 5
Watch Video - Part 6
Watch Video - Part 7

Download Component

Date added: 2016-01-19
TabbedUI Component Keyboard Shortcuts The TabbedUI component is a great way for navigating to the different components that make up an application. You can assign keyboard shortcuts to the different buttons in the TabbedUI that launch components.

Launching a component using a keyboard shortcut can be more efficient than having to visually locate the button in the TabbedUI and then click on it.

In this video we show how to assign a keyboard shortcut to a button in the TabbedUI.

Watch Video

Date added: 2016-01-21
Xbasic Calling SOAP Web Services from Xbasic You can register SOAP web services at the Web Projects Control Panel and then call methods of these services from your Xbasic code.

In this video we show how to register a SOAP service and then call methods of the service.


Watch Video

Date added: 2016-01-21
Grid Component Using IN clause in SQL Statement and Argument Arrays Argument arrays, in combination with the SQL IN clause are a powerful way to define what records the Grid should show.

In this video we show how you can use argument arrays to define a button on a UX that opens a Grid showing a selected list of records.

Watch Video
Download Component

Date added: 2016-02-10
Xbasic Working with MongoDB using AlphaDAO Alpha Anywhere allows you to connect to a vast array of SQL databases and then build Grid and UX components against the SQL data. You can also use Xbasic (specifically the AlphaDAO object) to write code that executes SQL commands.

You can work with a Mongo database in the same way.

In this video we show how you can create an AlphaDAO connection string that points to a Mongo instance - how you can export data from a SQL database to a Mongo database - and how you can build a Grid component against a Mongo database.

NOTE: These videos show how the Mongo database is accesses using standard AlphaDAO objects. Alpha Anywhere also provides an API to access Mongo directly.


Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

Required build: 4612

Date added: 2016-02-10
UX Component Understanding Custom Settings The UX allows you to define Custom Settings - a list of named setting values. These custom settings can be referenced in Javascript code and also when the component is initially rendered.

Custom Settings are a powerful tool for dynamically configuring certain aspects of a UX component.

In this video we introduce the concept of Custom Settings and show some of they ways they can be used.

Watch Video - Part 1
Watch Video - Part 2
Download Component

Required build: 4614
Date added: 2016-02-14
UX Component - List Control Pull-past-end to Refresh List Data A common pattern in mobile applications is to allow a user to refresh the data in a List by pulling down on the List past the top of the List and if the user pulls down past some threshold value, to trigger a List refresh once the user releases the List, and it bounces back to its initial position.

In this video we show how you can implement the 'pull-past-end-to-refresh' pattern in a List control.


Watch Video

Required build: 4620

Date added: 2016-02-20
PhoneGap Including Pre-populated SQLite Database Files in a PhoneGap Project The UX component has extensive support for working with SQLite databases in PhoneGap applications. A common requirement when building PhoneGap applications is to include pre-populated SQLite database files as part of your PhoneGap project. These pre-populated database files can contain large amounts of data. Since they are part of the PhoneGap project, the data in these database files will be immediately available to your application when it is loaded, even if there is no connection.

In this video we show how the PhoneGap Builder allows you to define the pre-populated SQLite database files to include in your PhoneGap project.


Watch Video 1
Watch Video 2

Required build: 4625

Date added: 2016-02-27
UX Component Using SQLite in a UX Component in a PhoneGap Project Action Javascript has actions that make it easy to work with a SQLite database on a mobile device.

In this video we demonstrate various actions that can be performed with the Action Javascript SQLite action.

Watch Video 1
Watch Video 2
Watch Video 3
Watch Video 4

Required build: 4626

Date added: 2016-02-28
Publishing Web Applications Using the HTTP Method for Publishing Web Applications When you publish a web application to a remote server, you can choose whether to use FTP or HTTP to do the actually work of transferring the files. The HTTP option has more options than the FTP option, but has some additional setup that is required.

In this video we show how to configure a server to allow HTTP publishing and how to create a Publishing Profile in the Alpha Anywhere IDE that uses HTTP Publishing.

Watch Video - Configuring the Server
Watch Video - Defining a Publishing Profile

Date added: 2016-03-02
UX Component Vertically Centering Content in a Panel Card A common pattern in mobile applications built using Panels it to vertically center some content in a Panel Card. The content should be vertically centered regardless of the device orientation or size.

In this video we show how this is easily done with some Javascript in the Panel Card's onSize event.

Watch Video
Download Component

Date added: 2016-03-04
UX Component Using SQLite to Store a Large Database of Records with Images for Use in an Off-line Application In a PhoneGap application, being able to use SQLite on the device allows you to store a large amount of information on the device that will be available when the device is offline. A common requirement is for the data that is stored in the SQLite database to contain images.

In this video we should how you can build a UX component that makes a callback to the Alpha Anywhere server to create a SQLite database of 500 records, with each record having an associated image. The SQLite database is then download to the device and stored on the device. The a SQL query is executed against the on-device SQLite database and a List control is populated showing all of the records and their associated image.

Watch Video - Part 1
Watch Video - Part 2
Download Component

Date added: 2016-03-08
UX Component PhoneGap - iOS Background Geolocation This video shows how to use the 3rd party iOS Background Geolocation PhoneGap plugin.

Watch Video

Date added: 2016-03-11
UX Component PhoneGap - Local Authentication for iOS with the Fingerprint Scanner This video shows how to use the 3rd party Local Authentication for iOS with the Fingerprint Scanner PhoneGap plugin.

Watch Video

Date added: 2016-03-11
UX Component - ViewBox Control Introduction to Basic Concepts This video demonstrates basic concepts of the ViewBox control such as the a5-item attribute and the a5-value attribute and shows how events are attached to the ViewBox and how parts of the ViewBox can be made 'selectable'.

Watch Video
Download Component

Date added: 2016-03-13
UX Component - ViewBox Control ViewBox HTML Rendered by Merging Data into a Template The HTML that the ViewBox displays can be generated dynamically by merging data into an HTML template.

Watch Video
Download Component


Date added: 2016-03-13
UX Component - ViewBox Control ViewBox HTML Rendered by Merging Data Array into a Template The data that is merged into the ViewBox Template can be an array of objects. In this video we show how the template is expanded by iterating over all of the objects in the data array and how the resulting HTML can be formatted to look and behave like a simple List control.

Watch Video
Download Component

Date added: 2016-03-15
UX Component - ViewBox Control Making a ViewBox Behave Like a Simple List Control A common use case for a ViewBox control is to implement a simple List control. In cases where you don't need the full richness of a List control, but you only want to create a scrollable list of items, the ViewBox represents a simpler option.

In this video we show how the special ListRowContainer control can be used to make a simple List using the ViewBox.

Watch Video
Download Component

Date added: 2016-03-15
UX Component - ViewBox Control Sample ViewBox Walkthrough - Star Rating Example In this video we do a behind-the-scenes walkthrough on the sample 'star rating' ViewBox Control.

Watch Video - Part 1
Watch Video - Part 2

Date added: 2016-03-15
UX Component - ViewBox Control Sample ViewBox Walkthrough - iOS Login Example In this video we do a behind-the-scenes walkthrough on the sample 'iOS Login' ViewBox Control.

Watch Video - Part 1
Watch Video - Part 2

Date added: 2016-03-15
UX Component - ViewBox Control Understanding the Concept of 'Selectable' Elements in a ViewBox One of the key concepts of the ViewBox control is that elements in the HTML rendered by the ViewBox control can be 'selectable'.

In this video we explain this concept by taking a complex ViewBox layout that does not have any selectable elements and making portions of the ViewBox HTML selectable.

Watch Video
Download Component

Date added: 2016-03-15
UX Component - ViewBox Control Understanding the ViewBox State Object The ViewBox has a 'state' object and the values in the state object can be used in the ViewBox template.

In this video we show how the template can reference values in the ViewBox state and how the ViewBox's .setState() method allows you to set properties in the ViewBox state object.


Watch Video
Download Component

Date added: 2016-03-16
UX Component Add-in Controls The UX Builder allows you to define add-in data bound controls. These are control that are defined externally and are available in the uX Builder just like any of the built-in controls.

Watch Video - Part 1
Watch Video - Part 2

Date added: 2016-03-15
UX Component - List Control Dynamically Populating a List Columns and Data - Generic SQL Table Viewer The List control on a UX is one of the most versatile controls in Alpha Anywhere. To demonstrate its versatility this video shows a sample UX component that can be used to view the data in any table in a SQL database. The UX has a dropdownbox where the user can select the table in a SQL database and then a callback is made to the server to dynamically populate the List with the data from the table.

In addition the UX contains a search part where the user can specify filter criteria to filter the data in the table.

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

Download Component

Date added: 2016-03-18
Xbasic Using Output Arguments when Calling a Stored Procedure When you call a stored procedure from Xbasic, the stored procedure might return values (in addition to resultsets). The calling Xbasic code can read these return values by using 'output' arguments.

In this video we show how input/output and output arguments are defined and used when calling a stored procedure.

Watch Video - Part 1
Watch Video - Part 2

Date added: 2016-03-18
UX Component - List Control Audio Recording/Playback in a UX Component It is quite common to build mobile applications that work in disconnected mode and allow the user to capture images using the phone's camera. You can also build mobile applications that allow users to record and playback audio files.

NOTE: To record audio, you must be using PhoneGap.

In this video we show how a List with a Detail View can be used in a UX component that is running as a PhoneGap application to capture audio files for each new record that is added to the List. The application that we show can work in disconnected mode and allows the user to record many audio files while disconnected. When a connection is obtained and the data that was captured while disconnected is synchronized, the audio files can first be uploaded to a server (such as Amazon S3).

The component relies on the AudioRecorderAndPlayer control in the UX component.


Watch Video - Part 1
Watch Video - Part 2

Date added: 2016-03-26
Style Builder Style Builder In Alpha Anywhere V4 the Style Builder has been rewritten. You can now easily adjust the entire appearance of a style by simply adjusting the SASS variables that control the style colors and you can also easily add new sub-themes for different control types.

In this video we show how you create a new style for buttons and we also show how the entire style can be c hanged from a 'blue' color to a 'green' color.

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

Date added: 2016-03-26
UX Component - Ink Control Introduction to the Ink Control The Ink control allows you to create and edit 'ink' data.

In this video we give a very brief introduction to the Ink control.

Watch Video - Part 1
Watch Video - Part 2

Date added: 2015-08-13
UX Component - Ink Control Setting the Background Image for the Ink Control You can set the background image shown in the ink control to anything you want - either by specifying the URL of an image, or the base 64 encoded data for an image.

In this video we show how you can set the background to an image and also to a map this is generated by Google Maps.

Watch Video

Date added: 2016-01-21
UX Component - ViewBox Control ViewBox Control - In Depth Tutorial This video is an in-depth tutorial on how the ViewBox control can be used to build a 'star rating' control.

A common pattern in many applications is to allow a user to rate something by clicking on the number of stars. For example, the control might display 5 stars, all of which are grey. The user will then click on the 4th star to rate something as '4 stars'. The first four stars will then change color and the 5th star will remain greyed out.

This type of control can easily be built using the ViewBox control, as shown in this video.

NOTE: A 'star rating' control is actually a built-in control type (select the [More...] tool in the UX toolbox) so it is not necessary to go through the steps shown in this tutorial every time you want to add a star rating control to a component. The video is mean simply as in introduction to key concepts of the ViewBox control.


Watch Video - Part 1
Watch Video - Part 2

In depth discussion of how the control is built.
Watch Video - Part 3
Watch Video - Part 4
Watch Video - Part 5
Watch Video - Part 6
Watch Video - Part 7
Watch Video - Part 8

Download Component
Date added: 2015-09-04
UX Component - FormView Control Using the MobileForms_StarterExample Quick Start Template When you create a new UX component that will use the FormView control to create a mobile optimized form, the sample 'MobileForms_StarterExample' template is a convenient starting point.

In this video we give a quick overview of the features of this sample template.

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

Date added: 2016-04-02

Features

 

FormView Control - Starter Example - When you create a new UX component  you can use the MobileForms_StarterExample as a quick start to create a basic UX component with a List control (the form's data source), a FormView control and a set of Editors (for editing values in the form).

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

 

To use the template select 'MobileForms_StarterExample' from the dialog shown below.

 

 

FormView Control - The FormView control (together with Editor Sets and Editors and the List View control) are the fundamental building blocks for building touch optimized mobile forms.

For more information on the FornView control click here.

 

Ink Control - A new type of data bound control can be added to a UX Component. The ink control allows users to 'draw' (using a finger or stylus on a device that supports touch events) or with a mouse (on a desktop browser). The ink is captures using a special text format.

Watch Video - Part 1
Watch Video - Part 2

 

Overview

The ink control, shown in the image below, is made up of two main parts, the editor and the view.

 

 

The editor (bottom part -- this is where the user draws) allows the user to edit the ink while the view (top part) provides the ability to navigate to the part of the page where the ink is being drawn. For example, the 'page' that contains the ink might be a standard 8.5 x 11 inch page.  In ink editor (bottom part) only shows a small part of the page. The view (top part) contains a dragable zoom-box (see the dotted red rectangle) showing the portion of the ink visible in the editor. The editor and view can be laid out in three ways.

The first is a split layout. In this layout the editor and the view share the ink controls layout area in either a horizontal or vertical layout. It should be noted that a split layout can still optionally show only the view or editor. This is useful if you are targeting multiple screen sizes, as you can use responsive layout Javascript to change the split layout on smaller screens to toggle between the editor and view if there isn't space for both. You can also use this to allow the user to toggle the editor to take up the entire ink control on larger screens as well.

The second layout is a detached view layout. In this layout the editor takes up the entire ink control area, while the view part is injected into an element specified by an ID. This allows for extremely customized layouts.

The last layout is an editor layout. This will display only the editor. This is useful for ink editing that doesn't need navigation, such as signature capture.

Ink data is stored in a string format, with the strokes stored as vectors. Below is an example of some ink data.

 

#A5Ink
version 1.0
settings %json%
{"page":{"width":5,"height":3,"unit":"in","dpu":300,"lines":false,"background":{"image":false,"color":""}},"meta":{"bounds":{"l":57,"t":35,"r":1393,"b":571},"created":"2015-09-12 05:12:15 pm","modified":"2015-09-12 05:29:42 pm"}}
%json%
A pen 3 #000
S 120,228,CAC+D+E+F+G+I+J+M+M+TaTaR+UaQcRdQcTeOePcMfJcGcFcEdDcEdAdBcAcAdBd+e+c+e+caebcbebedddekhfcfbgbgbfahahajal+m+-29+p+lBiBkAhBfAfBdAdCcAcC+CCAFCHCKCMBUDQBOBPBN+NAJ+MAI+J+H+H+IaIcHbIbGbEcDbCbCc+d+cAc+cAdDdCdCcBcBcBcBcE+D+D+DADCEAEBDBCBBCCEACDEAECFAF+FAFAG+E+F+EbHbDaDbEaC.........

 

This keeps the file size down and allows for the ink to be rendered at any resolution. The boundaries of the ink page are defined by the ink page settings. The page settings include width and height in a specified unit (in, px, etc.). This data is combined with the dots-per-unit (dpu) to create the ink page. The width and height are multiplied by the dpu to get the base page size in "ink units". The dpu can be thought of like "dpi" in printing. The higher the dpu, the higher the ink resolution.

The goal is to get the dpu relative to the units so that when the editor is at a scale of '1 ink unit equals 1px', the user is encouraged to enter ink at a larger scale than if they where writing on a sheet of paper. This works around the inherent lack of accuracy in capacitive touch screens (ink can only be captured at screen pixel accuracy), and allows for readable written input.

If the ink page unit is 'inches' then the dpu should be at least be 300. All measurements inside of the ink (pen width, margins, etc.) are in 'ink units' derived from the dpu.

The page can also store background (color and image) settings, and have automatically generated lines to create graph and ruled paper look.

The editor and view parts of the ink control can each have an overlay. The overlay is arbitrary HTML that will be laid out over each part. Elements in the HTML can make use of the "a5-item" attribute in order to easily add buttons to the ink control. There are a number of predefined "items" that allow the user to access the eraser tool, pan tool, undo and redo actions, and navigate the ink. Custom "items" allow you to add unique behaviors to elements in the overlay. The events on the "items" have direct access to the ink control.

The ink editor uses tools to edit the ink. The default tool in the pen tool. Other tools can be selected using the ink control's .setTool() method. This method can specify whether the tool is "sticky" or not. If a tool is not "sticky" then after a single user interaction with the tool, the tool will be deselected, and the ink editor will go back to the pen tool. Each tool has an optional "active class name" that will be applied to the ink control when that tool is active. This allows you, though CSS, to automatically highlight the elements in the overlay, and possibly change visibility of elements as well.

 

 

 

AudioPlayer Control - The AudioPlayer control allows you to add a control to the UX to play audio files.

To add a new AudioPlayer control to the UX component, select the [More...] entry in the controls toolbox (in the 'Data Controls' section) and then select the 'AudioPlayer' control.

NOTE: A separate Audio Recorder/Player control is also available. This control can only record in a PhoneGap application.

 

 

This will insert a control into the UX that looks like this:

To customize the AudioPlayer control, click the smart field for the Control properties.

 

 

 

 

Since the AudioPlayer is a data bound control, it has a {dialog.object}.setValue() and a {dialog.object}.getValue() method.

To set the audio file that you want to play back you use the {dialog.object}.setValue() method

For example:

{dialog.object}.setValue('MYAUDIOCONTROL','stream:http://audio.wgbh.org:8004');

 

In this case the AudioPlayer value is being set to a 'stream' - (a continuous audio stream) rather than a file.

After the stream is ready to play, the AudioPlayer appearance will change to this;

While the stream is loading (i.e. before it is ready to play), the text 'Stream', shown in the above image, will say 'Loading...'.

All of the text messages shown in the control are customizable in the AudioPlayer Control properties. 

 

In this next example, the AudioPlayer value is set to a file URL:

{dialog.object}.setValue('MYAUDIOCONTROL','http://s3.amazonaws.com/alphaVideos/theway.mp3');

 

In the case where the AudioPlayer value is set to an audio file (not a stream), its appearance will change as follows once the audio file is ready to play:

 

 

When the user taps the Play button, the audio starts to play back. The number on the right side indicates the duration of the audio file. Before playback starts, or when playback is paused, the fast forward and fast reverse buttons (on either side of the Play button) will skip to the beginning or end of the audio clip (if you tap on them). However, if you press and hold, they will rewind or fast forward in 2 second steps.

 

The top bar shows the progress as the audio file is being played. The number on the right hand side shows the duration of the audio file. The number on the left hand side shows how much of the audio file has been played. The buttons on each side of the Play button allows you to skip forward and back in the file.

 

 

NOTE: The AudioPlayer control cannot play audio files that are hosted on the Alpha Anywhere server. It can play files that are hosted on Amazon S3, or, in the case of a PhoneGap application, files that are stored in the file system on the device.

 

 

AudioRecorderAndPlayer Control - The AudioRecorderAndPlayer control allows you to add a control to the UX component to play audio files and to record audio files.

NOTE: A separate AudioPlayer control is also available. This control is for playback only and is not limited to PhoneGap applications.

To add a new AudioRecorderAndPlayer control to the UX, select the [More...] entry in the controls toolbox (in the 'Data Controls' section) and then select the 'AudioRecorderAndPlayer' control.

 

The AudioRecorderAndPlayer controls is a dual purpose control. It can be used to play audio files (or streams) and it can also be used to record audio files.

You can only record audio files if you are using PhoneGap.

When you build your PhoneGap application you must must ensure that the Media plugin has not been selected:

and that the Media With Compression plugin has been selected.

In addition, you are likely to need to upload the captured audio files to a server so the following PhoneGap plugins should also be loaded: Device, File, File transfer.

 

When you add an AudioRecorderAndPlayer control to your UX you customize the control properties by clickin the smart field for the Control properties.

The customization genie allows you to set customize text and also set the maximum recording duration (in seconds).

 

When the component is run, the AudioRecorderAndPlayer control will look like this (if not audio file has been loaded for playback):

 

The red circle button will put the control into record mode. When the control is in record mode, it will appear as follows:

 

The Done button (text on this button is customizable -- you can use language, or text dictionary tags for International applications- <a5:r> or <a5:t>) becomes enabled. This button indicates that you want to end the recording. The record button changes to a Pause button. You can use this button to pause the recording.

The horizontal line at the top of the control indicates the recording level. The color of the line will be orange, green or red to indicate if the recording level is too low, ok or too high.

The number on the right indicates the duration of the recording.

If you set the value of the control to an audio stream or an audio file ( using the {dialog.object}.setValue() method ),  the control's appearance will change as shown below.

The control is now in 'Player' mode. The play button in the center of the control will start playback. The small record button at the left of the control will allow you to switch the control from 'Player' mode to 'Record' mode.

 

Audio Files - List Control - Detail View - The List control now supports the 'Audio' control type in the 'Fields' pane of the List Builder, as shown in the image below. The purpose of setting a field type to 'Audio' is to designate the field as a 'media' field for synchronization purposes (as explained below).

 

Watch Video - Part 1
Watch Video - Part 2

 

 

 

The 'Audio' control type is intended to address a very specific use case. Consider the following scenario:

  1. You have built a mobile application that runs in PhoneGap
  2. You have used the AudioRecorderAndPlayer control to record audio files in your application. When an audio file is recorded, the audio file is stored in the file system on the mobile device and the filename of the audio file is stored in the List control
  3. When you sync the List control to save any edits that were made, you want to upload the audio files from the device to a server (either Amazon S3, or the Alpha Anywhere server) and then store the edits that made in the List data to the SQL database that backs the List.

When you sync the List, Alpha Anywhere looks in all of the 'media' fields in the List looking for local filenames. These files are then uploaded to the target server and the data in the List are then changed to reflect the filename of the file on the remote server before the data are submitted to the server to update the SQL database. The following example will help make this point clearer.

Assume that you have a List with these fields:

name, audioFile

 

The user adds a new row to the List and records an audio. The data in the List will look something like this:

name: John Smith

audioFile: file://folderNameOnTheMobileDevice/filenameOfAudiofile.m4a

 

When the user hits the sync button to push the edits made to the List back to server so that the data can be added to the SQL database that backs the List, Alpha Anywhere first scans the data in all 'media' files to find any references to local file system filenames.

If the control type of the audioFile fieldname was set to Audio in the List builder, the audioFile field is considered a 'media' field. Alpha Anywhere will detect that the data in the audioFile field is a local file and it will first upload this file to the target server. Assuming that the target server is Amazon S3, the URL of the file once it has been uploaded to S3 might be something like: https://your_bucket_name.s3.amazonaws.com/audiofile1.m4a

Next, before sending the data in the List back to the Alpha Anywhere server (where the data will be written to the SQL database), the data in the List is changed so that the media fields are set to the URL of the files on the remote server. So, in our example, the data in the List is changed to this:

name: John Smith

audioFile: https://your_bucket_name.s3.amazonaws.com/audiofile1.m4a

 

The data are then sent to the Alpha Anywhere server and the value that is stored in the SQL database for the audioFile field is https://your_bucket_name.s3.amazonaws.com/audiofile1.m4a and not file://folderNameOnTheMobileDevice/filenameOfAudiofile.m4a (which of course would be a meaningless value to store in the database!) 

 

NOTE: It is recommended that you set Amazon S3 as the target for media file uploads as the AudioPlayer cannot play audio files that are hosted on an Alpha Anywhere server. To set the upload target go to the 'Media and Other Linked Files (PhoneGap Applications Only) property on the 'Detail View' tab in the List Builder.

 

 

 

 

PhoneGap - FileTransfer - Upload and Download - SSL Server - If you are testing a PhoneGap application with a server that is using SSL with a self-signed certificate, all PhoneGap file transfer functions will fail.

You can set a global flag to tell the PhoneGap file transfer function to trust all host. When you set this flag to true, you will be able to test PhoneGap file transfer functions even though your server might be using a self-signed certificate.

To set the flag, you could add this code to the client-side onRenderComplete event:

{dialog.Object}._phoneGapTrustAllHosts = true;

 

PhoneGap App Builder - Config.xml File Format - Updated - PhoneGap Build has deprecated the 'gap:' prefix previously used within the project's config.xml file. While the 'gap:" prefix is still officially supported, the recent PhoneGap Build documentation suggests that the prefix should be dropped. This change affects the splash, icon, platform and qualifier tags. All new PhoneGap project config.xml files will no longer include the 'gap:' tag. All previously defined config.xml files will be automatically updated and the 'gap:' prefix will be removed once the PhoneGap project is saved.

PhoneGap App Builder - Launch Images / Splash Screens - Android Only - PhoneGap Build now requires a default launch image /splash screen called 'splash.png' for Android apps. You must include the core SplashScreen plugin as well. The SplashScreen plugin is now automatically enabled if you choose to build an Android app. The config.xml file now includes the required splash tag as well.

PhoneGap App Builder - App Icons / Splash Screens - Windows 8.1 -  PhoneGap Build now supports Windows 8.1. The appropriately sized icons and launch images / splash screens have been added to the config.xml file and will be automatically generated, should you choose to generate the images files for icons and splash screens when building a Windows 8 mobile app. Please keep in mind that you should always check the sizing on each launch image / splash screen prior to publishing your app to any of the app stores. While the PhoneGap Builder does its best to size the images in the X axis, the Y axis may be larger than the expected size because of the numerous varying aspect ratios that the properly sized images require.

UX Component - Control Flow Direction - Right-to-Left Languages - A new property in the UX builder allows you to set the control flow direction.

 

The default is left-to-right (ltr). You can also select right-to-left, as shown in the image below.

 

 

 

Web-sockets Server - Redis - A new option has been added to the Web-sockets server to use Redis to store the messages that are sent and to handle the distribution of messages to the connected Node.js server(s)

To turn on this option, go to the Web Project Properties dialog (accessible from the Web Control Panel) and select the option as shown in the image below.

A copy of Redis is automatically installed with Alpha Anywhere. You need to ensure that the Redis server has been started before you run a component that uses the web-sockets server.

You can start a local copy of the Redis server, or you can point to a remote copy by specifying the Redis host property in the dialog.

To start a local copy of Redis you can either start Redis manually, or install Redis as a service.

To start Redis manually, navigate to the Alpha Anywhere executable folder from the command window and then type:

Redis-server

 

For information on how to install Redis as a service, see:

http://stackoverflow.com/questions/26213403/install-redis-as-windows-service

 

If you are using a load balancer to distribute load to multiple Alpha Anywhere servers, then you should turn on the Redis option.

 

 

The benefit of using Reds in your web-sockets configuration is that the solution is more robust. If the Node.js server is restarted for any reason, the message queue is not lost. In addition, Redis enables web-sockets applications if you are running multiple instances of the Alpha Anywhere server that are managed by a load balancer.

 

 

 

 

registry.sys_get() Method - 64 Bit Registry Entries - A new option has been added to the registry.sys_get() method to specify where you search for a registry value.

The second parameter passed to the method can be '32', '64' or 'Any'. 'Any' is the default option. With the 'Any' option, the method will first search the 32 bit registry and then if no match was found, it will search the 64 bit registry.

 

Examples:


? registry.sys_get("HKEY_LOCAL_MACHINE\SOFTWARE\MongoDB\Server\3.0\Edition")
= "MongoDB 3.0 2008R2Plus SSL (64 bit)"
 

? registry.sys_get("HKEY_LOCAL_MACHINE\SOFTWARE\MongoDB\Server\3.0\Edition","32")
= ""
 

? registry.sys_get("HKEY_LOCAL_MACHINE\SOFTWARE\MongoDB\Server\3.0\Edition","64")
= "MongoDB 3.0 2008R2Plus SSL (64 bit)"

? registry.sys_get("HKEY_LOCAL_MACHINE\SOFTWARE\MongoDB\Server\3.0\Edition","Any")
= "MongoDB 3.0 2008R2Plus SSL (64 bit)"

 

 

UX Component - Add-in Controls -- The UX Component now supports  'add-in' controls. Addin controls are defined by entries in the 'uxCustomControls' folder in the executable folder.

Watch Video

 

To add an add-in control to your UX component, click the [More...] item in the UX toolbox.

 

 

This will bring up a dialog showing the existing Add-in controls:

 

 

To define a new Add-in control add a new folder to the uxCustomControls folder in the executable folder.

The name of the folder defines the name of the add-in control. Inside the sub-folder there should be three files

 

For examples of how to define the contents of these three files, please refer to any of the sample controls that are shipped with Alpha Anywhere.

 

Here is an example of how the IntegerValue control looks:

This control is used for a field that only allow integer values and the value can be set by clicking buttons to increment/decrement the integer value.

 

UX Component - Data Controls - Custom Control - Data Bound Custom Controls are a powerful new technique for creating custom controls on a UX component.

NOTE: Contrast  'Custom Controls' in the 'Data Controls' section of the UX toolbox (discussed here) with 'Custom Controls' defined in the 'Other Controls' section of the the UX toolbar - search for 'UX Component - CustomControl - 'Other Controls' for more information.

NOTE: 'Data controls' are controls that have the concept of a control 'value'. These controls have a {dialog.object}.setValue() and {dialog.object}.getValue() method and when the UX is 'submitted' the value in these controls are submitted and are available in the e.datasubmitted object in your Xbasic event handlers.

 

Custom data controls are built using the ViewBox control. An understanding of how the ViewBox control works is essential before you can create a custom data bound control. For more information on the ViewBox control, click here.

 

 

To add a data bound Custom Control to a UX cpmponent, select the [CustomControl] item in the UX toolbox.

To define the properties of the Custom Control click the smart field for the control properties. This will bring up the builder as shown below:

 

When you define a custom control you can specify the properties for the control 'now' (i.e. at design time), or you can generate the property settings at run-time using Xbasic.

The 'Specify Now' option is rarely used because a Custom Control that uses the 'Specify Now' option is really no different than a ViewBox control and so there is little reason to use the Custom Control rather than the ViewBox.

However, the option to generate the custom control definition at run-time using an Xbasic function is extremely powerful. and allows you to generate highly customized controls on your UX component.

 

Creating a Custom Control - Starting with a ViewBox Control

The easiest way to create a new Custom Control is to start by creating a ViewBox control and then once you are satisfied with the ViewBox control copy the generated Javascript from the ViewBox builder to the Custom control.

From the ViewBox builder, click the Show button at the bottom left corner of the dialog. Then select the 'Javascript code to render ViewBox' menu command. 

Copy the code for the 'Settings' object. This is the code you will paste into the Settings JSON property in the Custom Control builder.

 

 

UX Component - ViewBox Control - A powerful new control type is now available in the UX Builder.

See this link for details about the ViewBox control.

 

UX Component - List Control - International Numbers - If the system regional settings on your server are set to a country that uses a comma as the decimal point, when you create a List control numbers are now shown with the comma as the decimal character. Previously, numbers were displayed using a period as the decimal character.
 

As a result of this change client side calculations (e.g. client-side calculated fields), might no longer work correctly. To fix the problem add this code to the client-side onRenderComplete event:

$u.decimal = ',';

 

This code informs the Javascript functions that convert a string into a number what the decimal character is.

 

UX Component - File Save Format - JSON - In a previous pre-release build (4582) an option was introduced to allow the UX component to be saved as a text file (using a JSON format) rather than the default binary file format. However, the default format was left unchanged as binary. Now, the default format has been changed to JSON. The reason for this change is to make using source controls systems easier to work with.

 

UX Component - PhoneGap - Image Capture - File name Option - When you use the PhoneGap camera option to take a picture, the picture filename is stored in the file system in a temporary location. This means that if the application is terminated the file may be removed by the operating system. You now have the option of moving the file to a different part of the file system so that it is not in a temporary location.

This new option is exposed in the Action JavaScript builder as shown below.

 

 

UX Component - PhoneGap - File System Methods - Several new methods for working with the file system in a PhoneGap application have been added.

NOTE: The existing PhoneGap file system methods (accessed using the PhoneGap - File System Actions action in Action Javascript) are limited in that they do not allow you explicitly specify what file system you (i.e. 'temp', 'private', 'saved', 'public') you want to use and they assume that all actions are in the 'saved' file system.

These new methods are more generalized as they can work with fully qualified file and directory URLs.

 

{dialog.object}.phoneGapFilesAvailable() Returns true if there is a local file system and PhoneGap is running.
{dialog.object}.phoneGapGetLocalDirURL(type) Returns URL of base for the requested part of the file system.  'type' can be: "temp", "private", "saved", "public"

Note: On iOS, "saved" and "public" may be backed up to iCloud
{dialog.object}.phoneGapReadFileURL(filepath, onReadSuccess, onError, startAt, endAt) Read a file. Optionally specify a starting and ending position in the file.
{dialog.object}.phoneGapWriteFileURL(filepath, text, onWriteSuccess, onError, append) Write a file
{dialog.object}.phoneGapFileExistsURL(filepath, onResult, onError) Check if a file exists. onResult(properties) will be called with false if the file does not exist.
{dialog.object}.phoneGapDeleteFileURL(filepath, onDeleteSuccess, onError) Delete a file
{dialog.object}.phoneGapCopyFileURL(srcpath, destdirpath, destname, onCopySuccess, onError) Copy a file.
{dialog.object}.phoneGapMoveFileURL(srcpath, destdirpath, destname, onMoveSuccess, onError) Move a file.
{dialog.object}.phoneGapRemoveDirectoryRecurseURL(dirpath, onRemoveSuccess, onError) Deletes the specified directory and all of its contents, including other directories and their contents.
{dialog.object}.phoneGapEnsureDirPathURL(rootpath, subdirpath, onCompletion, onError) Ensures that a directory structure (specified by subdirpath) exists within the specified rootpath. If the directories do not exist, they are created.
{dialog.object}.phoneGapListFilesRecurseURL(rootpath, onCompletion, onError) List files in a directory (recursively)
{dialog.object}.phoneGapListFilesURL(dirpath, matchRegex, onCompletion, onError) List files in a directory. If matchRegex is specified only matching files are listed.
{dialog.object}.phoneGapDeleteFilesNotInListURL(dirpath, matchRegex, keepList, onCompletion, onError) Delete files. If matchRegex is specified, only matching files are listed. If keepList is specified files in the list are not deleted, even if they matched.

 

 

 

UX Component - HTML Editor - Toolbar - You can now customize which buttons are shown on the HTML editor toolbar.

To customize the toolbar, click the smart field for the HTML editor toolbar customization property.

 

 

This will open the Genie where you can select the buttons that you want and the order in which you want them to appear. Use *break to start a new row of icons and *space to insert a spacer between the icons.

 

 

 

 

UX Component - Sample Templates - PhoneGap - When you create a new UX component, the available sample templates now include 'PhoneGap - iOS Background Geolocation' and 'PhoneGap - iOS Device User Authentication'.

 

PhoneGap App Builder - Third Party Plugins (iOS) - Touch ID. Added support for the TouchID plugin. This plugin, allows a PhoneGap app to locally authenticate the user with the TouchID sensor (fingerprint scanner) on iPhone 5S and greater devices.

For a video overview of using this plugin with the new UX PhoneGap - iOS Device User Authentication template,
see Local Authentication for iOS with the Fingerprint Scanner Plugin

For the full cordova-plugin-touch-id plugin documentation,
see cordova-plugin-touch-id

PhoneGap App Builder - Third Party Plugins (iOS) - Background Geolocation. Added support for the Transistorsoft/cordova-background-geolocation-lt plugin. This sophisticated plugin, allows a PhoneGap app to continue acquiring device geolocation data when the app is in the background or the device is locked.

For a video overview of using this plugin with the new UX PhoneGap - iOS Background Geolocation template,
see iOS Background Geolocation with PhoneGap

For the full transistorsoft/cordova-background-geolocation-lt plugin documentation,
see cordova-background-geolocation-lt

 

Style Builder - A new Style Builder is available for Alpha Anywhere V3 Styles - Alpha Anywhere styles that were released in older versions of Alpha Five (e.g. MobBlue, MobGreen, GrBlue, etc) are tagged internally as 'version 2' styles. Newer styles (e.g. iOS, iOS7, AndroidLight, AndroidDark) are tagged internally as 'version 3' styles.

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3
 

A new Style Builder is available for 'version 3' styles. Previously it was not possible to edit a 'version 3' style in the 'version 2' style builder.

Now, when you try to edit a style, Alpha Anywhere automatically selects the appropriate style builder.

 

There are several ways to get to the style builder. The easiest is to open the UX or Grid component and click the smart field button for 'Edit style in Style Builder'  property (which is just below the Style Name property).

You can also select the Edit, Open Web Style Builder command from the menu when the Web Control Panel has focus.

Alpha Anywhere web styles can be stored in one of three places:

When you select a style to edit, if you selected a 'system' style, you will get a dialog asking you to make a 'local' or 'global' copy of the style.

When you make a copy of the style you can keep the same name as the source ('system') style, or you can give the style a new name. Since the local or global style is stored in a different folder than the system style, it is perfectly OK to use the same name as the source ('system') style.

 

 

If you selected a version 3 style the new style builder will be displayed:

 

 

The Style Builder has two distinct modes.

Alpha Anywhere styles sheets are defined using SASS syntax. To learn more about SASS visit http://sass-lang.com/

One huge advantage of SASS syntax is the ability to define variables for many of the setting in the stylesheet, especially colors.

The Adjust mode allows you to easily adjust the SASS variables in your stylesheet. For example if you use the built-in iOS7 stylesheet you will see that the predominant color in the style is blue. By changing a single SASS variable in Adjust mode you can change the entire

The tabs at the bottom on the screen allow you to switch between Adjust mode and Code mode.

 

Code Mode

In Code mode the left side of the screen has a preview of the style in the top and the actually CSS in the bottom.

The property grid on the right shows all of the "object" types defined in the stylesheet. Examples of "objects" include Textbox, Button, Accordion.

For each object type one or more named sub-types can be defined. The sub-types are called 'sub-themes'. Generally every "object" has at least one 'sub-theme' called 'base'. For some object types only 'base' sub-theme is defined. You can add an arbitrary number of sub-themes for any object type.

A sub-theme defined all of the CSS classnames used to style the object.

At the top of the code window when you are in Code mode you will all of the SASS variables defined in the stylesheet.

You can adjust the variable values directly in the Code window or you can switch to Adjust mode to change the SASS variables.

 

 

 

 

UX and Grid Component - Open Style Builder - You can now open the Style Builder directly from the UX and Grid component. A new property 'Edit style in Style Builder' appears directly below the 'Style name' property.

 

 

Application Server - Open SSL - A new version of OpenSSL is now included with Alpha Anywhere.

OpenSSL 1.0.2g addresses the 'Drown attacks' vulnerability.

 

UX Component - Sub-theme Picker - Preview - When you pick the sub-theme for any control that supports sub-themes, the picker now shows a preview of all of the available sub-themes.

 

 

 

 

PhoneGap Builder - SQLite Databases - When you create a PhoneGap project, you can now include pre-populated SQLite database files as part of the PhoneGap project. A new genie allows you to create the SQLite databases that you include with your PhoneGap project.


Watch Video 1
Watch Video 2

 

If your PhoneGap project includes pre-populated SQLite databases, your UX component can work with the data in these SQLite databases using Action Javascript. See 'UX Component - PhoneGap - Using SQLite - Action Javascript' below for more information.

If you are including pre-populated SQLite databases in your project, be sure to specify the following PhoneGap plugins: Device, File, File Transfer, SQLitePluginExt.

To define the SQLite databases that should be part of your PhoneGap project, click the smart field for the SQLite Databases property in the PhoneGap Genie.

 

 

 

This will open a dialog where you can define your SQLite databases.

Your project can include multiple SQLite databases and each database can include multiple tables. Each SQLite database is contained in a single file and this file is automatically added to the Additional Files Required setting in the builder.

You can choose to put all of the tables you want in your SQLite databases in a single SQLite database, or you can use multiple SQLiite databases - the choice is yours.

 

 

 

Once you add a new SQLite database to the above dialog, you can click the Define SQLite Database Contents button to specify the tables that should be in the SQLite database. For each table that you specify you can define how the table should be populated. The options are to perform a SQL query to extract data from any SQL database supported by AlphaDAO, static data, or Xbasic. If you choose the Xbasic option, you can specify Xbasic code that will return data that are used to populate a table.

Once you have defined the SQLite databases, click the Create SQLite Database Files button to actually create the SQLite database files. These files will be created in the www folder in your PhoneGap project.

 

NOTE: Contrast creating pre-populated SQLite databases with making an Ajax callback to the server and dynamically creating the SQLite database. Dynamically creating SQLite databases is a built-in action in Action Javasascript and it is discussed below. See UX Component - PhoneGap - Using SQLite - Action Javascript.

 

 

UX Component - PhoneGap - Using SQLite - Action Javascript - The UX component now has extensive support for working with SQLite databases in a PhoneGap application.

SQLite is a SQL database that is available on your mobile device and is accessible through a PhoneGap plugin. When building disconnected applications, having an on-device SQL database can be extremely useful. It allows you to get rapid access to large amounts of data that are stored on the device (and is therefore available even when there is no connection). You can store significantly more data for offline access than would be possible using Local Storage.

The primary use case for an on-device SQLite database is to make large amounts of 'lookup' information available in a disconnected, mobile application.

 

Watch Video 1
Watch Video 2
Watch Video 3
Watch Video 4
 

NOTE: The UX Component Client-side Data Cache is also useful, in PhoneGap applications, for storing large amounts of data on the mobile device for use in offline applications. Your particular application requirements will dictate if the Client-side data cache, or SQLite, is the better solution.

 

IMPORTANT: To use the SQLite features in a PhoneGap application, your PhoneGap project must load the following plugins: Device, File, File Transfer, SQLitePluginExt. These plugins are all listed in the PhoneGap builder.

NOTE: While it is certainly possible to perform Insert, Update, and Delete actions on the SQLite database that is on a device, there is no built-in mechanism for persisting these changes to the source database on your server. You would be responsible for writing your own code to persist changes to the on-decice SQLite database to your server databases.

 

A SQLite database is a single file. The SQLite database file can be part of your PhoneGap project, or it can be downloaded to the device by making a callback to a server.

If the SQLite database is part of your PhoneGap project, you will need to list the name of the SQLite database file in the Additional Files Required property in the PhoneGap Builder.

 

 

NOTE: For more information on adding SQLite database to a PhoneGap project, see this section : PhoneGap Builder - SQLite Databases.

 

You can use Action Javascript to download a SQLite database to the mobile device at run-time (see below for more information). When you download the SQLite database to the device at run-time, you can either download an existing SQLite database, or your callback function can dynamically create the SQLite database file.

 

Action Javascript now has a new action called 'PhoneGap - SQLite Actions' that will allow you to select and configure the type of action you want to perform.

 

 

When you select this action, the builder shows the available SQLite actions:

 

 

 

The available action are:

 

Command Description
Download SQLite Database from the Server Downloads a SQLite database file from a server and stores the database file on the mobile device
Create SQLite Database on Server then Download to Device Similar to the 'Download SQLite Database from the Server' action excepting that the SQLite database file is dynamically created on the server before it is downloaded to the device
Execute SQL statement(s) Executes one or more SQL statements. If you execute multiple SQL statements, the statements are automatically wrapped in a transaction so that no changes are made to the database if any of the statements fail.
Get Tables in a Database Lists the tables in a SQLite database.

 

Each of these commands in discussed in more detail below.

 

 

Download SQLite Database from Server

Use this action to fetch a remote SQLite database file from a server (does not have to be the Alpha Anywhere server) and store the database on the mobile device. Once the database has been downloaded, you can then start executing SQL commands against the tables in the database.

There are two ways in which this action can be used:

  1. Specify the URL of the remote SQLite database file (using Javascript).
  2. Make an Ajax callback to the Alpha Anywhere server. The function that handles the callback will be responsible for returning the URL of the SQLite database file.

If you are using option 1, then you will need to specify Javascript code that returns the URL of the SQLite database file.

Examples:

Assume that the SQLite database files is in a folder in the webroot. The relative filename of the SQLite database file is (for example) sqlite/db1.db. Your Javascript code that returns the URL will therefore be:

return 'sqlite/db1.db';

 

There is no need to specify a protocol for the URL since the resource is relative to the webroot.

If, on the other hand, the SQLite database file was (for example) in an Amazon S3 bucket, your Javascript code might be:

return 'http://name_of_your_s3_bucket.s3.amazonaws.com/sqlitedbfilename.db';

 

Id you are using option 2, you must specify an Xbasic function that will handle the Ajax callback. The Xbasic function will return the URL of the SQLite database file (by setting the e.URL property in the Xbasic code).

 

Create SQLite Database on Server then Download to Device

This action is really just a variant of the Download SQLite Database from Server action. The main difference is that the SQLite database to download to the device is created on the fly by Alpha Anywhere and once the database file has been created, a message is sent to the client (i.e. the mobile device) telling it that the SQLite database file has been created and can now be downloaded to the server.

The SQLite database file is created by populating a SQLite database with data obtained from SQL queries (against your SQL Server, Oracle, MySQL etc. data sources), static data, or from Xbasic code (that returns data to be used to populate the SQLite database).

For example, you might define a SQLite database that contains several tables  (called say 'table1', 'table2', 'table3', etc.) where:

When you select this action, the builder shows this screen:

 

The SQLite Database definition property is where you define how the SQLite database will be created. When you click the smart field for this property you get this dialog.

 

 

 

This dialog allows you to define the tables that will added to the SQLite database.

You can add as many tables as you want. Once you have have added a table (by clicking on the Add table) button, you can then define the data source for that table (by clicking on the Edit table definition) button.

When you click the Edit table definition button you get a dialog as shown below where you can define how the SQLite table will be populated.

The choices are:

 

 

Format for Static Data and Data Returned by Xbasic Functions

If your Query Type is set to either Static or Xbasic, the required format for the data is as shown in the following example:

 

ID=INTEGER (Primary Key),FirstName=TEXT,LastName=TEXT,Salary=NUMERIC
1,Fred,"Smith",87234
2,Tom,Jones,45234

 

Note that the data is in CSV (comma separated value) value format. Values can be quoted if they contain commas.

The first row in the data is the field names. The format for the fieldnames is:

fieldname=fieldtype


There is no need to specify a field size for a SQLite table. The SQLite field types are TEXT, NUMERIC, INTEGER, REAL and BLOB. You can optionally indicate which column in the primary key by including the (Primary Key) keyword after the field type.

 

Execute SQL statement(s)

This action allows you to execute SQL statements against any SQLite database on the device. You can either execute a single SQL statement, or you can execute multiple statements.

If you execute multiple statements, the statements are wrapped in a transaction, which means that the state of the database is not changed if any of the SQL statements fails.

When you select this action you get the following dialog (shown twice - once for the 'Single' statement case and once for the 'Multiple' statement case).

 

 

Executing a Single SQL Statement

 

The properties in the Dialog are defined below:

Your SQL statement can optionally reference arguments (similar to SQL::arguments when using AlphaDAO in Xbasic).

For example, this statement does not use arguments:

select * from customers where id = 'ALFKI'

 

This statement does use arguments:

 

select * from customers where id = ?

 

The ? indicates an argument value.

If your SQL statement uses arguments you must defined the argument values in the Arguments property.

For example, if your SQL statement was select * from customers where id = ?

the Javascript that you define for the Arguments property might be:

return ['Alfki'];

 

 

Example:

Assume that your SQLite database has a table called customers and you want to populate a List control with the results of this query:

select * from customers where city = 'Boston'

 

You might set the onSuccess Javascript to:

 

if(resultArray.length > 0) {

    //populate list 'list1' with data
    {dialog.object}.setListColumnsAndPopulate('list1',resultArray);
} else {
    alert('No records in query.');
}
 

 


 

Executing Multiple SQL Statements

 

 

In the case where you are executing multiple SQL statements you must set the SQL definition Javascript property.

Your Javascript must return an object with these properties:

 

Alternatively, your Javascript can return an array of objects. Each object in the array should have these properties:

Example:

(This example uses the array of objects method. Notice that the parameters passed into the onSuccess functions are: tx, result, array and transObj.

where:

 

Notice how the arguments property for the last object in the array calls a function to set one of the argument values. This function can see the transObj variable.

)

 

 

var obj = [];
obj.push( { sql: 'drop table if exists cars', onSuccess: function(tx,result,array,transObj) { alert('table was dropped'); }} );
obj.push( { sql: 'CREATE TABLE Cars (Id INTEGER PRIMARY KEY, Name TEXT, Price INTEGER)'} );
obj.push( { sql: 'insert into cars (name,price) values (?,?)', arguments: ['Ford',1], onSuccess: function(tx,result,array,transObj) { transObj.foobar = 123;} });
obj.push( { sql: 'insert into cars (name,price) values (?,?)', arguments: ['GM',2] } );
obj.push( { sql: 'insert into cars (name,price) values (?,?)', arguments: ['Honda',3] } );
obj.push( { sql: 'insert into cars (name,price) values (?,?)', arguments: ['Toyota',function(transObj) { return transObj.foobar; } ] } )
return obj;

 

 

 

NOTE: When you edit the Javascript for the  SQL definition Javascript property, the Javascript editor shows extensive help for how to construct the object for the SQL definition object.  For example, the help shows how you can do the following task:

 

You can also define these properties:

 

How to Create a New SQLite Database on a Device

When you want to start working with a SQLite database on a mobile device there is no requirement that you either download an exiting SQLite database from the server or include a pre-populated SQLite database in your PhoneGap application. You can simply create a new SQLite database on the fly in your Javascript code.

When you use the 'Execute SQL statement(s)' action in the 'PhoneGap - SQLite Actions' action, you specify the name of the SQLite database name against which the SQL commands should be executed.

If you specify the name of SQLite database that does not exist, then a new SQLite database will automatically be created.

 

 

 

 

 

 

Xdialog - {treatasform} Directive - If a modeless Xdialog is displayed and then all Alpha Anywhere windows  (besides the modeless Xdialog) are closed or hidden, then once the last window is hidden, the Workspace itself will be closed.

For example, consider the following sample Xdialog code.

 

dim dlg_title as c 
dlg_title = "test"
dim dlg_body as c
dlg_body = <<%dlg%
<close><hide><show>
%dlg%
dim dlg_event as c 
dlg_event = <<%code%
if a_dlg_button = "close" then 
    ui_modeless_dlg_close(dlg_title)
else if a_dlg_button = "hide" then 
    controlpanel.hide()
else if a_dlg_button = "show" then 
    controlpanel.show()
end if 
%code%
ui_modeless_dlg_box(dlg_title,dlg_body,dlg_event)
 

 

Once you press the 'Hide' button to hide the Control Panel (assuming that there are no other Alpha windows open at the time), the Workspace will closed, and therefore the "Show" button, which is intended to show the Control Panel, will not work.

You can instruct Alpha Anywhere not to enforce this rule by adding the {treatasform} directive to the Xdialog. This will cause Alpha Anywhere to not close the workspace when the last window (not counting the Xdialog) is closed.

 

dim dlg_title as c 
dlg_title = "test"
dim dlg_body as c
dlg_body = <<%dlg%
{treatasform} 
<close><hide><show>
%dlg%
dim dlg_event as c 
dlg_event = <<%code%
if a_dlg_button = "close" then 
    ui_modeless_dlg_close(dlg_title)
else if a_dlg_button = "hide" then 
    controlpanel.hide()
else if a_dlg_button = "show" then 
    controlpanel.show()
end if 
%code%
ui_modeless_dlg_box(dlg_title,dlg_body,dlg_event)
 

 

UX Component Builder - Display Line Numbers in the Controls List - You can now turn on the display of line numbers in the control list in the UX builder. In large components, this will make it easier to find a control quickly.

 

Watch Video
 

 

 

To toggle the display of line numbers, click on the Menu button and select the Toggle line numbers in Controls display menu item.

You can also go to the Properties pane and check the Show line number in Controls list property.

 

 

 

TIP: You can easily navigate to a control by number by pressing the Ctrl-G shortcut key.

 

 

UX Component - List Control - Pull-past-End to Refresh List Data - You can now easily implement the common 'pull-past-end-to-refresh' List data pattern.

Watch Video

 

To turn on this behavior, open the List builder and check the Has 'pull-to-refresh' behavior property.

 

 

You can then configure the settings for the behavior.

 

 

The Convert to low level properties checkbox on the builder allows you to see all of the individual properties that get set to implement this behavior. If you want to customize the behavior beyond what this genie allows, check this box.

 

 

AlphaDAO - SQL - DateTime Fields - SQL::Resultset.toJSONObjectSyntax() - Datetime fields are now exported using an increased precision. Previously, the default format for date time fields was:

MM/dd/yyyy 0h:0m:0s   (or dd/MM/yyyy 0h:0m:0s if set by Windows regional settings).

Now, the default format is:

MM/dd/yyyy 0h:0m:0s 3

 

Technical Note: This change will solve the following problem: Assume that you had a SQL table with a field called (for example) 'ExaminationDate' and that the value in the field was 2/18/2016 3:24:10 123. Assume that you then built a UX component with a List control with a Detail View to allow users to edit this value and that you had write conflicting checking turned on for the ExaminationDate field.

When the user tried to synchronize the data after making a change to the ExaminationDate field they would get a write conflict error because the 'old' value for the ExaminationDate field was stored as 2/18/2016 3:24:10  and not 2/18/2016 3:24:10 123. With the above change, the 'old' value for the field stored in the List will be stored at the field's full precision, and the update will succeeed.

 

 

UX Component - Custom Settings - Custom settings are named setting values that you can reference in JavaScript code and in your component definition.

Watch Video - Part 1
Watch Video - Part 2

Download Component

 

To define Custom Settings go to the Properties Pane in the UX builder. The Custom settings property appears in the Advanced section.

 

 

Click the smart field and the Custom Settings dialog is shown.

 

 

 

The dialog allows you to create an unlimited number of custom settings. Each custom setting has a name and a value.

If the value is a string, just enter the string value. If the value is a JavaScript object, you must prefix the definition with '{javascript}'. If the value is a function definition, you must also prefix the value with '{javascript}. In the example below, three custom settings are defined showing how the value of the custom setting is set to a string, object and function:

Custom Setting Name Value
setting1 Some string value
setting2 {javascript}{name: 'Fred', city: 'Boston'}
setting3 {javascript}function(name) { alert('Hello name.toUpperCase());}

 

You can export Custom Setting definitions and import them using the Export and Import hyperlinks at the bottom of the screen.

 

Using Custom Settings

Custom settings can be used in your Javascript code and also at the time the UX component is rendered.

 

Using Custom Settings when a Component is Rendered

When you define the properties of a UX component, any place that you define some text you can use a Custom Setting value using this syntax:

[CustomSetting:settingName]

 

For example, assume you have a Button control in your UX. You could set the Button text to:

[CustomSetting:button1]

 

If you had defined a Custom Setting called 'button1' with a value of 'Save new record' then when the UX component was rendered, the label on the button would be 'Save new record'.

 

Using Custom Settings in JavaScript Code

The UX object has a method that allows you to read and set Custom Setting values:

{dialog.object}.customSetting(settingName [, newSettingValue])

 

If you do not provide the optional second parameter the method is used to read the value of a Custom Setting. If you provide the second parameter, the method is used to update a Custom Setting value.

For example, assume you had defined a Custom Setting called 'string1', with a value of 'this is the value of string1'. You could use this in your JavaScript code:

var txt  = {dialog.object}.customSetting('string1');

alert(txt);

 

If the value of 'string1' had been set to an object (using this for the value: {javascript}{name: 'Fred', city: 'Boston'} ), then your JavaScript might look like this:

 

var obj = {dialog.object}.customSetting('string1');

alert(obj.name + ' -- ' + obj.city);

 

If the value of 'string1' had been set to a function (using this for the value: {javascript}function(name) {alert('Hello ' + name);} ), then your JavaScript might look look like this:

 

var fn = {dialog.object}.customSetting('string1');

//now call the function

fn('Fred');

 

To set a new value for the 'string1' Custom Setting:

{dialog.object}.customSetting('string1','this is a new value for string1');

 

Overriding Custom Settings when Opening a UX Component

When you use Action Javascript to define an action that opens a UX component, if the target UX component has defined any Custom Settings, you can override the value of the Custom Settings.

In the image shown below, the Action Javascript action opens a UX called 'uxWithCustomSettings'. Since this UX has defined some Custom Settings, the dialog shows an option to override any of the Custom Setting values.

 

Note The overrides defined here are applied when the UX is initially rendered. If this action is called from a button and the target UX is opened in a Window and the 'Use cached UX Component' property is checked, the second and subsequent times the button is clicked to open the target UX, the Custom Settings are remain at the values they were set to when the target UX was initially opened.

 

Using Language and Text Dictionary Tags in Custom Settings

You can use language tags (<a5:r>...</a5:r>) and text dictionary tags (<a5:t>...</a5:t>) in the Custom Setting values.

 

 

UX Component Builder - Buttons and StaticText Objects -  Double-clicking on a Button in the UX Builder will now open the editor to edit the click or onClick event for the button. Similarly, double clicking on a static text control will bring up the text editor.

MongoDB - Using MongoDB in Grid and UX Components and with Xbasic AlphaDAO - Alpha Anwhere has an API for working directly with a Mongo database. This API is useful if you want to write your own server side code to query and update a Mongo database. However, if you want to use a Mongo database as the data source for a Grid, or UX component, you cannot use the API.

In order to use Mongo as the data source for a Grid or UX, it is necessary to impose a schema on the Mongo database, much like any SQL table has a schema.

Alpha Anywhere now allows you to define a connection string to a Mongo database (much like you would define a connection string to any SQL database). Once you have define a connection string, you can build Grid and UX components against the Mongo database in exactly the same way that you would build a Grid or UX against any SQL database. You can also use AlphaDAO in Xbasic to perform CRUD operations against the Mongo database

When you define a connection string to a Mongo database you define a schema for each table  (i.e. collection) in the database. This schema defines the fields and data type of each field in each table.

When you define a connection string to a Mongo database you define:

The image below shows the connection string builder for a Mongo database.

 

NOTE: In the above screenshot the manifest filename stats with '.\'. This syntax is used to indicate the the manifest is stored relative to the Web Project folder. In the above example, the manifest will be stored in a folder called 'schemas' in the Web Project folder, and when the project is published, the schema.json file will be published to a folder called 'schemas' in the web root.

 

 

Alpha Anywhere has a number of helper function that help you define the schema for the Mongo database.

 

Structure of the Schema JSON File

A sample schema JSON file is shown below. The JSON file defines two objects, 'schema' and 'collection' and an optional property, 'sourceconnection'.

 

The 'collection' object contains a property for each collection in the Mongo database and the name of the corresponding schema in the 'schema' object.

For example, the entry in the 'schema' object shown below specifies two schemas, one called 'Categories' and another called 'Employees'. For each schema, the primary key column is specified and the list of columns and their corresponding data type are identified.

The optional 'sourceconnection' identifies if the schema was obtained from a looking at the schema in some other SQL database.  If so, the 'sourceconnection' property is the connection string to that database.

 

			
{
    "schema": {
        "Categories": {
            "primary": [
                "_id"
            ],
            "columns": {
                "_id": "String",
                "CategoryID": "Number",
                "CategoryName": "String",
                "Description": "String",
                "Picture": "String"
            }
        }
        "Employees": {
            "primary": [
                "_id"
            ],
            "columns": {
                "_id": "String",
                "EmployeeID": "Number",
                "LastName": "String",
                "FirstName": "String",
            }
        }
    },
    "collection": {
        "Categories": {
            "schema": "Categories"
        },
        "Employees": {
            "schema": "Employees"
        }
    },
    "sourceconnection": "::Name::northwind"
}
			
		

Creating the Schema

To define the Mongo database schema, click the More... button on the connection string build.

 

 

This will open an intermediate dialog:

Then click the 'Edit/create Schema definition...' hyperlink.

This will open a dialog when you can edit the schema definition.

 

 

 

At the bottom of the dialog you will see several hyperlinks:

 

More on the 'Guess From Content...' Option

When you click the Guess From Content... button, Alpha Anywhere will examine the data in the Mongo database specified at the 'Database' prompt on the connection string builder. This is the dialog that was displayed before you clicked the 'More...' button to get to the dialogs when you define the schema.

 

 

 

Using a MogoDB Connection String

Once you have built the connection string to the MongoDB database you use it in the same way that you use any other connection string (that connects to SQL databases). You can build Grid and UX components against the Mongo database. You can also use Xbasic and AlphaDAO objects to work with the data in the Mongo database.

When you use a connection string that points to a Mongo database you are essentially using SQL syntax to interact with the Mongo database. Behind the scenes Alpha Anywhere is automatically converting the SQL commands to the appropriate commands that then Mongo API understands.

You can see how Alpha Anywhere makes this translation but turning on the 'Trace SQL' option in the connection string build (shown below). Once you do this, the trace information will be shown in the Trace window (View, Trace window) if you are working in the Alpha Developer Version - i.e. the IDE) or in a folder where your logs are created if you are in the Server.

 

Here is some sample output from the Trace window showing the SQL statement and how that statement was translated to Mongo commands.

 

SQL Statement: SELECT FIRST 11 [_id], CustomerID, CompanyName, ContactName, ContactTitle, City, Country FROM Customers ORDER BY ContactTitle, [_id]
Time to prepare URL: 0.001
Time to execute REST call: 0.041
Mongo Commands:
{
    "verb": "GET",
    "collection": "Customers",
    "select": "_id , CustomerID , CompanyName , ContactName , ContactTitle , City , Country",
    "groupby": "",
    "where": {},
    "orderby": "ContactTitle, _id",
    "limit": "TOP 11 "
}

 

Because Mongo is not a SQL database, there are obviously limitations as to what SQL commands you can send to Mongo. For example, you cannot execute a SQL statement that performs a JOIN since the concept is meaningless to Mongo. You also cannot perform CRUD operations that affect more than a single record. For example, the following SQL statement will update multiple records

UPDATE customers set Status = 'B' where Balance > 100

This will not work if you are connected to a Mongo database if there is more than one record with a Balance that is > 100.

 

 

 

 

 

 

 

Grid Component - Arguments - Array Arguments - IN Clause in SQL Statements - You can now use the IN clause in a SQL statement in a Grid, where the IN clause is tested against an argument.

For example, you might set the SQL query for a Grid to

Select * from customers where customerId IN (:array_customerIds)

 

IMPORTANT: The parentheses around the argument in the above SQL statement are required when using an IN clause.

 

The argument in the above SQL is 'array_customerIds'. The 'array_' prefix in the array name is significant. It informs Alpha Anyhwere that the argument is an 'array argument'

When you define the 'array_customerIds' argument in the Grid you might (for example), bind the array to a session variable. For example, you might bind the argument to session.whatCustomerIds.

The session variable would be set to a comma delimited list of values.

 

 

 

  Report Events - BeforePrint and AfterPrint - You can now define two new events for Reports. The beforePrint event fires before any report is printed and the afterPrint event fires after any report is printed.

These events must be defined in an Xbasic Function Library. The name of the functions to call to handle these events are defined in the Web Project Properties dialog, as shown below.

 

Xbasic - AlphaDAO - SQL::Resulset.ToCSVFile() and .ToStringFile() - Two new methods on the SQL::Resultset object allow you to create a file directly without first having to call .toCSV() or .toString() to create an intermediate variable.

 

 

List with Detail View - Synchronizing Data - Synchronization Log Table - The synchronization log table helps prevents a sync command being processed more than once.

If you do offline-data entry in a List, there is a small chance that the SQL updates to the underlying table will be executed more than once. This can happen if the mobile device loses connectivity to the server AFTER the synchronize command has been received by the server, but BEFORE the mobile device has received the response from the server. Under this condition, the next time the List is synchronized, the previously submitted edits will be submitted a second time. By checking the 'Use server-side synchronization log table' property, a special server-side log can be used to prevent the possibility of duplicate SQL updates. When you check this property an extra Ajax callback fires after the client-receives acknowledgement from the server that the synchronization was performed.
 

By default, after a successful sync, the sync log table is cleared out.

Now, a new property has been added to not clear the sync log table automatically. This provides an extra level of protection against duplicate sync commands being executed by the server.

NOTE: If you turn the 'Clear sync log table after successful sync' off, then may need to periodically clear our the sync log table manually as it will continue to grow as users sync their data.

 

Application Server - SSL - Alpha Anywhere now includes the latest stable release of OpenSSL, version 1.0.2f.

Why make the change?

No coding changes were required in Alpha Anywhere to move to OpenSSL 1.0.2.

For more information on OpenSSL releases please go to: http://www.openssl.org

 

a5_sqlToJSONTree() Function - Generates a JSON tree structure from a SQL database table - To display cascading data in a List control (i.e. user selects an item in the List and a sub-list is displayed and a back button is enabled to allow user to navigate to the previous list) a new helper function has been added to Xbasic.

 

Watch Video

 

The function will generate the JSON for the hierarchical List.

 

The function takes the name of a table and a list of fields. For example, if the field list is Country, City, ContactName, the generated JSON data will have a list of Countries. In each Country record there will be a nested array of Cities and in each City record there will be a nested array of ContactNames.

The syntax for the function is:

c JSON = a5_sqlToJSONTree as c (c connectionString, c table,c fieldList [, c endPointFfieldName [ ,c filter  [,c order [p arguments]]]])

Where

Example
 

dim args as sql::Arguments
args.add("c1","USA")
args.add("c2","UK")
json = a5_sqlToJSONTree("::name::northwind","Customers","Country,City,ContactName","CustomerID","Country = :c1 or Country = :c2","",args)

 

A partial listing of the JSON returned by the above function call is shown below:

Notice that for each 'endpoint' the display value is the ContactName, but the 'action' property is set to the CustomerID.


 

[
    {
        "display": "UK",
        "children": [
        {
            "display": "Cowes",
            "children": [
            {
                "display":"Helen Bennett","action":"ISLAT"
            }
        ]
    },
    {
        "display": "London",
        "children": [
        {
            "display":"Ann Devon","action":"EASTC"
        },
        {
            "display":"Elizabeth Brown","action":"CONSH"
        },

        ........
 

 

 

FormView Control - API Changes - The FormView Control API has been changed to simplify the passing of data to the Editors that are associated with fields in the FormView control. As a result of this change, existing UX components that use the FormView control will not be affected. But you should use new syntax when building new Editors.

For example, this syntax

settings['*a5column'] is replaced with settings.formView.active.path

settings.data is replaced with settings.formView.data

All information dynamically generated by the FormView when an Editor is invoked is now encapsulated in the settings.formView namespace. This reduces the chances of a user's settings conflicting with system settings.

 

 

Calling SOAP Services - A new set of genies makes it easy to register and call SOAP services from Xbasic code.
 

Watch Video

 

The Web Projects Control Panel has a new category called 'Web References' where your registered SOAP services are displayed.

 

 

To register a new SOAP web service, select the Web References category in the Web Projects Control Panel and then click the New button.

This will open the New Web Reference dialog where you can register your SOAP web service.

At the 'Service address' prompt, enter the URL of the service WSDL. For example:

http://bernera.zapto.org/astronomy/astronomy.asmx?WSDL

 

Also specify the local name of the service. This can be any name you want.

Once you click the OK button, Alpha Anywhere will create a proxy file in the bin\webreference folder in the web projects folder. The proxy file has the same name as the the Name you entered into the New Web Reference dialog and it has a .dll.

 

NOTE: When you publish your Web Project the 'bin' folder will automatically be published. Your Xbasic code that calls the SOAP service will need to be able to reference the proxy .dll file at run-time.

 

Once you have create the Web Reference you can explore it method by double clicking on the entry in the Web Control Panel:

 

 

This will open the Explorer. The explorer shows the methods exposed by the service and the arguments for each method and the return values for each method.

 

 

 

 

Calling a Registered SOAP Service from Xbasic

Once you have registered your SOAP service as described above, you can call it from your Xbasic code. A genie will help you write the Xbasic code.

 

To get to the genie open the Xbasic editor where you will be writing your Xbasic function to make the SOAP call (this might in the Xbasic Function Declarations section in a component, or while exiting an Xbasic Module file), and right click on white space.

Then select the Genies...., Web Reference Call... menu item.

 

 

 

This will then bring up a dialog where you can select the Web Service you want to call. The list of services that you previously registered are shown here.

 

 

 

Once you select the service, the Explorer is shown where you can choose the method that you want to call.

 

 

 

Finally, when you press the OK button, Alpha Anywhere generates the sample Xbasic code needed to call the service. You can paste this code in the Xbasic function you are writing.

 

 

 

Web Applications - Publishing - HTTP Publishing - When you publish a web application to a remote server you first define the Publishing Profile to use. The publishing is currently accomplished by using FTP to upload the files to the remote server. Now, a new way of publishing files to a remove server is available using the HTTP protocol.

Watch Video - Configuring the Server
Watch Video - Defining a Publishing Profile
 

The HTTP Publishing method requires that the Alpha Anywhere server on the remote site be running because the Alpha Anywhere server is actually handling the uploading of the data.

The HTTP Publishing method is more reliable and faster than the FTP method.

For more details on HTTP Publish, click this link:

http://downloads.alphasoftware.com/a5v12Download/ReleaseNotes/HTTPPublish/httpPublish.html

 

PhoneGap App Builder - Third Party Plugins (iOS) - Keyboard Plugins -  Added support for the cordova-keyboard and the ionic-keyboard plugins. These plugins provide functions to make interacting with the iOS keyboard a bit easier and include events to indicate the keyboard will show/hide.

For the full plugin documentation, see the links below.

cordova-plugin-keyboard
cordova-plugin-ionic-keyboard


PhoneGap App Builder - Third Party Plugins (Android, iOS) - Media With Compression Plugin - The Alpha cordova-media-with-compression plugin has been updated to include three (3) new methods.


For the full plugin documentation, see the link below.

cordova-plugin-media-wth-compression
 

 

UX Component - Data Binding - Server-side Save Submitted Data to Table(s) Action - onSQLError Event - A new event has been added to the action to allow you change the error message shown to the user when a SQL database error occurs.

For example say that the user tries to enter a new record. When the INSERT SQL statement is executed, the database returns some error (perhaps a foreign key violation). The error message returned by the database is displayed to the user. However, this error message is often quite cryptic and is certainly not 'friendly'. The onSQLError event handler allows you to intercept the error before it is displayed to the user and replace it with a friendlier message.

 

 

TabbedUI Component - Keyboard Shortcuts - You can now define keyboard shortcuts for the action buttons in a TabbedUI component.

Watch Video

To define a keyboard shortcut for a TabbedUI button, click the smart field and select the key combination. The user will be able to open the component by using the keyboard shortcut in addition to clicking on the button.

 

UX Component - Server-side Events - canAjaxCallback - afterAjaxCallback - Two new server side events have been added:

 

 

In the canAjaxCallback event handler, if your code sets:

e.authorized = .f.

 

then the Ajax callback action will not be performed. Your code can examine data in request.variables to see what type of callback was being attempted.

 

In the afterAjaxCallback event, the 'e' object that is passed into the event handler contains:

e.ajaxResponse

 

Your code can modify this response.

 

UX Component - List Control - SQL Datasource -  beforeQuery  - The beforeQuery server side event fires before a query is performed to get data for the List.

 

 

The event allows you 'authorize' the query.

In your Xbasic code in the function, you can set:

e.authorized = .f.

 

This will cause the query for the List data to return no data.

 

 

 

UX Component - CustomControl - 'Other Controls' - A new control type has been added to the 'Other Controls' section in the UX builder:

 

 

The CustomControl allows you to specify arbitrary HTML and Javascript for the control. You can specify the HTML and Javascript at design-time, or you can specify an Xbasic function that will generate the HTML and Javascript for the control at run-time.

A very powerful use case for the CustomControl is to dynamically generate a form based on a definition stored in a database.

 


Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3
Watch Video - Part 4
Watch Video - Part 5
Watch Video - Part 6
Watch Video - Part 7

 

When you add a CustomControl to a UX component, the PropertySheet for the control is displayed as follows

 

Clicking on the smart field for the Custom Control Properties brings up the builder.

 

If you select the 'Specify Now' option in the Custom Control builder you can specify the HTML for the control and (optionally) any Javascript you want to execute before the UX is 'prepared' and after the UX has been rendered.

 

 

For example, if you wanted your CustomControl to render a standard UX component input control (called, say, 'CUSTOM1')  you would add this code to the HTML:

 

<input id="{dialog.componentname}.V.R1.CUSTOM1" name="V.R1.CUSTOM1" class="{dialog.style}Edit" ></input>
 

And you would add this Javascript to the 'Javascript - Before Prepare' property:


{dialog.object}.columnInfo['CUSTOM1'] = { info: {controlType: 'Textbox'}, hiddenVal: false, type: 'input,label', isCalc: false, hlp: '', isArray: false, dataType: 'C' };
 

On the other hand, if you wanted your CustomControl to render a standard UX component button control (with an ID of, say, 'B1') you would add this code to the HTML:

 

<div id="B1" style="width: .5in;">MyButtonGoesHere</div>

 

And you would add this Javascript to the 'Javascript - After Render' property:


//add an event handler for the button
$e.add('B1',A5.d.evnts.click,function(e) {
alert('this is button b1');
},this,false,'B1');


//define a  new button object
{dialog.object}._buttons['B1'] = new A5.Button({
layout: 'text',
style: 'box-sizing: border-box; -moz-box-sizing: border-box; -ms-box-sizing: border-box; -webkit-box-sizing: border-box; width: 1.5in;',
html: 'Button',
onClick: function() {
},
theme: '{grid.style}'
})
 

//bind the button object to the html element
{dialog.object}._buttons['B1'].bind('B1');

 

 

If you wanted to generate the HTML and Javascript at run-time you can set the Method to 'Xbasic' and then define an Xbasic function that generates the HTML and Javascript.

 

 

 

PhoneGap Shell Template UX Component - Statusbar Plugin - iOS - The template UX component that implements a PhoneGap shell has been modified so that it now uses the PhoneGap Statusbar plugin. When running the Shell UX on an iOS device the status bar will now display above the UX component. Previously, the status bar was overwritten by the UX component. The code that implements this is in the UX components onPhoneGapReady client-side event.

NOTE: Search for PhoneGap - PhoneGap Shell - for more information on the PhoneGap Shell.

UX Component - List Control - Lists with Detail View - Synchronization - onSynchronize Server-side event -  The onSynchronize event fires when the user clicks the synchronize button on the UX to submit edited List rows to the server. The primary purpose for this event is to allow the developer to take complete control of the synchronization process and implement a custom handler to synchronize the edited List data.

When the user synchronizes a List with a Detail View, the dirty List records are submitted to the server. If the List is based on SQL queries, the CRUD operations to update the database are automatically computed by Alpha Anywhere. However, you may want to process the dirty List data yourself.

 In the case where the List is not based on SQL queries, you have no choices - you have to handle the List synchronization yourself.

 

 

NOTE: If the List is not based on SQL queries, the List Builder also has these events:

 

 

The onSynchronize server-side event is a higher level event that fires before any of the 'Synchronization Handler' events are fired. For example, the 'Commit data handler function' is called after the server has processed validation rules. The event is called once for each dirty composite record submitted to the server.

 

 

Application Server - Self-Signed Certificates - Self-signed SSL certificates are now signed using the SHA-256 algorithm. Previously they were signed using the md5 algorithm, which is no longer considered secure for these purposes. It is still recommended that a public-facing server use a certificate from a commercially supported Certificate Authority (e.g. Verisign, Comodo, GoDaddy, etc.) for browser compatibility, but this change increases security in situations where self-signed certificates are desired.
 

UX Component - PanelOverlay - Windows - A new property has been added to PanelOverlays to make the PanelOverlay behave like a window. When the 'PanelOverlay is window?' property is checked, the PanelOverlay is initially hidden (when the Panel that contains the PanelOverlay is shown).

Watch Video
Download Component
 

To show the PanelOverlay you can use Action Javascript. There are two new actions in Action Javascript:

These actions allow you to animate the PanelOverlay as it is shown or hidden.

NOTE: The animation option uses jQuery. Your application must load jQuery. See the Project Properties dialog (accessed from the Web Applications Control Panel).

.Net Framework v4.6 - Alpha Anywhere now uses .Net Framework v4.61. If the machine you are installing to does not include the .Net Framework v4.61, Alpha Anywhere will install it. It can take quite a bit of time to install the .Net Framework. However, this is a one-time event.

 

Web Applications - Xbasic Error Log - A new warning message is now written to the Xbasic error log if you run a component that was last edited with a build that is greater than the version of the server.

For example, say your server is running using build 4600 and you run a component that was built with build 4610. This is a version mismatch that might cause an error.

For example if the component built using build 4610 calls some function that was added after build 4600, it will definitely lead to a run-time error. On the other hand if the the component does not use any new functionality, then it is unlikely that there will be an error.

Because it cannot be know with certainty if this version mismatch will lead to errors, the message written to the Xbasic error log is termed a 'warning' and not an 'error'.

 

Xbasic - Web Applications - How to Write to the Xbasic Error Log - Xbasic_Write_to_Error_log() - A new Xbasic function allows you to write messages to the Xbasic error log.

The text is written to the error log exactly as specified in the function. Therefore it is recommended that you format the message so that it appears in the log in a useful manner.

For example

dim message as c

message = "Warning: " + crlf() + chr(9) + "This is a warning message" + crlf()

Xbasic_write_to_error_log(message)

 

The message will appear in the log as:

 

Warning:

    This is a warning message

 

 

 

 

UX Component - ButtonList Control - Allow Null Property - The ButtonList now has a new property - 'Allow NULL selection'. The options for this property are:

 

 

 

UX Component - ButtonList - Class name - You can now specify a class name for the items in a ButtonList.

 

 

 

In the above example the class name is set to 'foobar'

Here is how you might want to define this class:

 

.foobar {color: red;}

.{dialog.style}ButtonPressed.foobar {color: orange;}

 

Notice that two CSS selectors are defined.

.foobar - defines the appearance when the Button is not selected

.{dialog.style}ButtonPressed.foobar - defined the appearance when the Button is selected.

 

UX Component - Checkbox and RadioButton Controls - Vertical Alignment - Vertical Spacing - A new property has been added for Radio Button and Checkbox controls that allows you to control the vertical spacing between each item.  The 'Vertical spacing' property is shown when the Orientation is set to 'Vertical'.

 

 

 

 

UX Component - Data Bound Image Control - imageIsEmpty() Method - A new method on the Dialog object allows you to test if an image control is empty.

Example:

var flag = {dialog.object}.imageIsEmpty('PICTURE1');

 

 

UX Component - Explore Structure - A new dialog is available to help you understand the structure of complex UX component layouts.

 

Watch Video

 

When you build large UX components with many Panels, Windows, PanelOverlays, etc. it can be difficult to get an 'overview' of the underlying structure of the component. The new 'Structure View' can help you quickly explore the structure of a UX.

The 'Structure Explorer' is implemented as another view in the Quick Find dialog.

To open the 'Structure Explorer' click the 'Find' button on the toolbar and then select the 'Explore Structure' radio button.

 

UX Component - List Control - Configuring a List Control to Display Nested Lists - A new genie is available to configure a List to display a series of cascading Lists.

 

Watch Video - Introduction
Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

 

To select the Genie, create a new List, then select the 'Quick Access...' button at the bottom of the List Builder. Then select the 'List Quick Setup Genie'. This genie can be used to quickly configure a List that has a data source that defines hierarchical data to display a series of nested Lists.



UX Component - List Control - Static Data Genie - Nested List Data - A new genie is available to help you defined the static JSON data for a List that is intended to display a series of cascading Lists.

For example in the images shown below the List initially displays the data shown in the image on the left. When the user selects an item in the List that has a sub-list (indicated by the icon at the right edge of the List item), the List is repopulated with the sub-choices defined by the item that was selected and a 'back' button is shown. In order to implement a List that behaves in this manner, the List is populated with JSON data that defines the choices for each item in the List.

 



For example, for the List shown in the above two images, the following JSON data is used to populate the List.

 

[
    {
        display: 'Menu1',
        children: [
            {
                display: 'Menu1_A',
                action: 'Action_1'
            },
            {
                display: 'Menu1_B',
                action: 'Action_2'
            },
            {
                display: 'Menu1_C',
                action: 'Action_3'
            }
        ]
    },
    {
        display: 'Menu2',
        action: 'Action_4'
    },
    {
        display: 'Menu3',
        action: 'Action_5'
    }
]

 

Notice that the 'Menu1' item has a property called 'children' that defined the sub-choices for that item. The actual text displayed in the List is defined by the 'display' property in the JSON. Any item in the List can have a 'children' property.



It can be tedious to define this JSON data manually. The 'Nested List Genie' can help you define the JSON. Once you have the basic structure of the JSON defined, you can then make making further edits to the JSON manually. To get to the 'Nested Lists Genie', open the List builder, set the List Data Source to 'Static', click the smart field to open the Static Data dialog. Then click the 'Sample data' hyperlink at the bottom of the dialog (as shown in the image below).

 

 

 




UX Component - Sample Template - MobileAppFramework_with_SplitView_Hierarchical_Menu - When you create a new UX component, a new sample template is available. This template is similar to the MobileAppFramework_with_SplitViewMenu template. The only difference is that, unlike the MobileAppFramework_with_SplitViewMenu, which implements a 'flat' list of choices for the menu, the MobileAppFramework_with_SplitView_Hierarchical_Menu template implements a hierarchical list of menu choices.

 

UX Component - List Control - Paginated List - SQL Data - Change Page Size - You can now dynamically change the page size of a paginated List that is based on SQL data.

For example, say you want to change the page size of a paginated List (called, say, 'LIST1') to 20 records per page.

 

//get pointer to List object

var lObj = {dialog.object}.getControl('list1');

//set the new page size
lObj._state.pageSize = 20;'

//refresh the List

dialog.object}.refreshListData('LIST1');

 

 

 

 

UX Component - Embedded Report - HTML - Option Buttons - When a report is embedded into a UX component and is rendered as HTML, the report is displayed with a series of buttons that allow the user to print the report as PDF, export the report to Word or Excel, etc. There was no ability to control which of these buttons were shown. Now, when a report is embedded into a UX, the 'HTML report options' property allows you to control which button are shown.

 

UX Component - Persisting Variables to Local Storage - Variables to Omit - When you build a disconnected application using a UX component, it is typical to persist the variables (i.e. the Data Bound controls in the UX) in your component to Local Storage so that when the application is restarted, the variables (i.e. Data Bound controls) in the UX will have their values restored automatically from Local Storage. However, there may be certain variables that you do not want to persist to Local Storage. For example, your UX may contain a login section that contains a UserId and Password field. You might not want to persist the Password field to Local Storage.

The UX now has a new property that allows you to define an exclusion list. The Variables to NOT persist property in the Local Storage section (on the Properties pane) allows you to select a list of variables.

 

 

 

UX Component - Panels - .resize() Method - A new method has been added to allow you to force Panels (Cards, Layouts and Navigators) to resize themselves. Typically this is not necessary, but if the Panels were initially sized and then the window was resized (and a resize event was not triggered -- for example, the PhoneGap Statusbar plugin), then Panels will have been laid out based on incorrect size information and the .resize() method can be useful.

For example:

var obj = {dialog.object}.getPanelObject()
obj.resize();

 

 

UX and Grid Component - Date Picker - 'Today' Button - A new property in the Date Picker and the Calendar control (UX component) allows you to turn off the 'Today' button.

Web Security - Alpha Anywhere Server - Publishing Data - Publishing Roles - Publishing web security to an Alpha Anywhere server from the Publish genie or the Web Security menu "Publish Security Files" has new options. These are available only if using Optimized FTP publishing. You can now publish security roles without publishing the security tables. The options are:

The option to publish security tables is available in all publish profiles that publish to an Alpha Anywhere server.

UX Components - File Save Format - UX Components can now be saved as formatted JSON instead of binary (the default). Formatted JSON saves the properties in clear text. This is useful if you are using some type of source or version control system and the system has a method to show differences between versions. The save format can be selected in the UX Properties under 'Advanced-> Save component format'.

You can do a bulk conversion of the storage format by selecting the 'Edit, Bulk Operation, Change UX Component storage type' menu option when the Web Control Panel has focus.

 

Xbasic - Dot Variables - .set() Method - A new method has been added to dot variables to allow you to set properties on the variable. The .set() method complements the .data() method which is used for reading a property value.

Example

dim p as p

p.name = "Fred"

?p.data("name")

= "Fred"

p.set("name","John")

?p.data("name")

= "John"

p.set("city","Boston")

?p.city

= "Boston"

 

Reports - Free-Form Reports - UTF8 - SQL Data - Free-form reports that are based on SQL data can now use the full UTF8 character set. This means that reports can now, for example, easily include Chinese, Hebrew, Arabic and other characters on the same report. Previously this was only possible by setting the localization settings on the machine where the Application Server was running. Since you had to pick a particular locale that meant that you could not combine characters from different code pages (e.g. you could not have Chinese and Hebrew on the same report).

This feature can be turned off in web applications in the Project Properties dialog by un-checking the PDF Printing option to "Allow all international character in free-form reports".

For desktop applications, the option can be turned off in "View-> Settings-> Preferences-> Reports-> SQL Support All International Characters". When the feature is off, the reports will use temporary dbf tables for report data.
 

UX Component - Publishing Session Variable Values to Client Side - Ajax Callback - If an Ajax callback made a change to a session variable that had been published to the client-side the value of the session variable on the client-side is now automatically updated.

 

Application Server - Session Variables - Session.Sequence - A change was made to the way session variables are stored internally by the Alpha Anywhere server. This change should not affect any application.

This change makes the method used by the Alpha Anywhere server and the Alpha Anywhere Server for IIS the same and it opens the possibility for a future enhancement to the Alpha Anywhere server to use the IIS session state provider. This will allow for improved scalability and fail over (sessions shared across instances).

As a result of this change a new property is now available on the session object. Session.Sequence is a character value and is an unformatted string representation of a GUID. It will automatically be updated when a session variable is created, modified, or deleted.

UX Component - List Control - Detail View - Synchronizing in Batches -  Client-side Events - The client-side events for batch synchronization - afterSynchronizeListBatch and afterSynchronizeListBatch now both allow your Javascript to reference the e.countInfo object which has information in it about the number of records in each batch, the number of successful updates and the number of errors in the batch.

 

UX Component - Signature Control - .signatureIsEmpty() method - This method has been improved and it now gives accurate answers regardless of the browser that is being used. Previously, the method would be inaccurate for Chrome.

In addition, this method can now be used when the signature control is in 'signing' mode. Previously it could only be used after the user had clicked the 'accept' button to accept the signature.

You can also now pass in an optional second parameter to specify a length parameter The control is considered to be 'empty' if the base64 encoded value of the signature is less than the specified length. Note that even an 'empty' signature will have a non-null value for its base64 encoded value.

 

Reports - Calculated Fields - User Defined Functions - When you create reports you can define calculated fields that use user-defined functions in the calculate field expression.

Now, the user-defined functions that the report references can be defined in an Xbasic Function Library. Previously these functions had to be in an .aex file that was published along with the other files in the project.

Placing the Xbasic functions in a Function Library is more convenient than having to create an .aex file.

NOTE: This feature only applies to Project Reports (i.e. reports defined in the Web Projects Control Panel).

 

To attach an Xbasic Function Library to a report, right click on the report and select the Xbasic Function Library References.. command.

 

 

 

UX Component - Ajax Callbacks - Caching - When an Ajax callback is made to a component, the first thing that the Alpha Anywhere server does when handling the callback is de-serialize the component ( the .a5wcmp file). For very large components, the time taken to de-serialize the .a5wcmp file can be significant (perhaps as much as 200ms). Now, the de-serialized components are cached. As a result, the performance of Ajax callbacks will be improved.

NOTE: Caching is only used on UX component that do not user security or server-side show/hide expressions. For example, if you have a button that is only show to members of the 'Sales' group, caching is not used.

UX Component - List Control - Convert Data Source from Static to SQL or SQL to Static - A new genie in the List Builder allows you to convert the Data Source for a List from Static data to SQL or vice-versa. When you convert the data source from static to SQL, the following options are available:

When you convert the data source from SQL to Static, the following options are available:

 

PhoneGap Applications  - _phoneGapSettings() Function - In PhoneGap applications you can now call a special system function to return information about your PhoneGap application. For example, you might want to know if a particular option was selected, if a particular plugin was loaded or what the application id is.

For example:

To get the application id:

alert( 'app id: ' + _phoneGapSettings().appId );
 

To find out if the sqlite plugin was loaded:



var flagSQL = _phoneGapSettings().plugins['com.brodysoft.sqliteplugin'];

if(typeof flagSQL == 'undefined') flagSQL = false;

 

NOTE: When a PhoneGap application is built, a special .js file called _phoneGapSettings.js is created in the 'www' folder.



Below is a sample of the _phoneGapSettings.js file:


function _phoneGapSettings() {
    return {
        "appId": "com.yourCompany.yourApp",
        "preferences": {
        "permissions": "none",
        "orientation": "default",
        "target-device": "universal",
        "fullscreen": "true",
        "webviewbounce": "true",
        "prerendered-icon": "true",
        "stay-in-webview": "false",
        "ios-statusbarstyle": "black-opaque",
        "detect-data-types": "true",
        "exit-on-suspend": "false",
        "show-splash-screen-spinner": "true",
        "auto-hide-splash-screen": "true",
        "disable-cursor": "false",
        "android-minSdkVersion": "7",
        "android-installLocation": "auto",
        "phonegap-version": "3.7.0",
        "FadeSplashScreen": "true",
        "FadeSplashScreenDuration": "2",
        "EnableViewportScale": "false",
        "MediaPlaybackRequiresUserAction": "true",
        "AllowInlineMediaPlayback": "false",
        "TopActivityIndicator": "gray",
        "BackupWebStorage": "cloud",
        "iosPersistentFileLocation": "Library",
        "KeyboardDisplayRequiresUserAction": "true",
        "SurpressesIncrementalRendering": "true",
        "android-maxSdkVersion": "",
        "android-targetSdkVersion": "",
        "KeepRunning": "true",
        "splash-screen-duration": "5000",
        "ErrorUrl": "error.html",
        "LoadingDialog": "Please wait, the app is loading.",
        "LoadingPageDialog": "Please wait, the data is loading.",
        "LoadUrlTimeoutValue": "20000",
        "AndroidPersistentFileLocation": "Internal"
    },
    "plugins": {
        "battery-status": "npm",
        "console": "npm",
        "device": "npm",
        "file": "npm",
        "file-transfer": "npm",
        "geolocation": "npm",
        "inappbrowser": "npm",
        "media": "npm",
        "network-information": "npm",
        "com.phonegap.plugins.pushplugin": "pgb",
        "com.brodysoft.sqliteplugin": "pgb",
        "com.alphasoftware.plugins.camera.withexif": "pgb",
        "statusbar": "npm"
    }
    };
}

 

 

 

Xbasic - YELP API - You can make requests against the YELP API using Xbasic - The following example shows how to make a request against the YELP API:

Example:

The query syntax for the YELP API is described on the YELP website (see the YELP API dashboard).

Say that the syntax for the query you want to make is as follows:

https://api.yelp.com/v2/search/?location=lexinton ma&radius_filter=10000
 

This query will show businesses within 10,000 meters of Lexington, MA.

To perform this API query using Xbasic

1. Extract the URL from the query (everything up to the ?) and set the URL variable (in the code shown below) to this value.

2. DIM an Xbasic dot variable (DIM P  as p in the code shown below) and set properties in this dot variable for each parameter in the query string. Note that when setting parameter values, spaces in the parameter values must be converted to + signs.

dim p as p

p.location=stritran("lexington ma"," ","+")

p.radius_filter = "10000"

 

 

Here is the complete example:

 

dim ao as extension::OAuthClient

ao.consumer_key = "consumer key value - get from the YELP website"

ao.consumer_secret = "consumer secret value - get from the YELP website"

ao.oauth_token = "oauth token - get from the YELP website"

ao.user_secret = "user secret - get from the YELP website"

ao.oauth_signature_method = "HMAC-SHA1"

ao.url_encode_flags = "+plusspace"

url = "https://api.yelp.com/v2/search/"

dim p as p

p.location=stritran("lexington ma"," ","+")

p.radius_filter = "10000"

dim result as n

result = ao.Exec("GET",url,p4)

if result = 200 then

    dim jsonResponse as c

    'reformat the json response to make it readable

    jsonResponse =  json_reformat(ao.response_content)

    showvar(jsonResponse)

else

    showvar("Error")

end if


Once you get the response from YELP you can use the json_parse() function to get an Xbasic variable and then generate code to (for example) populate a List control on a UX component showing the results.

 

UX Component - {dialog.object}.refreshDropdownBoxChoices() Method - Refreshing Multiple Controls in a Single Ajax Callback - You can now refresh multiple Dropdown controls in a single Ajax callback. Previously, if you wanted to refresh the choices in multiple controls you had to make multiple Ajax callbacks.

There are two syntax options.

You can specify a comma delimited list of controls to refresh. For example:

{dialog.object}.refreshDropdownBoxChoices('COUNTRY,CITY')


Or, you can specify a JSON string. Using the JSON string method you can specify optional parameters for each Dropdown control.

For example:


var arr = [];
arr.push({ controlName: 'country');
arr.push({ controlName: 'city', dynamicFilter: 'country = \'usa\' or country = \'uk\''});
var json = JSON.stringify(arr);
{dialog.Object}.refreshDropdownBoxChoices(json)

 

Application Server - Configuration Changes - Many Application Server configuration changes are now effective immediately (without requiring a server restart)

Changes made to the Application Server's configuration are now effective as soon as those changes are saved, including when the server is currently running. This allows the server configuration to be modified without having to restart the server and interrupt user activity.

For example, many server administrators do not enable server logging in order to conserve disk space and other server resources. However, since logs are very helpful when an unexpected problem occurs, it is often times desirable to turn them on temporarily. Previously, this would require a server restart which meant either interrupting users of your applications or going without logging until some later time when the server became idle. Now changes such as this can be made with no impact on application users.

Some changes cannot be made effective without a server restart however. These are changes to the listening IP address or port, the server's license, and the SSL configuration.

IMPORTANT: Changes must be made through the Alpha Anywhere or Alpha Anywhere Application Server user interfaces. If the server's configuration file is directly edited then the changes will not be effective until either the server is restarted or changes are saved through the user interface.

 

UX and Grid Component - Auto-Suggest Control - Return Value - By default, the return value for an auto-suggest control is the same as the search field. Now you can specify a different return value than the search field.

PhoneGap App Builder - Status Bar Plugin (iOS)  - The Status Bar Plugin default behavior has changed to reflect the styling recommended by Apple for iOS 7 and greater apps. By default, the iOS status bar is now overlaid on top of the PhoneGap WebView. This will require the addition of a 20px spacer to a Panel header to accommodate the status bar. If you would like to set the behavior to the previous iOS 6 style, which does not overlay the WebView, you must set the properties for the status bar from within the onPhoneGapReady event in the Client-side events.

Example:

Add this code to the onPhoneGapReady event:

StatusBar.overlaysWebView(false);

StatusBar.styleDefault();

 

NOTE: While the PhoneGap documentation for the Status Bar plugin indicates that a preference setting within the config.xml file can be used to set the default behavior as required, this is not currently supported by PhoneGap Build.

 

IMPORTANT: The PhoneGap StatusBar plugin resizes the size of the WebView control asynchronously. That means that if your UX component uses Panels (which is very likely) the Panels will have been laid out using the original size of the WebView control. This will cause layout errors - most likely manifested as Panel Footers being incorrectly sized. Therefore, it is very important that you add this code to the onPhoneGapReady event to resize the Panels in your component. This code must be wrapped in a setTimeout() so that it runs after the Statusbar plugin has completed.

For example:

StatusBar.overlaysWebView(false);

StatusBar.styleDefault();


setTimeout(function() {
    var obj = {dialog.object}.getPanelObject()
    obj.resize();
},100);

 

 

 

 

 

UX Component - Action Javascript - File Upload - Amazon S3 Action - Alpha Anywhere Server - This action previously only allowed upload to S3. Now you can use the same action to upload files to the Alpha Anywhere server. In the case of the Alpha Anywhere server, you specify the name of an Xbasic function to call after each file us uploaded. This action allows you to select multiple files for upload. The files are all uploaded at once and separate progress bars are shown for each file. The Xbasic function will be called once for each file selected.

UX Component - PanelOverlay - zIndex Property - You can now specify an explicit z-index for a PanelOverlay. Previously the zIndex for a PanelOverlay was hard-coded to '4'. The default value has been changed from '4' to '6'. This means that it is possible that you might see a change in behavior when running a UX in that a PanelOverlay that was previously shown when another Panel was brought into view would now be hidden. To restore the prior behavior simply set an explicit value of '4' for the PanelOverlay's zIndex property.

 

Xbasic -  a5_word_merge_dotNet() Function  - Merge Data into Word Template - Merges data that results from executing a SQL query into a Microsoft Word template document.

IMPORTANT: You must install the Microsoft Office 2010: Primary Interop Assemblies Redistributable in order to use this function. http://www.microsoft.com/en-us/download/details.aspx?id=3508

 

Syntax:

p pResult = a5_word_merge_dotNet(c folder,c templateFile, c connectionstring,c sql,sql::arguments args [,l flagPortableSQL [c outputFilename]])

 

Where:

 

Example:

 

dim folder as c = "c:\data\wordMerge"
dim template as c = "Template.docx"
dim ConnectionString as C = "::Name::Northwind"
dim sql as c = "select customerid, contactname, address, city, region, country, postalcode, contactname as [salutation] from customers where country = :whatcountry"
dim args as sql::arguments
args.add("whatcountry","uk")
dim outputfilename as c = "Invoice for {customerid}"
dim pr as p
pr = a5_word_merge_dotNet(folder,template,connectionstring,sql,args,.t.,outputFilename)
 

 

The Xbasic source code for this function can be download here. The reason for including the source code is that it serves as a useful guide to calling .Net code from Xbasic and it allows developers to tweak the function to expose other Word features.

 

 

: UX and Grid Component - Building Real-time Applications - Web-sockets Server - Publish/Subscribe - The web-socket server functionality has been enhanced to support a publish/subscribe model. When a client-connects to the web-socket server they can specify the 'message types' that they are interested in receiving.

If the client is not subscribed to a particular 'message type' then when the web-socket server will not send any messages of that type to the client.

In the component properties, you can specify what message types the component should listen for.

You can use the Web-socket server actions in Action Javascript to dynamically change the types of messages that the component has subscribed to.

For example, in the image shown below, the component will be subscribing to messages of type 'messageboard' and 'alpha'

 

 

 

The 'message types' are completely arbitrary. When a message is sent, it is given a specific (arbitrary) message type.

For example, the code below sends a message of type 'myspecialtype':

 

var obj = {type: 'myspecialtype', messageText: 'this is the message};
{dialog.object}.wsclient.socket.send(JSON.stringify(obj));

 

Alpha Anywhere comes with certain 'built-in' message types. You can add you own built-in message types by writing a node.js handler for your user-defined message type.

The built-in 'messageboard' message type (for example) is written so that when the user connects to the web-socket server (or re-connects after having lost the connection) any messages of type 'messageboard' that were sent prior to their connecting are automatically sent to the client (assuming, of course, that the user has subscribed to messages of type 'messageboard'). The 'messageboard' special type is written to keep a certain maximum number of messages in is 'history' stack, but you can edit this value.

The custom message types are stored in the <Alpha Anywhere executable folder>\node_services\ws_queue folder.  For example, the 'messageboard' special type is in a file callled messageboard.js.

To add your own message type (called say 'type1') create file called type1.js in the ws_queue folder. Use the messageboard.js code as

 

The web-socket server actions in Action Javascript allow you to specify what message types to subscribe to when you select the following actions:

 

Using the Web-Sockets Server when Alpha Anywhere is Using a Load Balancer

A load balancer is commonly used to distribute incoming requests to one of several Alpha Anywhere Application Server instances running on a single Windows computer. Alpha Anywhere uses a Node.js server running on a different port in order to provide WebSockets functionality, so the load balancer will need additional configuration if you will be using WebSockets with your application. The URL used for your application points to the load balancer so it must know about all incoming traffic that is to be expected and passed along.

Configuring the load balancer to work with the WebSockets server is simpler than configuring it to work with the Alpha Anywhere Application Server instances because only one Node.js server is used. There is no balancing to be done, just allow the incoming traffic to pass through to the Node.js server. The load balancer should be configured to accept traffic on the port that has been specified in the web project properties and send that traffic to the same machine as the Alpha Anywhere Application Servers, but on the port specified. The exact configuration steps vary from load balancer to load balancer, but it is essentially the same as creating the alpha Anywhere Application Server load balancing that was already done but with just a single target.

 

 

Action Javascript - File Upload - Amazon S3 Storage Action - Base64 Encoded Data - Previously this action assumed that the user would select the files to be uploaded. The action has been enhanced so that you can now specify the file to upload by supplying base64 encoded data (which must be in the form of a data URI).

 

 

Tabbed UI - Initial State of Buttons Pane - If you specify that the Buttons Pane on the Tabbed UI can be collapsed, you can now specify its initial state.

 

 

The use case for this is typically when you have a Tabbed UI with integrated login. Before the user logs in you do not want the Buttons pane to display, but after login, in the afterLogin client-side event you want to display the Buttons pane. This is done by adding code to the client-side afterLogin event:

 

tbiObj.showTabbedUIMenuPanel(false);

 

Note that the .showTabbedUIMenuPanel() event is called with a false parameter to indicate that animation should not be used.

 

UX Component - Data Bound UX Component Quick Start Genie - You can now create a data bound (SQL Database) UX with full CRUD support using a quick start genie.

To get started, create a new UX component, go to the Controls pane and then click on the [Textbox] item in the toolbox on the left. The following dialog is shown:

 

 

Select the 'Create multiple new controls at once' option and then click the 'Populate list from a table' option.

 

The following dialog will be shown:

 

 

The highlighted properties are new. When the controls are added to the UX you can specify that a server-side action to load primary keys should be added to the onDialogIntialize event, that a server-side action to save submitted data to the database to which the UX is bound should be added to the afterDialogValidate event, that buttons to submit/cancel the UX should be added and that buttons to navigate from record to record in the bound table should be added.

This genie makes it much quicker to get started building a data bound UX component.

NOTE: You can also build UX components that perform CRUD operations by creating a List with a Detail View.

 

 

 

 

UX Component - Quick Find - When a UX component has a large number of controls, finding the control that you want to edit in the Tree View can be difficult. The existing Find feature (accessed by clicking the Find button on the toolbar) was not very helpful. The Find command has been re-implemented as shown in the image below.

To open the Quick Find dialog, click on the highlighted icon in the image below.

The tree view of your UX controls is shown below. You can filter this list by typing into the Filter box, or by clicking on one of the categories in the lists on the left.

You can then double click on an item in the tree view or click the Goto Control button.

 

 

PhoneGap App Builder - Added support for the latest CLI versions of PhoneGap - The PhoneGap App Builder has been updated to support the latest CLI versions of PhoneGap. As of early October, 2015 the latest CLI vesrion supported by PhoneGap Build is 5.2.0.

PhoneGap App Builder - Configuration options - Backup config.xml file - A new option has been added to the PhoneGap App Builder that controls the generation of a backup of the config.xml file when any changes are saved. The backup config.xml option is enabled by default. You may disable or enable this option as required. The backup config.xml files are stored in the projects resources folder and the files are date and time stamped. A .bak extension is included.



PhoneGap App Builder - Added support for the new NPM Plugin Registry - The PhoneGap App Builder has been updated to load all of the core PhoneGap plugins from the NPM registry. All prior versions of the PhoneGap App Builder loaded the core and 3rd party plugins from the PhoneGap Build Registry, which is being deprecated by PhoneGap in favor of NPM. If you are using any of the CLI versions of PhoneGap, the NPM core plugins are required. PhoneGap Build will no longer accept any updates to the plugins listed within the PhoneGap Build Registry.

Approximately 30% of the 3rd party plugins listed within the PhoneGap App Builder have been listed within the NPM registry by their respective authors and the PhoneGap App Builder will load those plugins from NPM when appropriate. Some of the plugins must still be loaded from the PhoneGap Build registry in order to work properly within PhoneGap Build. A new property has been added to all 3rd party plugins that identifies the registry that is being used. This information is available within the help of each plugin from within the builder.



All previous PhoneGap Build project config.xml files will be automatically updated to use the NPM listed plugins if they are used within a project. This includes the 3rd party plugins that have been updated to the NPM registry.

PhoneGap App Builder - Added support for the Android Crosswalk plugin - The Crosswalk plugin for Android is now supported. You must use one of the CLI versions of PhoneGap in order for this plugin to be enabled. Crosswalk replaces the Android WebView with the most recent revision of Chrome. This generally provides enhanced app performance and consistency among different Android devices.


json_filter() Function - Extracts or omits certain properties from a JSON string.

NOTE: Conceptually, this function is similar to the filter_string() function, except that it operates on JSON strings.

 

Syntax:

c result = json_filter(c json [, c properyNames [, L exclude]] )

 

Where:

 

Examples:

 

 

'extract object with a single field

dim json as c

json = <<%txt%

{

    one" : 1 ,

    two" : "TWO" ,

    three : [ 1 ,2 ,3 ]

}

%txt%
 

? json_filter(json,"one")
= {  "one" : 1}


? json_filter(json,"two")
= {  "two" : "TWO"}

? json_filter(json,"three")
= {  "three" : [ 1 ,2 ,3 ]}

'exclude a single field
? json_filter(json,"one",.t.)
= {  "two" : "TWO" , "three" : [ 1 ,2 ,3 ]}


? json_filter(json,"two",.t.)
= {  "one" : 1 , "three" : [ 1 ,2 ,3 ]}

? json_filter(json,"three",.t.)
= {  "one" : 1 , "two" : "TWO"}


'include multiple (comma separated) fields
? json_filter(json,"one,two")
= {  "one" : 1 , "two" : "TWO"}
? json_filter(json,"one,three")
= {  "one" : 1 , "three" : [ 1 ,2 ,3 ]}

 

 

compile_xbasic_function_library() Function - Allows you to use Xbasic Function Libraries in an .a5w page.

Syntax

 

p nameSpace = compile_xbasic_function_library(c functionLibraryName)

 

Where:

 

To call a function you must prefix the function name with the nameSpace. See example below.

 

Example:

 

<%a5

    dim p as p

    p = compile_xbasic_function_library('myFunctionLibrary');

    ?p.functionInMyLibrary()

%>

 

 

Amyuni PDF Printer Driver - Amyuni V5.0 - Windows 10 - Alpha Anywhere uses the Amyuni PDF Printer driver to produce PDF output from reports. Previously Alpha Anyhwere included V4.5 of the Amyuni Printer Driver. Alpha Anywhere now bundles V5.0 of the Amyuni Printer Driver. The V5.0 driver is compatible with Windows 10 whereas the V4.5 driver is not.

 

Grid Component - Sorting - Add Primary Key to ORDER BY Clause - By default, when you sort a Grid component, the Primary Key of the primary table for the SQL statement that the Grid is based on is now automatically added to the ORDER BY clause. This is done to ensure that even when the user sorts on a field that would not normally generate unique sort keys (e.g. user sorts on the 'City' column), that the sort keys are unique.

If you do not add the primary key to the ORDER BY clause and if the user sorts on a non-unique field, then when the user navigates from page to page in the Grid, it is possible for records that have appeared on a prior page to re-appear on a subsequent page.

You can control whether this feature is enabled or not by setting the 'Add primary key to all ORDER BY clauses' property on the Properties pane of the Grid Builder.
 

 

 

a5_copyLayout_to() Function - Can now be used without bringing up any UI.

The a5_copy_layout_to() function is used to copy a Report, Label, or Letter from one data dictionary to another (does not apply to 'Project' reports). This function brings up a user interface for the user to enter the target dictionary. Now, you can use this function programmatically, without bringing up a user interface.

 

Example:

a5_copy_Layout_to("Report","report1@c:\alphasports\customer.ddd","report2","c:\a5v12\packages\alphasports.ddd")


Where the arguments are:

 

 

: OData Support - Consume Data from OData Sources - You can now use standard AlphaDAO methods to access data exposed by OData data sources.
 

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

 

OData is a very popular standard for accessing data using REST calls. Alpha Anywhere now allows you to connect to OData services and then execute standard portable SQL code against the connection.  Obviously, the SQL that you execute is limited to functionality supported by the OData service. That means, for example, that while you cannot execute JOIN commands.

To use OData data, you define a named AlphaDAO connection string, and then select OData as the connection type.

The dialog will prompt for the Base URL of the OData service. Once you have the named connection string, you can then continue to build Grid and UX components in the same manner that you would for any SQL database.

 


 

: node_request() Function - Calling Node.JS Code From Xbasic - Node Code Defined at Project Level - The node_request() function allows you to execute some Node.js code.

The syntax is:

c Result = node_request(c NodeServiceName, p data [L flagRestartNode [, L flagShowNodeConsoleWindow]]);

 

Where:

 

Watch Video - Part 1
Watch Video - Part 2
Download Component

 

NOTE: Contrast this with the technique for running Node code shown in video XB_V12-3 "Calling into Node.JS from Xbasic". The technique shown in this video are for Node services defined at the Alpha Server level (the Node services can be called from any project), whereas the node_request() function discussed here is for Node services defined at the Web Project level.

 

IMPORTANT: The Node services must be defined in a special location in your Web Project. You must define the Node .js file in the Node\Node_Services folder in the Web Project.

Example:

Assume you have defined a Node service called 'hello' (name is case-sensitive). This service will be defined in a file called hello.js in the 'node\node_services' folder in the Web Project folder.

The contents of the hello.js file is:

 

exports.handler = function(packet,response,sendResponse) {
    var e;
    var attachments = null;
    var msg = 'Hello there <b> ' + packet.firstname + ' ' + packet.lastname + '</b>';
    response.result = msg;
    console.log(msg);
    sendResponse(response,attachments);
};
 

This is the standard format for a Node module.

 

Notice the following about the hello.js file:

 

To run this Node service from the Interactive window:

 

'define an object (i.e. an Xbasic dot variable) to contain the input parameters

dim p as p

p.firstname = "Fred"

p.lastname = "Smith"

'restart the Node service so that any edits to the hello.js file are picked up and show the console window

?node_request("hello",p,.t.,.t.)

 

The result, shown in the Interactive window will be:

{"_id":"e38bcc7c-581f-4b6b-9d13-d4da6eb0aa8a","error":"","result":"Hello there <b> Fred Smith</b>"}

 

This string is a JSON object that can be parsed:

 

For example:

dim json as c

json = node_request("hello",p)

dim pOut as p

pOut = json_parse(json)

showvar(pOut.result)

 

 

TECHNICAL NOTE: The node_request() function is actually a simple wrapper around these low level Xbasic commands:

dim n as helper::node

dim p as p

p._id = "some_unique_id"

p._command = "name of the Node service"

p.param1 = "value of parameter 1"

p.param2 = "value of parameter 2"

dim jsonCmd as c

jsonCmd = json_generate(p)

dim folder as c

folder = "fully qualified path to the  'node\node_services' folder"

n.request(folder,jsonCmd)

 

NOTE: The files in the 'node\node_services' folder in your Web Project are automatically published when you publish your application. When you do a Live Preview of a component you are working on and you choose the 'Full Preview' option from the menu, the files in the  'node\node_services' will also be published to the LivePreview folder in the server webroot.

 

 

: Client-side Data Cache - The client-side data cache allows you to define one or more 'data items' that are cached on the client-side so that you can reference this data in a UX component. The data in the data cache is in the form of Javascript arrays.

 

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3
Watch Video - Part 4
Watch Video - Part 5
Watch Video - Part 6
 

 

For example, you might define a client-side data cache with these items:

For each item in the data cache you specify the server side query that generates the JSON data for the data item. For example, you might specify that the data for the 'customer' data item is obtained by executing a SQL SELECT command against a SQL Server database.

The data for the 'orders' data item might be obtained by executing some custom Xbasic code that returns a string of JSON data.

The data source for a data item can be:

 

The data in a data-item can, optionally, be saved on the client-side so that it is available when you are running the application in disconnected mode. When you choose to save the data on the client, you have the option of storing the data in:

The amount of data that can be stored in local storage is limited. If you store data in a file on the device you will be able to store significantly more data than would be possible in local storage.

The UX has methods that allow you to refresh the data in a data item and to read the data from a data item into a Javascript array. When you read data from a data item into an array you can, optionally, specify filter and order conditions so that only 'records' that meet your filter criteria are in the array returned by the read method.

You can specify that the data in a data-item should be 'delayed'. This means that when the UX is initially rendered, the query for the data item is not performed and no data is initially sent to the client. Only when the user executes an explicit command to 'refresh' the data item will an Ajax callback to the server be made and then the data item query is performed and the data are sent to the client.

If you have specified that the data in a data item should be persisted to Local Storage, there is no way of knowing, at the time the query to get the data for the data item is performed, if the data that is returned to the client will actually be able to be stored in Local Storage - because there is not enough available space in Local Storage. Therefore, when you specify that a data item should be stored on the client side you can also specify an event handler that will get fired if the data could not be successfully persisted to Local Storage. This will allow you to display some UI to inform the user to enter more selective search criteria for the query that returns the data for the data item.

 

IMPORTANT: If you want to use the FileSystem option in a PhoneGap application you must include the Device, File and File Transfer plugins when you build your PhoneGap application.

 

 

Defining a Client-side Data Cache

To define a client-side data cache, you open the Client-side Data Cache Editor. There are two ways to open the editor. You can use the dropdown menu by clicking the Menu button, as shown below:

 

 

Or, you can click the smart-field for the 'Client-side data cache' property on the Properties pane in the UX builder

 

 

 

Client-side Data Cache Editor

The Client-side Data Cache editor, shown in the image below, shows the names of data items in the Data Cache. The dialog show summary information about each data item.

 

 

To edit an item in the Data Cache, click the 'Edit item' button, or double click on the item in the list. This will open the Data Item editor.

 

 

 

For each item you can specify:

 

Persisting Data

If the Delay query until explicit refresh property has been checked, the dialog shows additional properties that allow you to specify that the data item should be stored on the device.

 

 

 

The options for Store where are:

IMPORTANT: If you are persisting to the file system and you are using Xbasic to generate the data for the data items, be sure to generate properly formed JSON. For example: [ {"name" : "fred"} ] and not [ {name: 'fred'} ]

 

When Store data on device option is checked you can specify a Maximum payload size property. This is the maximum size (in bytes) that a query is allowed to return. If you specify the default value of -1 there is no maximum. This property is designed to allow you to protect against the user trying to download too much data to the device. When the

Maximum payload size property is set to some value greater than -1, the payloadSizeExceeded Javascript Event property is shown. You can put code in this property to alert the user that their query for the data item returned too much data and they they must enter a more restrictive query.

 

Other Settings

If any of the data items in your Client-side Data Cache are configured to store data in the file system on the device then you can set additional settings in the Other Settings tab of the Client-side Data Cache editor.

These settings control whether a progress bar is shown while the device is downloading the data from the server to be stored in files on the device.

If you are storing large amounts of data on the device you will generally want to show the user a progress bar so that they know that something is happening.

 

 

You can specify the color and width of the progress bar and you can also specify a placeholder or an explicit element id for the position of the progress indicator. Say for example, and element with an ID of 'progress1' and you want to display the progress indicator in this element, you specify the Placheholder for progress indicator as element:progress1

 

Before file download begins - This event fires after the Ajax callback to get the data for the data items that are being refreshed has completed, but before the device actually starts downloading data.

The use case for this event is as follows:

Say you have defined a Client-side data cache with a large number of data items, (or a few data items, some of which return a large amount of data.) The Ajax callback to refresh all data items will take some time on the server to complete. While the server is busy performing the queries to get the data in the data items, the user has no indication that anything is happening. So, it is likely that you will want to display a wait.. dialog when the user clicks a button to refresh the data in the data items (which triggers the Ajax callback to the server). Once the server has obtained all of the data it sends a response back to the client telling the client to start downloading the data. At this point the progress indicator will start moving, giving feedback to the user. The Before file download begins event will allow you to dismiss the wait... dialog (since it is no longer needed -- the user can now watch the progress indicator).

 

Action Javascript

Action Javascript allows you to perform several actions on data items in the Data Cache. Select the 'Client-side Data Cache Actions' action from the list of available actions.

 

 

Then in the editor, select the action type:

 

The actions currently currently supported are:

 

Read Data Action

The builder for the Read Data action is shown below. You specify the name of the data item you want to read and then you define the Javascript code you want to execute once the item has been read. You code can reference data - a Javascript array that contains the data in the data item.

 

The filter allows you to define an arbitrary filter to filter the data. The filter builder dialog is shown below. The filter is in the form of a Javascript expression that evaluates to true or false. Fields in the data item are referenced with the data. prefix. In the screenshot shown below only records in London or Berlin are included in the data array passed to the onSuccess event handler.

 

 

The order allows you to define an arbitrary sort order for the data in the data array. The order builder is shown below:

 

 

The order builder allows you to define a multi-level sort. It also allows you to parse numeric, logical and data strings into data of the correct type so that the data are ordered correctly. For example data values in your data cache might be in form of date strings (e.g. 12-31-2015). In order to sort these values correctly, they have to first be parsed into real date objects.

 

Data Cache Methods

The UX object has several methods for working with data items.

 

Refreshing Data-cache items:

{dialog.object}.refreshDataCacheItem(listOfItemsToRefresh, onCompleteFunction)

 

Where:

 

Reading a data-cache item:

{dialog.object}.getFromDataCache(itemName,onSuccessFunction, onFailFunction, filter, order)

 

Where:

Here is an example of the filter parameter specified as a string:

var _filter = 'data.Country == "USA" || data.Country = "France"';
 

Here is an example of the filter parameter specified as a function:

var _filter = function(data) {
if(data.City == 'Boston') return true;
    else return false;
}
 

Here are examples of the order parameter specified as an object:

//sort by City, then by Lastname (descending)
var _order = {'City' : 1, 'Lastname': -1};

 

//sort a date string that is in the format MM-dd-yyyy

var _order = {'DateOfBirty:date:MM-dd-yyyy' : 1);
 

Here is an example of the order parameter specified as a function:

//sorts by Lastname, then by DOB ( a date field with a format of MM-dd-yyyy) in descending order
 

var _order = function(a,b) {
    if(a.Lastname > b.Lastname) return 1;
    else if(a.Lastname < b.Lastname) return -1;
    else {
        if(new Date().fromFormat(a.DOB:date:MM-dd-yyyy,'') > new Date().fromFormat(b.DOB:date:MM-dd-yyyy,'')) return 1;
        else return -1;
   }
}
 

 

 

: UX and Grid Component - Building Real-time Applications - Web-sockets Server - You can now build 'real-time' applications by enabling a 'web-sockets' server to broadcast messages to all 'connected clients'.

Use cases for  'read-time' applications include:

 

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

 

In a typical web-application, the server can only respond to a request from a client. The server cannot push information to clients. But in web-socket applications, the server and the client can establish a permanent 'channel' that allows the server to send messages to all of the connected clients.

In addition to the server, all of the other connected clients can send messages and all of the connected clients will receive the messages.

To turn on web-socket server support in your application you must first go to the Project Properties dialog:

 

Then navigate to the 'Web-socket Applications' section and turn on web-socket applications and specify the port that the web-socket server should run on. This needs to be a different port than your Application Server. Be sure to specify a port that is not in use.

 

 

Web-socket support must then be turned on at the individual UX or Grid component level. For a UX component, go to the Properties Pane, Advanced section and check the 'Web-socket server' property.

 

 

For a Grid component, go to the Grid, Properties pane and check the 'Web-socket server' property.

 

 

 

Once the 'Web-socket server' property has been checked, when the UX or Grid component is run, it will automatically launch the web-socket server (if it is not already running) and it will start listening for messages. When a message is received, the client-side webSocketOnMessage event will fire and your Javascript code can decide what (if anything) to do with the message.

 

Web-socket Client-side Events

The UX and Grid components have method for web-socket server applications. These methods are:

 

Web-socket Server - Action Javascript

Action Javascript has actions for the web-socket server. The Web-sockets Server Actions option allows you to perform the following actions:

 

 

web_socket_server_sendMessage() Function

The web_socket_server_sendMessage() Xbasic function can be used to broadcast messages to all connected-clients.

The syntax is

P pResult = web_socket_server_sendMessage(C message)

 

Where

pResult - object with two properties - error (.t. or .f.) and errorText.

message - message text to send

 

: UX Component - List Control - De-select a Row - If a row in a List has been selected, and the List allows NULL selection, you can now set a property to de-select the row (so that no row is shown as selected) by clicking on the selected row a second time.

 

 

: UX Component - List Control - Loop Navigation - You can now set a property in a List to turn on 'loop navigation'. With loop navigation, if the last row in the List is selected and the user presses the 'down' key, focus will go to the first row in the list (if Loop navigate null selection is unchecked) or will be set to NULL (if Loop navigate null selection is checked)

 

 

 

: UX Component - List Control - Dynamically Set Columns Shown in List - A new helper method has been added that allows you to dynamically set the columns shown in a List and populate the List with some data. The columns are based on the data with which you are populating the List.

For example, assume you have a List and you have a Javascript variable with this data:

 

[
    {
        "Firstname": "John",
        "Lastname": "Smith",
        "City": "Boston",
        "State": "MA"
    },
    {
        "Firstname": "Henry",
        "Lastname": "Rhodes",
        "City": "New York",
        "State": "NY"
    },
    {
        "Firstname": "Allison",
        "Lastname": "Berman",
        "City": "Los Angeles",
        "State": "CA"
    }

]

 

The 'columns' in the above data are Firstname, Lastname, City and State.

You might want to populate the List with this data and simultaneously set the display columns in the List to Firstname, Lastname, City and State.

At some later point you might have another Javascript variable with this data:

 

[

    {"Name" : "Fred Smith", "Age" : 30},

   {"Name" : "Tim King", "Age" : 23}

]

The 'columns' in the above data are Name and Age. You might want to populate the same List with this data and simultaneously set the display columns in the List to Name and Age.

 

The {dialog.Object}.setListColumnsAndPopulate(listName,data,options) method can be used to populate the List and set the List columns (based on the columns in the first row of data).

 

Examples:
 

var data = [
    {
        "Firstname": "Kathy",
        "Lastname": "Morton",
        "City": "New York",
        "State": "NY"
    }
];

//populate List 'mylist' with the first 3 columns in data
var ops = {columnCount: 3};
{dialog.object}.setListColumnsAndPopulate('mylist',data,ops);

//specify columns
var ops = {columns: ['Firstname','State']};
{dialog.object}.setListColumnsAndPopulate('mylist',data,ops);



 

: AlphaDAO - ToJSONFile() Method - A new method has been added to both the SQL::Connection and SQL::ResultSet object to create a file in JSON format with the data in a query.

 

Example:


dim cn as sql::Connection

?cn.open("::Name::Access_Northwind")
= .T.
?cn.tojsonfile("c:\temp\cncustomer.json", "select * from customers")
= .T.
 

 

: PhoneGap Shell - Memory Management - The sample PhoneGap shell component, used for testing UX components that use PhoneGap features, has been improved. Now, when you go back to the menu screen to load a different UX for testing, the UX that you were using is completely removed from memory. This will prevent the PhoneGap shell from becoming sluggish after you have cycled back and forth from the main menu to a test component several times.

 

: PhoneGap Builder - Android APK Version Code Property - A new property has been added to the PhoneGap Builder that allows you to define the APK Version Code.



This code is required for Android apps published to the Google Play store and it must be unique for each version/update that your submit to Google Play. If you fail to change the APK version code, your app submission to Google Play will be rejected.

: PhoneGap Builder - 3rd Party Plugins - Camera With Exif Plugin - The Camera with Exif plugin has been added to the PhoneGap 3rd party plugins.



The Camera With Exif PhoneGap plugin, developed by Alpha Software, is a modified version of the cordova-plugin-camera that provides the addition of the EXIF and geolocation metadata to all camera and gallery images and returns this metadata along with the image file URI to the success callback. This allows the image metadata to be stored to a database along with the image or the image file reference. The metadata does not need to be parsed from the image itself because it is included in the success callback.

See GitHub: cordova-plugin-camera-with-exif for the full documentation.

 

TIP: If you use the Image Capture - Camera/Photo Library action in Action Javascript and you use the Camera with Exit plugin, then when you write the Javascript code for the Javascript to execute when image has been captured property, you will be able to reference this variables in your code:

 


 


: PhoneGap Builder - 3rd Party Plug- ins - Media With Compression plugin - The Media With Compression plugin has been added to the PhoneGap 3rd party plugins.



The Media With Compression plugin, developed by Alpha Software, is a modified version of cordova-plugin-media that provides the ability to record and play back audio files on a mobile device. This plugin adds MPEG4 compression to both iOS and Android audio recording, making the recordings compatible for playback on either an iOS or Android device and within most modern browsers. MPEG4 compression typically results in a significant reduction in the recorded audio file size when compared to the stock Media plugin. The reduction in file size is required for efficient online/offline storage and retrieval of the audio files.

See GitHub: cordova-plugin-media-with-compression for the full documentation.
 

 

Web security - E-mail  - The data recovery options in web security can be configured to send an email to the user with the requested data. Previously, this process could only use an email profile configured on the Application server. Email can now be sent using email settings defined in the Web Security Settings, email settings defined in the Web Project Properties, or using Mandrill in addition to a defined profile.


UX Component - PhoneGap - Image Picker Plugin - A new plugin is now available in the PhoneGap Builder. The Image Picker plugin can be used to select multiple images from the Photo Library. The typical use case for this plugin is in a disconnected application where you want to add an image to a record, but instead of adding one record with an associated image at a time (to a List control with an associated Detail View), you want to select multiple images at once and then automatically add a new record to a List for each selected image and associate each new record with one of the selected images.

You can watch videos demonstrating this use case here:

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

 

The Image Picker plugin is invoked with this Javascript function:

window.imagePicker.getPictures(successFunction, failureFunction, options);

 

To see the options supported by the plugin do a Google Search on the PhoneGap Image Picker.

Here is how the image picker is used to add a new row to a List control for each selected image. In the code example below, the field in the List that contains the image filename is imageChar.

 

 

function getImages() {
    var success = function(results) {
    //add the selected image names to the child List.
    for(var i = 0; i < results.length; i++) {
        var _d = {};
        _d.imageChar = results[i];
        var lObj = {dialog.object}.getControl('LIST1');
        lObj.addTableRow(_d);
        }
    }

    var fail = function(error) {
    }

    var settings = {width: 800};
    window.imagePicker.getPictures(success,fail,settings);

}
 

In the above example, the imageChar field in LIST1 should be set to an Image control type (on the Fields tab in the List builder). Also, when is LIST1 synchronized, you can upload the selected images to either Amazon S3, or to the Alpha Anywhere server. See the medial files property on the Detail View tab in the List builder for LIST1.
 

PDF Printing - Windows 10 - Microsoft PDF Printer - Windows 10 includes a PDF printer driver. This printer driver can be used instead of the Amyuni PDF printer driver that is bundled with Alpha.

You can set Alpha Anywhere to use the Microsoft PDF printer by going to the View/Settings menu in the Development version and then selecting Preferences/Reports/PDF Driver.

 

 

 

For the Application Server there is no UI currently to set the preferred PDF printer. Instead you can open the Interactive Window by right clicking on the Alpha Anywhere Server icon in the system tray and then entering these commands:

 

dim p as p

registry.load_settings("preferences",p)

p.reports.pdf_driver = "Name of the driver you want to use"

registry.save_settings("preferences",p)

 

 

where 'name of the driver you want to use' one of:

 

AMYUNI printer driver

Microsoft Print to PDF

Microsoft XPS Document Writer

 

 

 

UX Component - Watermark - Dynamically Setting the Watermark - .setWatermark() Method - A new method has been added to controls that have a watermark property that allows you do dynamically change the watermark text.

For example, say you have a control called 'LASTNAME' and you want to set its watermark property.

var obj = {dialog.object}.getControl('LASTNAME');

obj.setWatermark('Enter your last name');

 

In the case where the watermark text contains international characters, you must use a unicode encoded value. For example, to set the watermark text to 'Prénom', you would use:

var obj = {dialog.object}.getControl('LASTNAME');

obj.setWatermark('Pr\u00E9nom');

 

TIP: To get the unicode encoded value of a string you can go to the Tools menu when the Web Control panel has focus and select the Open text encoder window menu command. The encoded string will be of this form:  Pr{unicode}00E9nom. Replace {unicode} with \u.

 

 

PhoneGap - PhoneGap Shell - Alpha Anywhere Developers enjoy a very rapid design-test cycle. You can test a component you are working on by simply going to the Working Preview or Live Preview tab in the builder. However, when you are working on a PhoneGap application and you want to test any PhoneGap specific functionality in your component (such as accessing the native file system on a device), you cannot test your application in the Working Preview or Live Preview tab. You have to create a PhoneGap application and then install the PhoneGap application on your mobile device. This is a time consuming process.

Using a PhoneGap shell you can dramatically shorten this cycle. The basic idea behind the shell is that you build the PhoneGap shell once and install it on your device. You then dynamically load the UX that you are developing into a Panel in the PhoneGap shell. If you make a change to your component, you can simply click the Refresh button on the PhoneGap shell and the new version of your component is loaded. You don't need to submit the component to PhoneGap build.

Alpha Anywhere now ships with a sample PhoneGap shell that you can use for testing your UX components on a device.

Watch Video - Part 1
Watch Video - Part 2

 

When you create a new UX component, you can select the PhoneGap-Shell.

 

 

Once you have created a new UX using the PhoneGap shell template, save the component using any  name that you want. The next step is to build a PhoneGap project from your shell UX component.

When you build your PhoneGap project it is extremely important that you set the URL For All Ajax Callbacks correctly. If you do not set this property correctly, your shell will not work - it will not be able to dynamically load the UX component that you want to test.

 

 

It is also important that you specify the plugins that your components will need when you build the PhoneGap shell. That's because the dynamically loaded components cannot load PhoneGap plugins.

For example, assume that you are building a UX component that uses the SQLite PhoneGap plugin. You will need to ensure that this plugin is selected when you build the PhoneGap shell.

Obviously, you can't know ahead of time what plugins the components you are going to build in the future will need. So, from time to time you will need to rebuild your shell component to specify a different set of plugins to load.

 

 

When you open the PhoneGap shell on your device, it will look something like this.

Since you have not previously loaded any UX components, the list is empty.

Click the Add button and enter the name of the UX component you want to test.

 

 

 

Here is what the List will look like after entering the name of a UX component called 'ux1'.

 

 

'

 

 

Now, to run this component in the shell, simply tap on the row in the List.

 

The shell will transition to a new Panel and load the component into the Panel as shown below.

 

 

If you make any changes to the 'UX1' component that you are testing, simply republish the component then hit the 'Refresh' button. If you want to load a different component into the shell, tap the 'Back' button, and add the component name to the List.

 

UX Component - PhoneGap File Download Action - Force Download Property - The 'Force download if file found on device' property allows you to force the file(s) to be downloaded even if a file with the specified name is already on the device. If you force download, the existing file(s) on the device will be overwritten. Previously, if a file with the specified name was found on the device, the source file was not downloaded.

 

 

Bugs

AlphaDAO - MySQL - Stored Procedures - Multiple Resutsets - If you create a MySQL stored procedure that returned multiple resultsets, the SQL::Resultset.nextResult() object failed. As a result you could only read the first resultset returned by the stored procedure.

Web Applications - Repository Database - Case Sensitive Databases - If you configured your Web application to use a Repository database (for example, to save searches in a Grid component) and your defined the repository tables in a SQL database that case case-sensitive for table and column names, saving data to the repository did not work.

Script Editors - Windows Server 2008 - The status bar in the Xbasic and Javascript Script editors contain several 'hot' areas that you can click on to navigate to a line in the script or navigate to a particular function in the script. These 'hot' areas did now work on Windows Server 2008.

UX and Grid Component - Live Preview - In some cases if the browser you selected for Live Preview was installed as a 64 bit program, the selected browser was not found. This is now fixed.

 

UX Component - List with Detail View - Local Storage - Minify - If the minify option was turned on to compress the data stored in Local Storage when a List's data was updated, under some circumstances you could be sync errors when syncing a List's data after restoring the List data from Local Storage.

Xbasic - Stringdictionary Object - Clearing Existing Entries when Initializing - When the stringdictionary object was initialized (using its .initialize() method) , existing entries in the stringdictionary were not being cleared out. Now, they are. An optional flag has been added to the initialize() method to allow you to specify that existing entries should not be cleared out.

Example:

 


dim map1 as c = "alpha=this is alpha"
dim map2 as c = "beta=this is beta"
dim sd as stringdictionary
sd.Initialize(map1)
?sd.get("alpha")
= "this is alpha"

?sd.get("beta")
= ""

sd.Initialize(map2)  'clear out existing entries
?sd.get("alpha")
= ""    'because existing entries were cleared

?sd.get("beta")
= "this is beta"

sd.Initialize(map1,.f.) 'do not clear out existing entries
?sd.get("alpha")
= "this is alpha"
?sd.get("beta")
= "this is beta"   'because existing entries were NOT cleared
 

UX Component - Action Javascript - File Upload Action - Repeating Section - Fixed a problem when using the File Upload action in a Repeating Section.

UX and Grid Component - Action Javascript - Send E-mail  Action - If you used the Send-mail action multiple times on a component, the settings for the last instance were used for all instances.

UX Component - Image Capture - Character Fields - PhoneGap - In a PhoneGap application if captured images were uploaded to the Alpha Anywhere server (as opposed to Amazon S3), the images would not render correctly after the component was refreshed.

UX Component - Image Capture - Character Fields - Thumbnails - If you were capturing images in a character field and you had specified that you wanted to create thumbnails for the image and the stored filename expression for the field was <Shortname> (as opposed to <Fieldname>), the thumbnail was not created correctly.

UX Component - Panels - Google Map - Touch Events - When a Google Map is displayed in a PanelCard, certain touch events on the Map that the Google Map should have responded to were not being seen by the Map control.

Report Preview - Two Page Preview - When you switched to Two Page preview mode, a 'Print Progress' dialog was displayed. This dialog could not be dismissed and should not have been displayed.

Runtime - Debug(1) - In a Runtime application, if a debug(1) statement was inadvertently left in some user-defined code, Alpha would hang.

Grid Component - QBE - Hidden Columns - Fixed a problem in the generated HTML for the QBE feature if a Grid contained hidden columns.

Web Applications - Publishing - FTP Publishing - History - In certain cases the History list was not being maintained correctly when using FTP publishing. As a result of the bug, files were published in some cases when they did not have to be published.
 

UXComponent - Hierarchical Lists with Detail View - Data Synchronization - Fixed errors that occur under certain circumstances if the initial sync returns sever-side validation errors and then a subsequent sync is performed after the validation errors are corrected.

Oracle CLOB Fields - Limit of 4000 Characters - When reading data from an Oracle CLOB field, only the first 4,000 characters were read. This is now fixed.

Xbasic CURL Genie - Fixed an issue in converting certain CURL statements to Xbasic.

international_days_of_week() Function - This function was returning the days in the incorrect order when with a specific start of week day. For example:


?international_days_of_week("start-monday,short")

= Mon

Tue

Wed

Thu

Fri

Sun

Sat

 

UX Component - List Control - Detail View - Synchronizing in Batches - If a UX contains List controls that are in a parent-child hierarchy, and the parent List is configured to synchronize data in batches, then there were errors when the data was submitted that prevented all dirty rows from being synchronized. This error was only if the List was set to synchronize in batches.

Grid - Export Data - Security - The export function was not honoring security settings for columns in a Grid.

Web-Sockets Server - Fixed a bug where the web-sockets server was not starting correctly if the user was running the application on the default port (i.e. the URL for the application did not specify an explicit port).

UX Component - Repeating Sections - Xbasic Validation - Immediate Validation - Improvements were made in how immediate Xbasic validations are performed on fields in Repeating Sections.

 

Grid and UX Component - Searching SQL Databases - 'Is blank' and 'Is not blank' Search Options - The generated SQL for the 'Is blank' and 'Is not blank' search options has been changed to:

 

 

Previously, the generated SQL was:


 

The change was made because in some Oracle databases the previous generated SQL did not return the expected results. The stringLength() function is a portable SQL function.

Alpha Anywhere Server - 500 Error - Fixed an error that would, under some circumstances, cause the server to crash with a 500 Error. Also improved server memory utilization.

UX Component - Data Bound - Repeating Sections - Unbound Controls - Default Values - If you had unbound controls in a Data Bound UX component and you had set default values for the unbound controls, then when UX was initially rendered and the data bound controls were set to their bound values, the unbound controls did not show their default values. If the component did not use Repeating Sections, this bug did not occur.

UX and Grid Component - jQuery - Internal Version - The version of jQuery and jQuery UI that Alpha Anywhere includes when you choose the 'built in' version have been updated to jQuery 1.11.3 and jQuery UI v 1.11.4.

UX and Grid Component - Oracle - Search for Records that End with '_ some character' - A user was trying to search for records in an Oracle table that ended with '_1'. This was failing because SQL treats the _ as a wildcard character. To perform the search the search has to be entered as '\_'. Alpha Anywhere will now automatically add the ESCAPE '\' clause to the generated SQL statement for Oracle.

UX Component - Signature Capture Control - Initially Hidden - If the Signature Capture control was initially hidden when the UX component was rendered, but was then made visible by some Javascript, in some cases, it did not work correctly.

UX Component - List Control - .addTableRow() Method - Fixed issues with the .addTableRow() method when the rows were being added to a child List control.

UX and Grid Components - Google Maps - Google made some changes to the Google maps API fairly recently, and now recommends a different URL to access the API. They also changed Google Premier and now use a "key" value in the URL instead of "clientId". The existing code added the ClientId property which has been deprecated. The URLs generated by the UX and Grid to access the Google Maps API have been updated to reflect the changes Google made.

Another issue occurred if the map was run on a server using SSL, but was not set to use SSL. Most browsers blocked the request for the API JavaScript. A change has been added to force the Google URL to SSL if the server is using SSL in places where the link is built at run time.

The standard public Google map access will throttle map requests, and currently that public access limit is listed at 2,500 requests per day.

The latest Google method to get a higher limit is to sign up for a Google developer account (previously called Google Premier), create a project (free), and then activate the Google Maps JavaScript API. This will create a special API key that can be added to any Alpha Anywhere Map configuration in the builders as the "Google Premier ID". If you use an API key, Google tracks the number of requests, but allows a much higher free limit, currently listed as 25,000 per day. For large companies, they do start charging if the requests exceed that limit. If a key is not provided, the standard public map access will be used.
 

UX Component - Auto-suggest Control - Fill in Fields - The fill in fields were only filled in if you selected from the auto-suggest list by clicking on a row in the suggestion list. If you typed in a matching value (and did not select by clicking on the suggestion list), the fill-in values did not fill in.

UX Component - List Controls - List with Parent List - Pre-fetched Data - Arguments in Child List WHERE Clause - Fixed a bug where you would get an error after synchronizing data in a List with a Detail View if the SQL for the List used arguments in the WHERE clause.

 

Tips

AlphaDAO - Stored Procedures - Output Arguments - When you use execute SQL statements from Xbasic using AlphaDAO it is very common to use the SQL::Arguments object to pass parameter values to the SQL statement that you execute. For example

dim args as sql::arguments

args.add("customerId","alfki")

dim cn as sql::connection

dim flag as l

flag = cn.open("::Name::Northwind")

dim sql as c

sql  = "Select * from customers where customerId = :customerId"

flag = cn.execute(sql,args)

 

In the above example, the argument (customerId) is termed an 'input' argument - it is passing a value to the database engine.

However, Alpha Anywhere also allows you to create 'output' arguments and 'inputOutput' arguments. These argument types are used when you want the database engine to return a value to Xbasic.

Watch Video - Part 1
Watch Video - Part 2

 

For example, consider the following (very simplistic) stored Procedure defined in a SQL server database:

 

CREATE PROCEDURE [dbo].[output]

-- Add the parameters for the stored procedure here

@Param1 integer output,

@Param2 varchar(30) output

AS

BEGIN

-- SET NOCOUNT ON added to prevent extra result sets from

-- interfering with SELECT statements.

SET NOCOUNT ON;

-- Insert statements for procedure here

set @Param1 = 100

set @Param2 = 'Hello world'

return

END

 

In this stored procedure, the parameters (Param1 and Param2) are being set.

Here is how an Xbasic script could call the stored procedure and get the value of the parameters set in the stored procedure:

 

dim args as sql::arguments
 

'define to arguments, 'inout' and 'inout2' as inputOutput arguments
args.add("inout",0,sql::ArgumentUsage::inputoutputargument)

 

'notice that a dummy value of the correct size needs to be defined for the argument
args.add("inout2",replicate(" ",40),sql::ArgumentUsage::inputoutputargument)

dim cn as sql::Connection
cn.open("::Name::sqlserver_northwind")
 

'call the stored procedure and pass in the two argument values
?cn.Execute("exec output :inout, :inout2",args)
= .T.

?args[1].data
= 100

?args[2].data
= "Hello world"

 

If the size of the argument is not big enough then when you execute the stored procedure you might get an error like this:

?cn.CallResult.text
= "Internal Error - Data Truncated - The buffer for receiving data is too short"
 

In some cases your stored procedure will also return one or more resultsets in addition to setting the value of output arguments.

Depending on the database you are using you might have to read each of the returned resultsets before you can read the values in the output arguments.

For example, consider the following modification to the above stored procedure:

 

CREATE PROCEDURE [dbo].[output]

-- Add the parameters for the stored procedure here

@Param1 integer output,

@Param2 varchar(30) output

AS

BEGIN

-- SET NOCOUNT ON added to prevent extra result sets from

-- interfering with SELECT statements.

SET NOCOUNT ON;

-- Insert statements for procedure here

set @Param1 = 100

set @Param2 = 'Hello world'

select * from customers

select * from orders

return

END

 

This stored procedure now returns two result sets.

 

Below is the Xbasic to execute the stored procedure and get the values from the output arguments:

 

dim args as sql::arguments
args.add("inout",0,sql::ArgumentUsage::inputoutputargument)
args.add("inout2",replicate(" ",50),sql::ArgumentUsage::inputoutputargument)
dim cn as sql::Connection
cn.open("::Name::sqlserver_northwind")
?cn.Execute("exec output :inout, :inout2",args)
= .T.
 

'value of the output arguments not yet available because we have

'not read the resultsets
?args[1].data
= 0
?args[2].data
= ""

dim rs as sql::ResultSet
rs = cn.ResultSet
 

'still not available
?args[1].data
= 0
?args[2].data
= ""

'get the next resultset
?rs.NextResult()
= .T.
 

'still not available
?args[1].data
= 0
?args[2].data
= ""
 

'no more resultsets to read
?rs.NextResult()
= .F.
 

'argument value are now available!!
?args[1].data
= 100

?args[2].data
= "Hello world"

 

 

Web Applications - Windows 10 - Acrobat PDF Viewer - Internet Explorer 11 - Unlike Chrome and Firefox, Internet Explorer 11 does not have a built-in PDF viewer and therefore it relies on Adobe Acrobat Reader to display PDF files. On some machines, when you try to view a PDF report in IE, Acrobat will not open. You will need to turn off 'Enhanced Protected Mode' in IE11 to solve this problem. For more information, see this post.

 

UX Component - Panel Cards - Vertically Centering a Container - A common requirement when building mobile applications is to vertically (and horizontally) center content in a Panel Card.

Watch Video
Download Component

 

For example, in the image below, the content in the blue frame is always vertically and horizontally centered, regardless of the device orientation.

 

 

This is achieved by putting the following code in the onSize event of the Panel Card that contains the container.

Assume that the content to be centered is in a container called CONTAINER_1 and that the in-line style on this container has been set to 'visibility: hidden'. Setting the visibility to hidden will prevent the container from being seen until it is correctly positioned.

 

 

if({dialog.object}) {
 var p = $(this.contId + '.BODY');
 var v = {dialog.object}.getPointer('CONTAINER_1');
 var ph = p.offsetHeight;
 var vh = v.offsetHeight;
 var pw = p.offsetWidth;
 var vw = v.offsetWidth;
 var offsetH = (ph-vh)/2;
 var offsetW = (pw - vw)/2;
 v.style.left = offsetW + 'px';
 v.style.top = offsetH + 'px';
 v.style.visibility = '';
 v.style.position = 'absolute';
}

 

 

Windows 10 - Default Printer - PDF Printing - When you save a report as a PDF, Alpha Anywhere uses the special 'AlphaFive' printer driver that is automatically installed with Alpha Anywhere. After the report has been saved to PDF the default printer (that was defined before the report was saved) is restored. On Windows 10 this does not work because of a change Microsoft made. After the report has been saved to PDF, the default printer is now set to the AlphaFive printer. To disable this new Microsoft feature, see this document.

 

AlphaDAO - Microsoft Access - Can't Load ODBCJI32.dll Error - If you have installed Office 365 on your computer you might find that you can no longer connect to a Microsoft Access database.

To fix the error you will have to install the Microsoft Access Database Engine.

Here is a link to the installer on the Microsoft site.

If you already have the Microsoft Access Database Engine installed, then running a 'Repair' on the engine should fix the problem.

 

 

 

Working with XML Data in Xbasic - JSON_from_XML() Function - Xbasic has extensive support for parsing XML data. However in some cases, the Xbasic XML parsing features are too granular and you might want a quick and simple way to convert an XML document into an Xbasic object (i.e. dot variable). The xml_from_json() function provides such a mechanism.

 

Here is an example of some simple XML that is first parse into a JSON string which is then parsed into an Xbasic object using the json_parse() function.

 

dim xml as c
xml = <<%html%
<customers>
    <customer>
        <name>Dion Jones</name>
        <city>Boston</name>
        <more attribute1="val attr1" attribute2="val attr 2">More for Dion Jones</more>
    </customer>
    <customer>
        <name>Donald Trumpet</name>
        <city>Washington</name>
        <more attribute1="val attr1" attribute2="val attr 2">More for Donald Trumpet</more>
    </customer>
</customers>
%html%
dim json as c
json = json_from_xml(xml)
json = json_reformat(json)
showvar(json)

 

dim p as p

p = json_parse(json)

 

 

 

UX Component - Radio Button and Checkbox Controls - Render as Button List - Right to Left - For languages that use right-to-left text, when you render a radio button or checkbox control as a Button List, you might want the Button List to render as shown below (text right aligned and icon to the right of the text).

 

 

In the property sheet for the Radio Button or Checkbox, set a custom class name for the 'Class name - choices' property.

 

 

Then, in the CSS for the component, define this custom class as follows:

 

.myButtonListClassName {
    direction:rtl;
    text-align:right !important;
}

 

 

UX Components - List Control - Nested Lists - Hierarchical JSON Data from SQL Tables - If you want to display a List control with nested Lists (ile. when the user selects an item in the List, the List is repopulated with that item's child data), you typically define JSON data for the List using this format:

 


Watch Video
Download Component

 

[
    {
        display: 'Menu1',
        children: [
            {
                display: 'Menu1_A',
                action: 'Action_1'
            },
            {
                display: 'Menu1_B',
                action: 'Action_2'
            },
            {
                display: 'Menu1_C',
                action: 'Action_3'
            }
        ]
    },
    {
        display: 'Menu2',
        action: 'Action_4'
    },
    {
        display: 'Menu3',
        action: 'Action_5'
    }
]

 

In some cases you might want to generate this JSON data by querying a SQL database. This is easily done by using the a5_xbasicTreeToJSONTree() function.

For example, consider the following Xbasic string which defines a tree structure in Xbasic syntax:

 

 

dim txt as c
txt = <<%str%
MA.Boston.Smith
MA.Boston.Jones
MA.Cambridge.King
CA.Los Angeles
%str%

json = a5_XbasicTreeToJSONTree(txt,".","display")

 

The syntax for the a5_XbasicTreeToJSONTree() function is:

 

a5_XbasicTreeToJSONTree(c XbasicTreeDefinition, c delimiter [, c propertyName])

 

 

   This will generate a JSON string in this format:


[
    {
        "display": "MA",
        "children": [
                        {
                            "display": "Boston",
                            "children": [
                                            {
                                                "display": "Smith"
                                            },
                                            {
                                                "display": "Jones"
                                            }
                                         ]
                           },
                            {
                                "display": "Cambridge",
                                "children": [
                                                {
                                                    "display": "King"
                                                }
                                            ]
                              }
                        ]
        },
        {
            "display": "CA",
            "children": [
                            {
                                "display": "Los Angeles"
                            }
                        ]
        }
]

 

With this understanding of how the   a5_XbasicTreeToJSONTree() function works, it is easy to see how to generate the JSON from a SQL database. The key is to simply define a query that returns data in the Xbasic tree format and then call the a5_XbasicTreeToJSONTree() function.

For example, to generate data that displays a list of Countries, Cities and Contact Names, you can use this Xbasic:

 

dim cn as sql::Connection
cn.open("::Name::northwind")
dim sql as c
sql = "SELECT Country, City, ContactName FROM Customers ORDER BY Country"
dim flag as l
cn.PortableSQLEnabled = .t.
flag = cn.Execute(sql)
dim rs as sql::ResultSet
rs = cn.ResultSet
dim txt as c

'generate the Xbasic tree format data using a | as the delimiter
txt = rs.ToString(-1,-1,.t.,"|")

dim json as c

'generate the JSON tree specifying the | as the delimiter and 'display' as the property name
json = a5_XbasicTreeToJSONTree(txt,"|","display")

 

 

Reports - Calculated Fields - User Defined Expressions - Slow Performance in Report Design Mode - A common pattern in reports is to define calculated fields that use user defined functions. Sometimes these functions are quite complex and because the functions get evaluated repeatedly when you are design mode, the performance of the report designer is degraded.

You can easily solve this problem by adding code to your user defined functions that cause the functions to exit when you are in report design mode.

For example, say you have a calculated field that references a function defined as follows:

 

function my_report_calc_field as ()

    'some code here that does a database query

    my_report_calc_field = "function return value"

end function

 

You can rewrite this function as follows:

function my_report_calc_field as ()

    if eval_valid("topparent.window_title") then
           'in report design mode, so bail out

            my_report_calc_field = "some dummy return value"

            exit function

    end if

    'some code here that does a database query

    my_report_calc_field = "function return value"

end function

 

 

 

 

 

Reports - Calculated Fields - User Defined Expressions - 1024 Character Limit - A common patter in reports is to define calculated fields that use user defined functions. In some cases the function might return a long value. However, calculated fields have a limit of 1024 characters.

You can easily work around this limit by converting the calculated field to an HTML type. For example, suppose you have a function that returns a long string of text. You could define your calculated field in the report as follows:

myCalcField = *mime_object("html",myFunction())

 

 

UX Component - Columnar Lists Not Displaying Correctly - If a List control is initially hidden when the UX is rendered, and then it is later shown (for example, using some Javascript that shows the container in which the List is contained), the List will not display correctly (if the List is defined as a columnar List as opposed to a free-form layout List). In order to get the List to display correctly you must refresh it. For example:

var lObj = {dialog.object}.getControl('name of your list');

lObj.refresh();

 

In many cases when you build your UX, Alpha Anywhere will be able to detect automatically that a List is not displayed when the UX is initially rendered and it will automatically generate the code to refresh the List when it is shown (for example, if you put a List on Pane number 2 of a Tab control, the List is not initially shown, bug when Pane 2 is given focus, the List is automatically refreshed). However, there are cases where it is not possible for Alpha Anywhere to detect this and you will need to add the refresh code yourself.

NOTE: Lists that use a free-form layout do not need to be refreshed when they are shown.

 

UX Component - PhoneGap - Disconnected Applications - Storing Read-only Data in the Device File System -  When you build applications that are designed to be used while you are disconnected, you typically load the data that you want to have while you are disconnected into List controls and then you set these List control to persist the data to Local Storage.

 

TIP: You can download a working example of the component described in this topic here. You can also watch a video tutorial on the steps.
Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3
Watch Video - Part 4
Watch Video - Part 5
Watch Video - Part 6
Watch Video - Part 7
Watch Video - Part 8
Watch Video - Part 9

However, if your application is designed to be run in a PhoneGap shell, then you can store the 'read-only' data in your application in the file system on a mobile device. Only the editable data needs to be stored in List controls. By storing the 'read-only' data in the file system, you leave more of the available space in Local Storage for your editable data.

NOTE: The technique described here is different from linking in a static Javascript file in the Javascript linked files property in the UX component. You certainly can include read only data in linked Javascript files, but after the PhoneGap application has been built, you will not be able to refresh the data in the Linked files. The technique described here allows the user to click a button at any time to make a callback to the server to refresh the data that is stored in the mobile device's file system.

When the user wants to update the 'read-only' data stored on their device, you might perform the following steps:

  1. Make an Ajax callback to the server. Include data in the callback describing what data you want to load onto the device. Include with the callback data the name of the file in the file system on the mobile device where the data should be saved.

    NOTE: When you define an Ajax callback you can specify 'additional data' to be sent to the server when the callback is made. Assume that you want to store the data in a file called 'data1.json' on the device. If you are using Action Javascript to define this Ajax callback, you would set the 'Additional data to submit' property to '_filename=data1.json'.
  2. The Xbasic function that handles this callback will perform the necessary database queries to get the data. The function will create a file that contains this data (in JSON format) and will store the file as a temporary session file. (See 'The Xbasic Function to Handle the Ajax Callback' below for details)
  3. The Xbasic function will send a response back to the client with the URL of the temporary session file and call a Javascript function that uses the PhoneGap File Transfer plugin to download the temporary file from the server (using the URL that the Ajax callback returned). Once the file has been retrieved, it will be stored in a file in the file system on the mobile device. (NOTE: You don't have to write the code to use the PhoneGap File Transfer plugin yourself - there is an Action in Action Javascript that will write the code for you. See below for more details).

Now that the data is in a file, you can use PhoneGap to read the file into memory. Once the file has been read into memory, you can call the JSON.parse() Javascript function to crate a Javascript object with the data and your UX component can then use this data as needed.

 

The Xbasic Function to Handle the Ajax Callback

The Xbasic function that handles the callback to fetch data from the server will have to create a file with data in JSON format. Here is an example of what the file might look like:

{

    "table1" : [

        { "field1" : "alpha", "field2" : "beta"},

        { "field1" : "alpha", "field2" : "beta"},

        { "field1" : "alpha", "field2" : "beta"}

 

    ],

 

    "table2" : [

        { "field1" : "a", "field2" : "b", "field3": "c"},  

        { "field1" : "d", "field2" : "e", "field3": "f"}  

 

    ]

}

 

Notice that the file is in JSON format. In this case, the file defines two objects (you can think of these as 'tables') called 'table1' and 'table2'. 'table1' has 3 records and each record has these fields: field1 and field2. 'table2' has 2 records and these fields: field1, field2, field3

This file must then be stored as a session file so that the client (i.e. the mobile device) can download it from the server.

Assume that you used Action Javascript to define the the Ajax callback and that in the action definition you specified that the name of the Xbasic function to handle the callback was xb_getData. Assume also that you specified  Additional data to submit as '_filename=data1.json'.

 

 

Here is how xb_getData() might be defined.

 

Function xb_getData as c (e as p)

'in this example the json data is statically defined.

'in a real-world case you would likely execute database queries here to generate the json

 

dim json as c

json = <<%txt%

{

    "table1" : [

        { "field1" : "alpha", "field2" : "beta"},

        { "field1" : "alpha", "field2" : "beta"},

        { "field1" : "alpha", "field2" : "beta"}

 

    ],

 

    "table2" : [

        { "field1" : "a", "field2" : "b", "field3": "c"},  

        { "field1" : "d", "field2" : "e", "field3": "f"}  

 

    ]

}

%txt%

 

'get a temporary filename

dim tempFn as c

tempFN = request.GetRequestTempFileName(".json")

 

'save the json data to the temporary file

file.from_string(tempFn,json)

 

 

'get the filename to use from the 'additional data' submitted by the ajax callback

dim clientSideFileName as c

if eval_valid("e._filename") then

    clientSideFileName = e._filename

else

    'user did not specify the client-side filename in the Ajax callback

    'so generate a random filename

    clientSideFileName = remspecial(api_uuidcreate()) + ".json"

end if

 

'now put the temporary file into session storage

session.SaveFileToSessionFile(tempFN,clientSideFileName)

 

'get the URL for this session file
dim url as c
url = Session.FormatFileDataURL(clientSideFileName)
 

 

'construct the Javascript response that will be sent to the client

'note that we specify that a function called 'fetchFile()' should be called

'on the client-side with the name of the URL that points to the temporary

'file in session storage. This 'fetchFile()' function is a user-defined

'Javascript function that you will need to add to your UX component

 

dim js as c
js = js + "fetchFile('" + js_escape(url) + "');"

 


 

'return the javascript code

xb_getData = js

 

 

End function

 

 

At run-time, the user might click a button to trigger the Ajax callback. The Xbasic function will prepare the file and then send a response back to the client (i.e. the browser) and call a function (called 'fetchFile' in this example).

Here is how the fetchFile function could be initially defined (in the Javascript functions section of the UX) to test that the Ajax callback is working:

 

function fetchFile(url) {

    alert('Server has prepared this file: ' + url);

 

    /*

        eventually, we will put the Javascript here to make a

        callback to the server to fetch the file

        however, in the mean time, we are just going to store the URL

        in a variable so we can reference it from another function

    */

   

    {dialog.object}._urlToDownload = url;

   

 

 

}

 

Flushing out the 'FetchFile' Action

In order to fetch the file from the server and store it in the file system on the device we can use Action Javascript to get started.

Add a temporary button to your UX (label it 'Fetch File') and then use Action Javascript to define the button's onClick action. Select the PhoneGap - File Download action.

NOTE: The reason for putting the temporary button on the UX is so that we can use Action Javascript to assign an action to this button and then copy the generated Javascript. This is easier than writing the Javascript by hand.

 

 

The genie for this action will open:

 

 

The builder allows you to specify the names of the files on a remote server (in this case the Alpha Anywhere server) that you want to download. You do this by specifying the name of a Javascript function that will return an array of filenames.

You can specify the name of the folder on the device where the downloaded file(s) should be stored.

The 'Force download if file found on device' property allows you to force the file(s) to be downloaded even if a file with the specified name is already on the device. If you force download, the existing file(s) on the device will be overwritten.

You can also specify if you want to display a progress bar while the files are being downloaded. Since you might be downloading large files or many files, displaying progress to the user is always a good idea.

Finally, you can specify some Javascript to execute once the file(s) have been downloaded and stored in files on the device.

 

Set the 'Files to download Javascript Function' property to 'getFiles' and add this function to the Javascript functions in the UX component.

 

function getFiles() {

 

    /*

        recall that in the fetchFile() function we put

        the url in a temporary variable (called _urlToDownload)

        in the UX object

    */

    var url = {dialog.object}._urlToDownload

 

    /*

        this function must return an array of filenames, so

        put the url into an array

    */

    return [url];

 

}

 

We can add a [Placeholder] control to the UX and set the 'Placeholder for progress indicator' to the name of our placeholder.

 

Finally, we can set the 'On Download Complete (all files)' property to some Javascript code.  Let's set it temporarily to this:

alert('File was downloaded');

 

 

After you have filled in all of the properties that you need to fill in in the PhoneGap File Download genie, click the OK button. Here is the Javascript code that was generated to download a file on the server (specified by a URL) and store that file in local file on the mobile device.

Note: To see this code, click the View Javascript button in Action Javascript editor.


 

 

var _list = window['getFiles']();
var arr = [];
for(var i = 0; i < _list.length; i++) {
    arr.push( {filename: _list[i]} );
}
var options = {
    targetFolder: '__myAlphaFiles',
    showProgress: true,

    forceDownloadIfFileExists: false,
    onComplete: function(array) {
        alert('file was downloaded');
    },
    onError: function(array,arrayIndex) {
        alert('error');
    },
    progress: {
        color: '#9fa1e8',
        width: '300px',
        allowCancel: false,
        progressElement: '{dialog.componentname}.V.R1.PLACEHOLDER_1'
    }
}
{dialog.object}.phoneGapFileDownload(arr,options);

 

 

Next, we need to write some Javascript that will read the contents of the file that has been stored on the mobile device. Again, rather than write this Javascript by hand, we will use the same technique we just used - add a temporary button to the UX and then use Action Javascript to set the button's action. We will be using the PhoneGap - File System Actions action to define this action.

 

 

Add a temporary button to the UX (label it 'Read file') and select the PhoneGap - File System Actions action. The builder for this action will then open.

 

 

The PhoneGap File System Actions genie allows you to select from many different types of actions (such as read file, delete file, read directory, delete directory, etc.). Set the Action name to Read File.

Next, set the Filename to __myAlphaFiles/A5SessionFile/data1.json.

Recall that when you defined the File Download action you specified __myAlphaFiles as the folder where the downloaded file(s) were to be stored. Recall also, that when we made the Ajax callback to create the file of JSON data we specified that the file should be called data1.json. Our Xbasic function that handled the callback created the JSON file and then added it to temporary session storage using the name data1.json as the key. Our Xbasic function then called the Session.FormatFileDataURL() method to get a URL for this session file. The format of the URL that this function returns has A5SessionFile/ as a prefix. So, the actual name of the file that is stored in the file system on the device is not __myAlphaFiles/data1.json as you might have expected, but is instead __myAlphaFiles/A5SessionFile/data1.json.

 

The OnSuccess property allows you to specify the Javascript to run once the file has been read and the OnFailure property allows you to specify the Javascript to run if the file cannot be read.

The onSuccess function can refer to a variable called data, which contains the contents of the file that was read. The data that was read will be a string in JSON format, so we will need to use the Javascript JSON.parse() function to turn it into a Javascript object.

 

Edit the onSuccess property and enter this Javascirpt:

 

var _d = JSON.parse(data);

var _dt = '';

for (var tableName in _d) {

       _dt = _d[tableName];

       var msg = 'Rows in table \'' + tableName + '\': ' + _dt.length;

       alert(msg);

}

 

Here is what this code does.

  1. Parse the string of data in data into a Javascript object called _d .
  2. Loop over all of the properties in the _d object. The properties in this object should be 'table1' and 'table2'.
  3. Get an object for the table  _dt = _d[tableName]. This object will be an array containing the rows of data in the table. Get the number of rows in the table and alert it in a message that says (for example) Rows in table 'table1' : 3.

You can set the onFailure code to

alert('could not read file');

 

After you have completed filling in the genie, click ok and then view the generated Javascript. The generated code will look like this:

 

{dialog.object}.phoneGapReadFile('__myAlphaFiles/A5SessionFile/data1.json',function(data) {
    var _d = JSON.parse(data);

    var _dt = '';

    for (var tableName in _d) {

           _dt = _d[tableName];

           var msg = 'Rows in table \'' + tableName + '\': ' + _dt.length;

           alert(msg);

    }

    },function() {
        alert'Could not read file');
    }

)

 

 

Putting it All Together

At this point we have separate buttons for:

  1. Making the ajax callback to prepare the file of JSON data
  2. Downloading the file of JSON data and store it in a file on the device.
  3. Reading the file and process the data.

Ideally, we would like to combine all of this into a single action so that the user can click a button, which makes a callback to the server and then the file is automatically downloaded to the device, read and processed.

As you will recall, the whole client-side process starts when the Ajax callback completes and it calls the 'fetchFile' function which is current defined as follows:

 

function fetchFile(url) {

    alert('Server has prepared this file: ' + url);

 

    /*

        eventually, we will put the Javascript here to make a

        callback to the server to fetch the file

        however, in the mean time, we are just going to store the URL

        in a variable so we can reference it from another function

    */

   

    {dialog.object}._urlToDownload = url;

   

 

 

}

 

Also recall that when we created a button to download the file from the server and we then examined the code to download the file, the generated code looked like this:

 

var _list = window['getFiles']();
var arr = [];
for(var i = 0; i < _list.length; i++) {
    arr.push( {filename: _list[i]} );
}
var options = {
    targetFolder: '__myAlphaFiles',
    showProgress: true,

    forceDownloadIfFileExists: false,
    onComplete: function(array) {
        alert('file was downloaded');
    },
    onError: function(array,arrayIndex) {
        alert('error');
    },
    progress: {
        color: '#9fa1e8',
        width: '300px',
        allowCancel: false,
        progressElement: '{dialog.componentname}.V.R1.PLACEHOLDER_1'
    }
}
{dialog.object}.phoneGapFileDownload(arr,options);

 

So let's take this code and inject it directly into the fetchFile() function. We know the url of the file that needs to be downloaded (it is passed into the fetchFile() function), so we don't need to call the getFile() function as we did previously. The fetchFile() function will become:

 

 

Let's change this function to:

function fetchFile(url) {

 

    /*

    we need to put the url into an array of objects where the filename is

    specified by the 'filename' property.

    */

    var arr = [];

    arr.push({filename: url})
 

    var options = {
        targetFolder: '__myAlphaFiles',
        showProgress: true,

        forceDownloadIfFileExists: false,
        onComplete: function(array) {
            alert('file was downloaded');
        },
        onError: function(array,arrayIndex) {
            alert('error');
        },
        progress: {
            color: '#9fa1e8',
            width: '300px',
            allowCancel: false,
            progressElement: '{dialog.componentname}.V.R1.PLACEHOLDER_1'
        }
    }
    {dialog.object}.phoneGapFileDownload(arr,options);

}

 

The next step is to replace the onComplete code above, which current simply does:

alert('file was downloaded');

 

with the code that reads and processes the JSON file.

As you will recall when we defined the action to read the file and then examined the generated Javascript, the code to read the file was:

 

{dialog.object}.phoneGapReadFile('__myAlphaFiles/A5SessionFile/data1.json',function(data) {
    var _d = JSON.parse(data);

    var _dt = '';

    for (var tableName in _d) {

           _dt = _d[tableName];

           var msg = 'Rows in table \'' + tableName + '\': ' + _dt.length;

           alert(msg);

    }

    },function() {
        alert'Could not read file');
    }

)

 

We need to simply replace the codeblock that says alert('file was downloaded'); with the above code block. However, rather than simply injecting the read file code into the onComplete event let's wrap the code that read the file in a function and then call this function in the onComplete event.

 

So we have:

 

function readFileAfterDownload() {

    {dialog.object}.phoneGapReadFile('__myAlphaFiles/A5SessionFile/data1.json',function(data) {
        var _d = JSON.parse(data);

        var _dt = '';

        for (var tableName in _d) {

               _dt = _d[tableName];

               var msg = 'Rows in table \'' + tableName + '\': ' + _dt.length;

               alert(msg);

        }

        },function() {
            alert'Could not read file');
        }

    )

}

 

And the fetchFile() function becomes:

 

function fetchFile(url) {

 

    /*

    we need to put the url into an array of objects where the filename is

    specified by the 'filename' property.

    */

    var arr = [];

    arr.push({filename: url})
 

    var options = {
        targetFolder: '__myAlphaFiles',
        showProgress: true,

        forceDownloadIfFileExists: false,
        onComplete: function(array) {
            readFileAfterDownload();
        },
        onError: function(array,arrayIndex) {
            alert('error');
        },
        progress: {
            color: '#9fa1e8',
            width: '300px',
            allowCancel: false,
            progressElement: '{dialog.componentname}.V.R1.PLACEHOLDER_1'
        }
    }
    {dialog.object}.phoneGapFileDownload(arr,options);

}

 

 

 

 

 

 

 

UX Component - Abstract Events - Tweaking Settings - For mobile applications built with the UX component, several abstract events, such as tap, double tap, swipe, etc. are implemented. In certain cases you might want to customize aspects of the way these abstract events are implemented. For example, you might want to:

 

This can be done by setting properties on the $e.abstractEvents object. You could, for example, set these properties in the onRenderComplete client-side event.

 

Examples:

//if the user's finger moves by more than 20px after touching the screen, the 'tap' event will not fire.

$e.abstractEvents.tap.wiggle = 20

 

//if the user puts a finger on an element that has a 'click' event handler and then scrolls the screen by

//more than 20px, the 'click' event will not fire.

$e.abstractEvents.click.scrollMax = 20

 

 

//if the time between the first tap and the second tap is less than 600ms, a 'dblTap' event will fire.

$e.abstractEvents.dblTap.duration = 600

 

 

$e.abstractEvents.dblClick.duration = 600

//see dblTap example

 

//if you hold down on an element for less than 600ms the 'downHold' event will not fire

$e.abstractEvents.downHold.duration = 600

 

//if you hold down on an element for more than the 'downHold' duration, but move your finger

//by more than 10px after you touch the screen, the 'downHold' event will not fire

$e.abstractEvents.downHold.wiggle = 10

 

//specify the 'swipe' velocity - a smaller value will mean that a less 'dramatic' gesture is needed

//to register a 'swipe' event on an element

$e.abstractEvents.swipe.velocity = .75

 

 

Alpha Anywhere V3.5 - Build 2999-4519 28-Jul-2015

Bugs

UX Component - Captcha Controls - Captcha control got broken in build 2970. This is now fixed.

Editors - Horizontal Scroll Bar - Various editors in the Development version (e.g. code editor, CSS editor, etc.) did not automatically display a horizontal scroll bar if the current line in the editor too long to display in the window.

 

Alpha Anywhere V3.5 - Build 2991-4518 24-Jul-2015

Features

CSS Icons - Google Material Design Icons - The open source Google Material Design icon set is now included with Alpha Anywhere. When you select an image, and you select the 'Css Icon' category, in addition to the built-in 'FontAwesome' category, there is now a new category called 'MaterialIcons'. There are over 700 icons in the Material Design icon set.

Bugs

UX Component - List Control - Custom Data Source - Pagination - Fetch More - If the Xbasic function for the custom data source set the e.fatalError flag to .t. the 'Fetch More' button in the List was not turned off.

Trial Version of Alpha Anywhere - If a user was using Alpha Anywhere in trial mode (i.e. they did not have a license key), certain features of the product that should have been enabled were incorrectly disabled.

 

 

Alpha Anywhere V3.5 - Build 2988-4516 22-Jul-2015

Features

UX Component - PhoneGap Applications - Setting Default Properties for the PhoneGap Genie - When you build a PhoneGap application it is critical that you turn on all of the required plug-ins for your application in the PhoneGap Build Project Settings genie.

Now, a new property in the UX Builder allows you to specify that certain PhoneGap settings should be automatically set when a PhoneGap application is built using a particular component.

 

 

When you click the smart field for the PhoneGap default settings property, a dialog is shown where you can set certain PhoneGap Builder properties. When you open the PhoneGap genie, the corresponding properties in the builder will automatically be set.

 

 

UX Component - List Builder - Refresh Database Schema - By default when you edit a List that is based on one or more SQL tables, the database schema information is refreshed every time you click OK to exit the List builder. In most cases, if your database is local, the time taken to refresh the database schema is negligible. However, if your List is based on one or more tables in a remote SQL database, the time taken to refresh the schema can be significant.

A new property Automatically refresh database schema on edit allows you to turn off the automatic refresh of schema information when the List builder is opened. If you subsequently change the structure of any of the tables that the List is based on you should click the 'Refresh Database Schema' link shown below.

 

 

 

 type::Definition::Exists() - Check if a namespace exists - Check if a type in a specified namespace exists.

Syntax

L flag =  type::Definition::Exists("mynamespace::mytype")
 

This method is particularly useful for checking if a .NET dll has been successfully registered.

 

UX Component - List Control - SQL Data Source - Group By in SQL - Filter List - If a List control is based on a SQL statement that uses the GROUP BY clause and the UX contains a button to filter the list, if a filter is defined on any of the summary fields in the SQL statement, an appropriate HAVING clause will now be generated.

 

UX and Grid Component - Class Name Selector - Filter - When you bring up the Class Name selector dialog you can now filter the list of CSS class names to make finding the class name you want easier.

 

 

Bugs

 

UX and Grid Component - Javascript Actions - Filter List Of Actions - If you opened the Javascript Actions dialog and you applied a filter to filter the list of actions shown in the window, then clicked the OK button without first clearing the filter, the actions that were excluded by the filter were permanently deleted.

UX Component - Pre-render at Design-Time - {dialog.object}.getParentObject() - If a child UX (that is pre-rendered at design-time) was opened by a parent Grid or UX component, the {dialog.object}.getParentObject() method did not return the correct value.

UX Component - Pre-render at Design-Time - Session Timeout Warning - Was not working if the UX was pre-rendered at design-time.

UX Component - Pre-render at Design Time - 3rd Party CSS Icons - Working Preview - If your UX included any 3rd party CSS icons (e.g. FontAwesome, Fontello, etc.) these icons did not display in working preview if the UX was pre-rendered at design-time.

UX Component - Spin Lists - Percentage Width - If the width of a Spin List control was set to a percentage value (e.g. 50%), the width setting was not correctly applied. NOTE: To see the fix you will need to edit any property on the Spin List control to cause the generated code to be recalculated.

 

Tips

UX Component - Google Map - Getting a Pointer to the Low Level Map Object - The UX component allows you to place a Map control on the UX. Alpha Anywhere creates a map object that has many methods (such as placing markers on the map). Behind the scenes, the Alpha Anywhere map object just calls methods of the underlying Google Map object.

In some cases you might want to get a pointer to the underlying Google map object so that you can invoke methods on it directly. For example, you might have read about some feature in the Google Map API documentation that is not implemented in the Alpha Anywhere map object. Getting a pointer to the underlying Google Map object will allow you to implement any feature you might read about in the Google Map API documentation.

 

Here is how you can get a pointer to the Google Map object:

 

// get a pointer to the Alpha Anywhere map object

//assume your map control is called 'MYMAP1'

var mObj = {dialog.object}.getControl('MYMAP1');

//now get a pointer to the underlying Google Map object

var gMap = mObj.map;



 

 

 

Alpha Anywhere V3.5 - Build 2970-4510 14-Jul-2015

 

Videos

UX Component File Upload to Amazon S3 Storage Amazon S3 is a popular service for storing files. In this video we show how you can build a UX component that allows a user to upload files from their machine directly to S3 storage.


Watch Video - Part 1
Watch Video - Part 2
Download Component

Date added: 2014-12-31

In this next vide we show how you can make an Ajax callback after all of the files have been uploaded. By making an Ajax Callback this action can be used as a replacement for the 'File Upload - User Defined' action in Action Javascript:

Watch Video - Part 1
UX and Grid Component Image Upload When you use the Image Upload action in Action Javascript to upload an image to an image field in a database you now have the option of uploading the image to Amazon S3 storage, rather than to a folder on the Alpha Server.

This video shows how to set up image upload to Amazon S3 and discusses some of the benefits of upload to images to Amazon S3, rather than to the Alpha Anywhere server that is hosting your application.

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

Date added: 2015-01-28
UX Component Applying Security Client-Side A common pattern in applications is to control the visibility (or enabled state) of certain controls on a page based on the 'role' that the user has in the application security framework. For example, a button might only be visible to users in the 'Administration' role.

Typically, the security settings are enforced server-side. But in some situations you might want to enforce the security rules on the client-side.

In this video we show how controls in a UX can be shown/hidden client-side based on the user's role.

Watch Video - Part 1
Watch Video - Part 2
Download Component

Date added: 2015-02-06
UX Component - List Control Exporting Data in List to Excel or Ascii Files A popular feature in the Grid component is the ability to export the data in the Grid query to an Excel or Ascii file. The UX component List control also allows the data in the List to be exported to Excel or Ascii. When you export data from a List you can either export the data currently shown in the List, or the data in the query that the List is based on. Setting up the code to export the List data is easily done using Action Javascript.

In this video we show how the data in a List and in a List query can be exported to Excel.

Watch Video
Download Component

Date added: 2015-02-09
UX Component 'File Upload' Action in Action Javascript This video shows how you can configure the UX component to upload a file to the Alpha Anywhere server and then store the filename of the uploaded file in a character field in the table to which the UX component is data bound.

Watch Video - Part 1
Watch Video - Part 2

Date added: 2015-02-15
UX Component 'File Upload' Action in Action Javascript - Uploading to Amazon S3 This video shows how you can configure the UX component to upload a file to Amazon S3 storage and then store the object name of the S3 object in a character field in the table to which the UX component is data bound.

TIP: It is recommended that you watch these videos (Watch Video - Part 1    Watch Video - Part 2 ) which discuss uploading files to the Alpha Anywhere server (as opposed to Amazon S3) before watching this video.


Watch Video - Part 1
Watch Video - Part 2

Date added: 2015-02-15
UX Component File Download from Amazon S3 This video shows how you can use the File Download action in Action Javascript to download files that were previously uploaded to Amazon S3 storage.

The video discusses the two different download modes - 'Indirect' (in which the Alpha Anywhere server retrieves the file from S3 and then sends it to the client) and the much more efficient 'Direct' mode (in which the file is downloaded to the client directly from Amazon S3 storage, thus placing minimal load on the Alpha Anywhere server).


Watch Video - Part 1
Watch Video - Part 2

Date added: 2015-02-15
UX Component File Upload to Amazon S3 Storage - Ajax Callback On Complete When all files have been uploaded to S3 a Javascript event is fired, but there is no property in the builder that allows you to specify the name of an Xbasic function to execute.

In this video we show how an Ajax callback can be made after all of the files have been uploaded to S3. The Xbasic function that handles the callback gets passed an array with the names of all of the files that were uploaded.

A typical use case for this technique would be to store the name of the files that were uploaded in some database on the server.

Watch Video - Part 1

Date added: 2015-02-18
UX Component Stripe Checkout The Stripe API allows you to use the popular Stripe service to process credit card transactions.

Watch Video
Download Component

Date added: 2015-04-01
UX Component - List Control Client-side Summary Values - Aligning Summaries with List Columns The List control allows you to insert client-side group breaks in a List and to display summary values in the group headers and footers. In a columnar List layout you typically want to align these summary values with the appropriate List columns.

In this video we show how a genie can generate the necessary Javascript to make it easy to align the summary data with the corresponding List column.

Watch Video
Download Component

Requires build 4465 or above
Date added: 2015-04-07
Reports Linked Reports The Alpha Anywhere report writer lets you create 'Linked reports'. A linked report is a report that is embedded inside a parent report and linked on some common fields. Linked reports can themselves also contain other linked reports.

In this video we take a simple database that has a 'customer', 'orders' and 'payments' table and create reports on each of these tables. We then link the 'orders' and 'payments' reports into the parent 'customer' report.

When you use linked reports you will often want to reference fields values in the linked reports from the parent report. The video shows how this is done by computing the net amount due for each customer, which is the total for their orders minus the total for their payments.

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3
Watch Video - Part 4

Download Files

Requires build 4469 or above
Date added: 2015-04-17
UX Component - List Control Using the a5-item Template Item Attribute to Add Custom Event Handler to the List Row Template Each row in a List control is rendered by merging data into a row template. The row template is standard HTML which you are free to edit. You can include events in the HTML, but adding onClick and other events directly into the HTML template is not efficient and does not work well on touch enabled devices. A much better solution is to use 'template items' to add custom events to the HTML template.

In this video we show how the a5-item attribute can be added to the HTML template and how you can define event handlers for these 'template items'.

Watch Video

Requires build 4473 or above
Date added: 2015-04-17
UX Component - List Control Field Level Events - Adding Events for Click, Double Click and Right Click on a Field in a List The List control has several events that fire when the user clicks, double clicks, taps, etc. on a List row. Now there are additional events that fire when the user clicks, double clicks or right clicks on individual fields in a List. The onFieldClick event fires when the user click on a column in a particular row of the List. The event handler that get called is passed an object with the row number of the row, the name of the field and the value of the field that was clicked.


Watch Video

Requires build 4473 or above
Date added: 2015-04-17
Grid Component Master Template - Tabs - Controlling Active Tab with Javascript When you build a Grid component you can specify that the Grid parts (Search, Grid and Detail View) should be shown in a Master Template. There are several pre-defined Master Templates that you can choose from. For example, you can choose a template that puts each Grid part in its own tab.

In this video we show how you can use Javascript to automatically control which tab has focus. For example, after the user does a search you would want the Grid tab to have focus. After the user clicks on a row in the Grid to show the Detail View for that row, you would want the Detail View tab to have focus.

Watch Video
Download Component (requires a connection string called Northwind that connects to the sample Northwind database).

Date added: 2015-04-28
Grid Component Adding 'Genie-Style' Tabs to the Detail View When you build a Grid component you can specify that the Detail View fields should be shown in a Tab Control. A common design pattern with tabs is to hide the tab buttons and instead display Next and Previous buttons that allow the user to step through the tabs one at a time.

This style of moving from tab pane to pane by clicking Next and Previous buttons is called 'Genie-style' tabs.

The Grid does not have a built-in option for creating 'Genie-style' tabs (unlike the UX, which does), but with a small amount of Javascript you can add this feature to the Grid, as shown in the video.


Watch Video
Download Component (requires a connection string called Northwind that connects to the sample Northwind database).

Date added: 2015-04-28
UX Component - List Control Disconnected Applications - Compressing Data Before Storing it in Local Storage When you build applications that are designed to work while disconnected, the data in the List controls in your UX component are persisted to Local Storage. There is a limit to the amount of data that can be put into Local Storage. The limit varies by browser, but it typically in the 5MB range.

By compressing the data before it is put into Local Storage you can store more data. In this video we show how to turn the compression feature on and how to measure the impact of data compression.

Watch Video
UX Component Using Date Variables in Client-side Calculated Fields When you define a client-side calculated field expression in a UX and a fields in the expression is a 'Date' type field, it is important to understand what goes on behind the scenes. Alpha Anywhere converts the date string into a Javascript date object, which enables date calculations in your client-side calculated expression.

This video explains some of the subtleties when working with 'Date' type fields in client-side calculated fields.

Watch Video - Part 1
Watch Video - Part 2

Addendum. In the video we describe how the formatDate() function should be defined. Under some circumstances the formatDate() function, as defined in the video, will give an error because the code that adds the .toFormat() method to the date object has not yet executed. The modified version of the formatDate() function, shown below, can be used instead:

function formatDate(dt) {
       var fmt = A5.__dtfmt + ' ' + A5.__tfmt;
       try{
                return dt.toFormat(fmt);
       } catch(err) { }
}


Date added: 2015-06-26
UX Component - List Control Capturing Photos in a Disconnected Application  when using PhoneGap If your disconnected application runs in a PhoneGap shell then you can capture a large number of photos while you are disconnected without being constrained by the amount of Local Storage available on a device. You can also load photos onto your device so that they are available while you are disconnected.

In this video we show how photo capture works in a PhoneGap application when the option to use the file system on the device is enabled.

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

We also show how the List control is configured to use PhoneGap and the file system on the device:

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

Date added: 2015-07-07
     

 

 

 

Features

UX Component - Methods - {dialog.Object}.refreshClientSideComputations([flagSynchronous]) Method - Now takes an optional flag to indicate whether the refresh should be synchronous or asynchronous. By default, this method now executes asynchronously and the refresh is delayed for 300ms. The reason for changing the behavior of this method to be asynchronous is to prevent multiple calls to this method within a very short time from degrading performance of a UX component (especially in the case where the UX has a lot of watch expressions or the UX is running on a mobile device - which will have a relatively slow processor compared with a desktop machine). If multiple calls to the method are made within a 300ms window, only the last call is now executed - unless the calls are made with the flagSynchronous flag set to true.

 

Application Server - Open SSL - Updates to OPenSSL 1.0.1p

PhoneGap - UX Component with Child UX Components - Pre-render at Design-time - When you build a PhoneGap application you specify the name of the UX component that is the 'start-up' component. This is the UX that is loaded when the user taps on the application icon on the device home screen. Since the start-up component is physically part of the PhoneGap app, the application can be launched regardless of whether the mobile device has a connection or not.

A common design pattern is for this start up component to call child UX components. These child UX components can either be embedded into the start-up component (for example on a Panel Card that is not initially visible) or might be displayed in pop-up windows. These child components are loaded by making an Ajax callback to the server.

However, if you do not have a connection, you will not be able to make the callback to load the child component.

Now, when you add an embedded object to a UX, or when you use Action Javascript to define an event to open a child UX, you can specify that the child-UX should be pre-computed.

In the image below, the new property (Method for opening UX in a PhoneGap or Static HTML application) for an embedded object is shown in the Optimizations (PhoneGap/Static HTML) section.

 

 

A similar property is also available in the Action Javascript builder for opening a child UX.

 

 

The options for this property are:

Benefits of the Pre-computed Method

The primary benefit of the precomputed method is speed. No callback is necessary, so the child UX will load very quickly.

Limitations of the Pre-computed Method

Since the child UX component is pre-computed at the time the PhoneGap application (or Static HTML) application is build, there is no concept of what the user's security groups are and what the value of any session variables are. Therefore this option is not appropriate if you have any server-side show/hide expressions, or if certain controls have associated security settings. Also, any data in the component will have been rendered at design-time so you may need to write Javascript code to set certain control values in the child UX after it has been rendered.

 

 

PhoneGap - Action Javascript - Working with Files - New actions have been added to Action Javascript that make it easy to work files files in the file system of a mobile device. The new actions are:

 

PhoneGap - File Upload Action - Action Javascript - Uploads files from the file system on a mobile device to a server.

When you select this action, the following dialog appears:

 

IMPORTANT: Your PhoneGap application must include the Device, File, File Transfer plug ins.

 

Properties of note in this builder include:

If you select multiple files to upload, the files are uploaded asynchronously. Each selected file has its on 'On Upload Complete' event. There is also an 'On Upload Complete' event that is fired once all selected files have been uploaded.
If you upload files to the Alpha Anywhere server, you can specify an Xbasic function to call after each file has been uploaded.

 

 

PhoneGap - File Download Action - Action Javascript  - Downloads files from a remote server and stores the files in the file system a mobile device.

When you select this action, the following dialog appears:

 

 

 

IMPORTANT: Your PhoneGap application must include the Device, File, File Transfer plug ins.

 

Properties of note in this builder include:

PhoneGap - File System Action - Action Javascript - A collection of actions that make working with files in the mobile device file system easier.

When you choose this action, you can select from the following list of file system actions:

Note: All PhoneGap file system actions are asynchronous. When you define any of these actions you specify a success function that gets called once the PhoneGap action has successfully completed.

List Control - Detail View - Photos in PhoneGap Applications - Previously, when you built a disconnected application (using List controls with associated Detail Views) you were limited as to how many photos you could capture while you were disconnected because the photos had to be stored (as base64 encoded data) in the browser's Local Storage cache until a connection was available and you could synchronize the data. On most mobile devices, Local Storage is limited to about 5MB.

Also, if the data you were loading from your server onto a mobile device contained photos, the number of records you could retrieve from the server and keep on the mobile device was limited because the photos had to be stored along with your data in Local Storage on your device.

Now, if your application uses PhoneGap, you can use the file system on the device to store your photos and you can capture a large number of photos while you are disconnected, without having to worry about the limits of Local Storage. Future versions of Alpha Anywhere will also allow you to capture video and audio while you are disconnected.

NOTE: Photos, videos and audios are collectively labeled as 'media' files in this topic.

Quick Summary of Steps to Use PhoneGap File System for Photos:
-
Photo fields in your SQL database must be character fields.
- Create a List control with a Detail View on your UX component.
- In the Detail View, set the control type for the Photo fields to Image.
- In the List builder go to the Detail View pane and set the Media and other Linked Files properties. Most importantly, specify if the media files should be uploaded to Amazon S3 or the Alpha Anywhere server. It is also recommended that you check the Automatically download media files... property so that your photos in your existing data are available when you go offline.
- In the List builder, go to the Fields pane and set the control type for the Photo fields to Image. Also, if you have specified that the media files should be uploaded to the Alpha Anywhere server, edit the Image Capture and Storage properties to specify the folder where the uploaded photos should be stored.
- Add a button to the Detail View to capture an image using the camera. Define the click event for this button using the Image Capture for List-Detail View action in Action Javascript. In the builder for this action set the Image Capture Method to Phonegap and set the Data capture mode to Filename.

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3
 

NOTE: In order to use this feature, your PhoneGap application must include these PhoneGap plug-ins: Camera, Console, Device, File, File Transfer, Media, Media Capture.

Similarly, when you retrieve data from the server to store on your device, there is no need to store the photos in Local Storage. The photos can be downloaded and stored in files on the device. This will substantially increase the amount of data you can load onto your device.

In order to use the file system for your images (rather than Local Storage), you configure the Image Capture for List-Detail View - Camera/Photo Library action in action Javascript to use the 'Filename' option (rather than the 'Base64' option). See below for more detail.

When you sync the List with the server database, the photos (and other media files, once support for videos and audios is made available) are first uploaded (to the Alpha server or to Amazon S3) and then once the media files are all uploaded, the data in the Lists are synchronized.

Before examining how to configure the Image Capture for List-Detail View - Camera/Photo Library action in action Javascript and the List Detail View to use this option, it is helpful to understand more about what happens behind the scenes when you capture photos, and then sync the data in your List controls.

 

Behind the Scenes

When you take a picture, the List data for a row in the List might look like this (where the file in the picture field is a local file on the mobile device):

 

{Name: 'Fred Smith', picture: 'file://folder_in_the_file_system/image1.jpg'}

 

Note: If you had not set the action that captured the picture to use the 'filename' option, the data in the List might have looked like this (note that the picture field contains a long string of base64 encoded image data):
{Name: 'Fred Smith', picture: 'xysshdh24g22334hack46h2dk43hahdh...........'}

 

When you sync the List data, the media files (the photo in this case) are first uploaded to the server. Let's assume you are uploading media files to S3. The URI of the image on S3 might be something like:

https://yourS3bucketName.s3.amazonaws.com/image1.jpg

 

After the media files have been successfully uploaded to the server, the data in the List are changed as follows:

 

{Name: 'Fred Smith', picture: 'https://yourS3bucketName.s3.amazonaws.com/image1.jpg'}

 

The data in the List can then be synchronized with the server database. The following record would be written to the database:

Name              Picture

Fred Smith        https://yourS3bucketName.s3.amazonaws.com/image1.jpg

 

Once the data synch operation has completed, the data in the List is again changed back to:

{Name: 'Fred Smith', picture: 'file://folder_in_the_file_system/image1.jpg'}

 

The reason to change the data in the List back to its original state is that there is no need to reference a remote image (on say S3) when the local copy of the image is already available in the device file system.

 

Taking Your Media Files With You When You Go Off-line

If the data in your List has references to remote files (e.g. photos, videos, audio files, etc.) that are located on remote servers (such as the Alpha server, or Amazon S3), you can retrieve those files and store them in the file system on the mobile device. By doing this, you ensure that even when you are disconnected, your application can still reference these files.

Assume that a typical row in the SQL table that you are querying to populate the List contains data like this:

Name                   Picture

Fred Smith             https://yourS3bucketName.s3.amazonaws.com/image1.jpg

 

When you retrieve data from the server, the JSON representation of the data in a typical row in the List might look like this:

{Name: 'Fred Smith', picture: 'https://yourS3bucketName.s3.amazonaws.com/image1.jpg'}

 

The picture field is pointing to an image on Amazon S3 and this image will not be available if you are not connected. However you can fetch the image while you do have a connection, store the image in the file system, and update the data in the List to something like this:

{Name: 'Fred Smith', picture: 'file://folder_in_the_file_system/image1.jpg'}

 

Notice that the picture field in the List no longer points to the remote server, but instead is pointing to a file on the mobile device.

Orphaned Files

Assume that when the List is initially populated, the data in the List are:

[

   {Name: 'Tom Smith', picture: 'https://yourS3bucketName.s3.amazonaws.com/image1.jpg'},

   {Name: 'Jan Toms', picture: 'https://yourS3bucketName.s3.amazonaws.com/image2.jpg'}

]

 

When you fetch the media files, the following files will be stored in the file system on the mobile device:

Assume that the user then does another query and retrieves this data with which to populate the List:

[

  {Name: 'Tom Smith', picture: 'https://yourS3bucketName.s3.amazonaws.com/image1.jpg'},

  {Name: 'Ian King', picture: 'https://yourS3bucketName.s3.amazonaws.com/image3.jpg'},

  {Name: 'Jack Jon', picture: 'https://yourS3bucketName.s3.amazonaws.com/image4.jpg'}

]

 

At this point, the file system on the device will contain these files: 'image1.jpg', 'image2.jpg', 'image3.jpg' and 'image4.jpg', Notice that it still contains a file called 'image2.jpg', but there is no data in the List that references this file. 'image2.jpg' is an 'orphan' file and it can be deleted. The List Detail View has settings that allow you to automatically delete orphan files (see below). There are also events that are fired before and after orphan files are deleted.

 

Configuring Photo Capture to Use the File System

In order to capture photos in disconnected application you will need a List control with an associated Detail View. Let's assume that the List control is bound to a SQL table that has these fields

NOTE: When you are capturing base64 data, the photo field could be a character field, or a binary field. But if you want to use the file system on the mobile device for your photos, your photo field must be a character field.

Assume that you have have added a List control that is bound to this table to your UX. The control type for the photo field (imageChar) in the Detail View should be set to Image.

First you will need to edit the List control and go to the Fields pane and ensure that the control type for the imageChar field is set to Image. Since imageChar is a character field the List does not set its default type to Image.

 

You should then add a button next to this Image control and set the action on this button to Image Capture for List-Detail View - Camera/Photo Library.

When you click the smart field to configure this action, the builder will open as shown below:

 

 

Note that the builder has several properties shown as read-only properties.

 

In this example, the target field (i.e. the Bound field type) is a character field. Therefore we have the option of uploading the image to either Amazon S3, or the Alpha Anywhere server when the data in the List are synchronized.

NOTE: If the Bound field type is a binary field then uploading the image to Amazon S3 is not an option. The image can only be uploaded to the Alpha Anywhere server.

 

NOTE: More properties...  are actually stored in the List control settings. It is merely a convenience that you can edit these setting in this builder. Open the List builder and go to the Field pane to see the settings for each image field.

NOTE: Upload target settings are actually stored in the List control settings. They are not stored as part of your Action Javascript definition. It is merely a convenience that you can edit the Upload target settings from within this builder.  If you open the List builder and go to the Detail View pane,  Media and Other Linked Files (PhoneGap Application Only) section, you will the upload settings.

NOTE: Upload target settings apply to all image fields in the List (and any child Lists with pre-fetched data that are linked to this List). For example, assume that you have two image fields in your List. You might have one button to capture a photo for the first image and another button to capture a photo for the second image. If both of these buttons are configured to use the Filename option for the Data capture mode, then both of these images will be uploaded to the same target (either the Alpha Anywhere server, or Amazon S3). It is not possible to upload the first image field to S3 and the second image field to the Alpha Anywhere server.

 

Upload Target Settings Dialog

The Upload Target Settings Dialog allows you to define if the media files should be uploaded to the Alpha Anywhere server or to Amazon S3. There are two ways to get to this dialog:

  1. While you are editing an Action Javascript button to capture a photo, you can click the smart field for Upload target settings (as explained above)
  2. While editing a List control settings. Go to the Detail View pane and then click the Media files smart field (as shown in the image below).

    NOTE: You must define the Upload Settings in the top-most parent List if you have a List hierarchy (i.e. a parent-child relationship between Lists with the child Lists configured to pre-fetch their data).

 

 

The Upload Target Settings dialog is shown below.

 

 

NOTE: In the case where you are not using PhoneGap, you can still access photos in your data when you are offline. However, the amount of data you can load into the List will be limited because the photos are stored in Local Storage along with the List data. In order to store images in the List data so that they are available when you are offline, the photo field in your database must be a binary field (as opposed to a character field - which is required if you are using the PhoneGap option) and you must configure the List to embed the image data (as base64 encoded data) into the List (by checking the Embed images into HTML property for the image field in the List settings, Fields pane).

Methods

The following methods are available

Events

The following client-side events have been added:

 

 

 

 

 

UX Component - Optimizing Initial Load Time - When a UX component is opened, the layout of the component is computed from the UX component definition. In a large component that can take some time and the component will appear to be slow to open.

NOTE: If the component is opened from a button on a parent component, and the action that defines how the component is opened uses the 'Use cached UX Component' option, the second and subsequent times the button on the parent component is clicked, the UX will open quickly.


 

A new option in the UX allows you to pre-render the component layout at design-time, thus speeding up the load time for the component at run-time.

NOTE: Not all use cases are appropriate candidates for this option. In particular, if you have controls on your UX that are shown/hidden based on a user's security group, or based on session variables, then you should not use this option. The reason is that at design-time when the component is rendered, it is not know what the value of the session variables or group assignments are.

TIP: You can easily check if a component uses security and/or server-side show hide expressions by click the Menu button and then selecting the 'Security and server-side show/hide settings in component...' menu choice.

 

To turn on this optimization feature go to the Properties pane in the UX builder and check the 'Pre-render component at design-time' property.

 


 

When you check this property you will see two additional properties:

 

TIP: When you save a pre-rendered component at design-time, you might have Xbasic code in functions you have defined that is meaningless at design-time, but is nevertheless being called when the component is being pre-rendered. You can test if you are in pre-render mode by checking the flagPreRender property of the rtc object that is passed to all server-side code in the e object. For example:

 

function someXbasicFunction as c (e as p)

if eval_valid("e.rtc.flagPreRender") then
    if e.rtc.flagPreRender then
        exit function
    end if
end if

 

.... your code

end function


 

 

json_sqlQuery() Function - Allows you to filter a JSON array using a simple SQL query syntax. For example assume you have a JSON string as shown below. The JSON is an array of objects. You can think of this as a table with the following fields: firstname, lastname, city and state.

 

 

dim json as c
json = <<%str%
[
    {firstname: 'John', lastname: 'Smith', city: 'Boston', state: 'MA'},
    {firstname: 'Fred', lastname: 'Jones', city: 'Cambridge', state: 'MA'},
    {firstname: 'Tom', lastname: 'King', city: 'New York', state: 'NY'}
]
%str%
 

Assume that you want to apply a filter to this string to retrieve certain records and also to sort the result.

The SQL that you would need to express your query might be:

select * from JSONTABLE WHERE state = 'MA' ORDER BY lastname

 

Or if you would like to use arguments in your SQL, you might express your query as:

select * from JSONTABLE WHERE state = :whatstate ORDER BY lastname

 

Here is how you can use the json_sqlQuery() function:


dim args as sql::arguments
args.add("whatstate","MA")
dim jsonResult as c
json2 = json_sqlQuery(json,"select * from jsontable where state = :whatstate ORDER BY lastname",args)

 

The resulting string will be:

 

[

    {firstname: 'Fred', lastname: 'Jones', city: 'Cambridge', state: 'MA'},
    {firstname: 'John', lastname: 'Smith', city: 'Boston', state: 'MA'}

]

 

 

UX Component - List Control - Persisting List to Local Storage - The UX component has a property that allows you to minify the data before it is put into Local Storage, thereby reducing the amount of space needed to stored the List data.

 

When you check the Minify data option now, any blank fields in the JSON data are automatically removed and system fields that are used internally in the List (these are field that have a leading '*' in their name) are also removed. This can result in a significant reduction in the amount of space needed to save a List in Local Storage.

 

UX Component - SQL - Native SQL and Stored Procedures - You can now enter native SQL statements (including SQL to execute Stored Procedures) in the SQL Statement for a List that is based on a SQL data source.

Previously if you wanted to base a List on native SQL, or on a Stored Procedure you had to use a Custom data source. However, when you used a custom data source you then had to write your own code to handle pagination and server-side filtering.

Now, pagination and server-side filter all work regardless of whether the SQL for the List is portable, native or a Stored Procedure.

If you apply a server side filter to a List that is based on a Stored Procedure, or a native SQL statement that cannot be parsed, Alpha Anywhere will execute the SQL (without the filter/order clause) and then apply the filter/order to the data that is retrieved from the database server.

For example, suppose you based on List on this SQL statement:


exec getAllCustomers


The you apply a server-side filter to the List:


Country = 'USA'
 

Since the Stored Procedure can only return all customers and since it (presumably) was not designed to take an arbitrary 'where' clause, Alpha Anywhere will execute the Stored Procedure and then apply where filter to the data after it has been returned by the database server, but before it is sent to the List control.
 

Storage Connection Strings - Amazon S3 - Connection String Builder - Region Name - The dialog now uses 'friendly' region names that match the region names used in the AWS Management Console.

 

 

Web Applications = Development Server - The Alpha Anywhere Development Server now allows an unlimited number of sessions from localhost clients (i.e. browsers running on the same system) without requiring an Application Server license. This extends the existing Development Server functionality that has always allowed 5 sessions from any client. Localhost clients are no longer counted towards the 5 session limit, so a developer may do unlimited testing using local browsers and device emulators, and still test from 5 non-local clients such as an actual mobile device, a coworker's or client's computer, etc.

Previous versions of Alpha allowed an unlimited number of localhost sessions and no non-local sessions when running the server without a license.
 

Web Security - Password Validation - The password validation in the web security now supports regular expressions in the Text Format. Previously, if a regular expression was used for validation, it had to be added as a custom expression. Publishing to IIS does not support custom expressions, so a custom expression should be converted to a regular expression if possible.
 

PhoneGap Builder - File Opener Plugin - The File Opener plugin has been added to the options screen in the PhoneGap Builder.

More info on the plugin is available here.

 

http_fetch() Function - Validation has been added to the host specified for the HTTP request. Users have occasionally specified a full URL as the host name, which has caused a failure. The new validation logic will extract the host name from the URL if one is mistakenly provided and allow the HTTP request to be completed

UX Component - List Control - Scroller - You can now dynamically show/hide the scroller for a List control. This is useful if you are dynamically populating the List and under some circumstances that are so few rows in a List that the scroller is not wanted, but in other cases there will be many rows in the List and the scroller would be wanted.

The List's .setDisplay() method is used for this as follows:

 

var lObj = {dialog.object}.getControl('myList');

lObj.setDisplay('scroller',false); //hide

lObj.setDisplay('scroller',true); //show

 

Other parts of the list that can be controlled with the .setDsiplayMethod() are:

 

 

Grid Component - .filterCheckedRows() Method - Now takes an optional argument to filter the unchecked rows as opposed to the checked rows.

Syntax:

{grid.Object}.filterCheckedRows([flagUncheckedRows])

 

UX Component - DataBound UX Components - Refreshing Schema Information - The UX builder has an option to automatically refresh the stored schema information every time the UX is opened for editing. For complex data bindings, this can slow down the time taken to open the UX for editing. If you know that the table schema has not changed, there is no need to refresh the stored schema in the UX and you can therefore speed up opening the UX for editing by skipping this step. When you specify that the schema should be refreshed when the UX is edited, there is now a new option to prompt for confirmation each time the UX is opened.

 

 

a5_getExifInfo() Function - Extract EXIF information from an image.

Syntax

P result = a5_getExifInfo(c imageFilename)

 

The result object that is returned has these properties

 

 

UX Component - Action Javascript - Populate Controls in an Unbound UX - New options if no matching record found - If the specified primary key is not found in the table you can now specify that the values in the databound controls should be cleared, you can also suppress the error message, and you can call a Javascript function.

See 'Errors and No Match Found' section in the genie.

 

 

Faster Startup - Alpha Anywhere now starts up faster because the licensing check is now done in a background thread.

PhoneGap - Index.HTML Meta Tags - When you build a PhoneGap app, a new option in the PhoneGap builder now allows you to insert custom META tags in the index.html file that is generated for your PhoneGap app.

A common use case for this feature is to turn off iOS auto-detection of phone numbers and email addresses.

 

 

Web Applications - Context Object Documentation - The Context object is available to all server side code that executes in the context of a Web application (for applications that use the Alpha Anywhere server and for those that use the Alpha Anywhere plug-in for IIS).  This object has an extensive set of methods and properties that allow you to get information about the request and the response to interact with the security framework.

 

Click here to see Context object documentation.

 

 

json_parse() Function - Parsing Javascript Object Literals - The JSON parse function now takes an optional second argument to indicate if the JSON being parsed is a Javascript object literal rather than a JSON string. For example, consider the following Xbasic code which defined an Xbasic object (i.e. dot variable):

 

dim p as p
p.name = "Fred"
p.sayHello = "{javascript}function() { alert('hello');}"

 

Now, generate a Javascript object literal. Pass in .t. as the second argument to vartojson() to indicate that we want an Javascript object literal and not a JSON string.

 

dim jsObject as c

jsObject = vartojson(p,.t.)
 

Here is what the resulting string looks like:

 {
name: 'Fred',
sayHello: function() { alert('hello');}
}

 

Now, in order to be able to parse this object literal back to Xbasic, we use the json_parse() function but we set the optional second argument to .t.


dim pj as p
pj = json_parse(jsObject ,.t.)
?pj.name
= "Fred"

?pj.sayHello
= "{javascript}function() { alert('hello');}"


 

 

 

UX Component - List Control - Template Items - a5-item Attribute - Template Items are a powerful new way to efficiently add event handlers to the HTML markup used in the List template. Template items are added to the HTML markup by adding an a5-item attribute to the markup, as explained below.

 

Watch Video

 

Regardless of whether the List is defined as a free-form or columnar layout, every row displayed in the List is created by merging data into the row template. For a free-form List, there is a single template for the entire row and for a columnar List, there is a template for each column in the List. The template is HTML with placeholders for the List data.

For example, the template for the Firstname field in a columnar List might be:

{Firstname}

 

The template for a free-form List might be:

<b>{Firstname} {Lastname}</b> <br>

{City} {State} {Zip}

 

You might want to add an event handler so that when the user clicks on the Firstname field, an event fires. You might change the template for the Firstname field to:

<span  onClick="event1()" >{Firstname}</span>

 

When the user clicks on the Firstname field in any row of the List, the event1() Javascript function should be called.

While inserting the onClick attribute into the <span> that wraps the {Firstname} placeholder seems easy enough there are two problems with it:

Both problems can be solved by using template items. The template could be defined as:

<span  a5-item="item1" >{Firstname}</span>

 

In the above example, 'item1' is the name of a template item. The event handlers for the 'item1' template item are defined in the Template Item editor.

 

To define template items, you can either click the Quick Access... button at the bottom of the List Builder window and then select 'Template Items' from the menu.

 

 

Or, you can click the Template 'items' hyperlink in the Column Template of Layout Template editor.

 

When you open the Template Items editor you get a screen that looks like this:

 

 

You can define as many template items as you want. For each item you define event handlers for the Click, Double Click and Right Click events.

You can also set the 'Selectable' property. If this property is set, then when the user clicks on the item, the row in which the user clicks is selected. Otherwise, the row is not selected.

 

When you insert a template item into the HTML markup you can insert an optional 'item argument'. The item argument follows the item name, delimited by a colon. In the example below, 'item1' is the item name and 'argumentValue' is the item argument. The purpose of the item arguments is to pass additional information to the Javascript event handler.

<span  a5-item="item1:argumentValue" >{Firstname}</span>

 

The Javascript event handlers for the item can reference:

When you are editing the List template the Template 'items' hyperlink also gives you access to a special genie that makes it easy to insert items into the template:

 

 

 

UX Component - List Control - onFieldClick, onFieldDblClick, onFieldRightClick Events - New events have been added to the List that fire when you click, double click or right click on fields in the List.

 

Watch Video
 

Contrast these events with the onClick, onDblClick, etc. event which fire when you click on a row (as opposed to a field) in the List.

When the onFieldClick, onFieldDblClick or onFieldRightClick events are fired, the e object that is passed into the event handler has these properies:

NOTE: The above events are only implemented for Label and RawData control types.

 

 

 

varToJsonHash() Function - Converts an Xbasic property array to a JSON hash

 

Syntax:

C jsonHash = varToJSonHash(p propertyArray, c hashProperty [, L flagSpecialTags  [, L  flagCondense [, flagUseDoubleQuotes ]]])

 

Where:

 

Example:

Consider the following Xbasic property array:

 

DIM P[0] as p
p[].name = "John Smith"
p[..].address = "123 Main Street"
p[..].age = 23




p[].name = "Fredia Malt"
p[..].address = "456 Center Lane"
p[..].age = 33

 

We can convert this to a JSON hash, using the 'name' property as the hash index as follows:

dim jsonHash as c

jsonHash = vartojsonHash(p,"name")
 

The resulting JSON string looks like this:


{
    'John Smith' : {address: '123 Main Street',age: 23},
    'Fredia Malt' : {address: '456 Center Lane',age: 33}
}
 

In this next example we use the flagSpecialTags property

 

DIM P[0] as p
p[].name = "John Smith"
p[..].address = "123 Main Street"
p[..].age = 23

p[..].sayHello = "{javascript}function() { alert('hello John') }"




p[].name = "Fredia Malt"
p[..].address = "456 Center Lane"
p[..].age = 33

 

jsonHash = vartojsonHash(p,"name", .t.)
 

 

The resulting JSON string is:

 

{
    'John Smith' : {address: '123 Main Street',age: 23,sayHello: function() { alert('hello John') }},
    'Fredia Malt' : {address: '456 Center Lane',age: 33}
}


 

AlphaDAO - SQLServer Driver - Faster Connections - There are two changes in the SQL Server Extension driver:

  1. The actual ODBC driver is selected based on the installed drivers and the selected SQL Server database version. The logic is not complicated but can be expensive; taking a few milliseconds to find the best matching driver. The driver has been optimized so that for a specific SQL Server version, the result is cached and only needs to be evaluated once per process.
  2. The code that should be enabling connection pooling was not working properly. The SQL Server Extension driver now pools connections in a driver specific environment. This behavior should not have any effect on other drivers and is not implemented for the generic ODBC driver because some ODBC drivers are not thread-safe.

As a result of both changes, the connection times are now in the microsecond range when connecting to a local machine.

 

UX Component - Edit Combo - Stored Value is Different than Display Value - Resolving Value Message - When you define an Edit-Combo that sets the stored value to be different than the display value, and the Edit-Combo is populated using an Ajax callback, you can now control the message that is shown when the stored value is resolved into a display value. By default the message:

Resolving: <stored value being resolved>

is shown while the Ajax callback that resolves the stored value is running. But you can customize this message or even eliminate it by setting the message text to <None>.

 

 

UX Component - List Controls - Detail View - Parent/Child Data - In disconnected applications, when you define parent-child relationships between List controls you must set the child List's 'Pre-load data' property to true.

However, when you are building a connected application you might still want to define a parent-child relationship between Lists and you might want to define a Detail View for each List to allow editing of the List data, but you might not want to pre-load the child data (since Alpha Anywhere can easily fetch the child data as needed as you have a connection).

Previously, if you did not have the pre-load option checked, you were not allowed to edit data in the child Lists (using the child List's Detail View).

Now, you can edit data in the child Lists, but you must specify linking values in the optional Linking fields section. The data you fill into these properties is used to ensure that the values in the linking fields are automatically set to the corresponding values in the parent List record when insert or updates are performed.

 

 

a5_sql_schema_to_json() Function - Takes a schema of a SQL database and generates a JSON representation of the schema showing all tables in the database, and their relationships.

 

Example:

 

Type the following commands in the Interactive window:

 

dim cn as sql::Connection

?cn.Open("::Name::northwind")

= .T.
dim sn as sql::Schema

?cn.GetSchema(sn)

= .T.

dim jsonSchema as c

jsonSchema = a5_sql_schema_to_json(sn,{ show_field_type_info : true })

showvar( jsonSchema)
 

 

UX Component - Action JavaScript - Geolocation Functions- A new option, Get accurate position within a designated radius has been added to the Action JavaScript Geolocation functions. When enabled, you may specify a desired accuracy radius. The returned lat/lon will fall within the desired accuracy radius if at all possible. This option calls a new custom method that has been added to the navigator.geolocation object called getAccuratePosition(). This method uses the geolocation watchPosition() method to attempt to get position data within a specified accuracy radius. The method will time-out at the maximum wait time and will return the last known location, even if the accuracy does not meet the desired accuracy target.


The maximum wait time defines the maximum amount of time in ms to wait for a geolocation change event.
If Ignore first result is checked, the first geolocation point returned will not be used. Some devices return cached location data for the first result, which is, in most cases, inaccurate.

The returned geolocation data can be accessed through the {dialog.object}.getGeolocation() method.

Example code for the 'Callback function' in the above image:
 

   function gotResults() {
       var e = {dialog.object}.getGeolocation();
       alert('Lat = '+e.latitude+' Lon = '+e.longitude);
     }
    

UX Component - Client-side Group Breaks - Aligning Summary Values with List Columns - The List control allows you to insert client-side group breaks in a List and to display summary values in the group headers and footers. In a columnar List layout you typically want to align these summary values with the appropriate List columns.

A new genie in the Header/Footer builder make this easy to do. The genie generates a sample Javascript function that you can easily modify.

Watch Video
Download Component
 

 

UX, Grid, TabbedUI and Custom Components - Local CSS and Linked CSS Files - SASS - When you define local CSS (at the Local CSS definitions property), or when you link in CSS files you can now use SASS syntax in your CSS definition.

NOTE: For more information on SASS syntax see http://sass-lang.com/

In the case of linked CSS files your CSS file should have a .scss extension and when you specify the name of the linked CSS files you should include the .scss extension.

 

TIP: You can turn off automatic SASS processing of your local CSS definitions by adding this property to the  Advanced, Other Properties section in the builder: 
    tmpl.sassProcessor = .f.

 

UX and Grid Builder - Editing HTML Content - Script Tags - When you add a <script> tag to HTML content that you are editing, by default Alpha Anywhere assumes that the type is 'text/javascript' and does not auto-complete or syntax highlight the text between the opening an closing <script> tags.

However, if you set the type to 'text/html', then Alpha Anywhere will treat the text in the <script> tags as HTML and will do syntax highlighting and html code completion.

This feature is very useful when you want to create strings of HTML for use in Javascript code.

 

 

UX and Grid Component - HTML Snippets - When writing Javascript functions, a common requirement in the Javascirpt code is to define a long string of HTML markup. A good example of where this requirement is common is when using the A5.u.template.expand() function in client-side templates.

For example, you might write Javascript like this:

 


var _d = {

    firstname: 'Fred',

    lastname: 'Smith',

    Address: {
                Street: '123 Main St',
                City: 'Boston',
                State: 'Ma'
            }
    };
 

var _t = [
    'Hello {firstname} {lastname}<br>',
    'Address: {Address.Street}<br>',
    '{Address.City} {Address.State}'
].join('');
 

var settings = {
    template: _t,
    partials: ''
}
var html = A5.u.template.expand(_d,settings);

 

 

The HTML template in the above code was written as an array of single-line strings that were then joined to create a long string.

 

While the above pattern for creating long strings is perfectly reasonable, it is difficult to write because the single-line strings all need to be Javascript escaped and you do not get any HTML auto-complete help while you compose the script.

 

A better technique is to add a static-text control to the UX and then to add the HTML template to the static-text control using a <script> tag with a type of "text/html".

Because the HTML markup is in a <script> tag, it will not be rendered when the UX is run. And because the type is 'text/html' the markup will not be executed as Javascript code.

Any text inside a  <script> tag with a type of "text/html"   will be highlighted as HTML text and the standard HTML auto-complete help will apply.

By giving a unique Id to the <script> tag, your Javascript can easily reference the contents of the <script> tag.

 

 

In the above example Javascript, the code can be changed as follows:

 

var _d = {

    firstname: 'Fred',

    lastname: 'Smith',

    Address: {
                Street: '123 Main St',
                City: 'Boston',
                State: 'Ma'
            }
    };
 

var _t = $('template1').innerHTML
 

var settings = {
    template: _t,
    partials: ''
}
var html = A5.u.template.expand(_d,settings);

 

And the template can be defined in a static-text control as follows

 

<script id="template1">

    Hello {firstname} {lastname}<br>
    Address: {Address.Street}<br>
    {Address.City} {Address.State}

</script>

 

json_flatten() Function - Takes a JSON string that defines an array of hierarchical objects and 'flattens' the array.

This function is useful for Reporting where the report data source is set to a Custom data source that returns JSON data. If the JSON data that is returned is hierarchical, then you will need to 'flatten' it in order to get it into an appropriate format for the report writer.

The syntax for json_flatten() is

c output = json_flatten(C jsonIn, c template)

The format of the template is shown in the following example.

 

Consider the following JSON String:


[
        {
            "id": "alfki",
            "name": "customer 1",
            "__a5crc": -253329,
            "orders": [
                {
                    "orderId": 1,
                    "orderData": "12/1/2013",
                    "ordcust": "1|||alfki",
                    "orderDetails": [
                        {
                            "lineitemId": 1,
                            "prodId": 1,
                            "qty": 3,
                            "ordprod": "1|||1"
                        },
                        {
                            "lineitemId": 4,
                            "prodId": 3,
                            "qty": 2,
                            "ordprod": "1|||3"
                        }
                    ]
                },
                {
                    "orderId": 3,
                    "orderData": "12/3/2013",
                    "ordcust": "3|||alfki",
                    "orderDetails": [
                        {
                            "lineitemId": 6,
                            "prodId": 4,
                            "qty": 9,
                            "ordprod": "3|||4"
                        },
                        {
                            "lineitemId": 7,
                            "prodId": 3,
                            "qty": 1,
                            "ordprod": "3|||3"
                        }
                    ]
                }
            ]
        },
        {
            "id": "bolid",
            "name": "customer 2",
            "__a5crc": -194126,
            "orders": [
                {
                    "orderId": 2,
                    "orderData": "12/2/2013",
                    "ordcust": "2|||bolid",
                    "orderDetails": [
                        {
                            "lineitemId": 2,
                            "prodId": 6,
                            "qty": 6,
                            "ordprod": "2|||6"
                        },
                        {
                            "lineitemId": 3,
                            "prodId": 9,
                            "qty": 7,
                            "ordprod": "2|||9"
                        }
                    ]
                }
            ]
        }
]


The JSON object defined by the above string shows an array of customers with embedded orders. For each order, there are embedded line-items.

The structure of the JSON object is

Customers

    Orders

        Order Details

 

The json_flatten() function takes two arguments - the JSON string you want to flatten, and a template that defines which properties in the input JSON you want to map to the output JSON.

Assume that the following template is specified:


{
   "id" : "id" ,
   "name" : "name" ,
   "orders" : [ 
                 { 
                    "orderId" : "orderId" , 
                    "orderData" : "orderData" , 
                    "orderDetails" : [
                                         { 
                                            "lineitemId" : "lineitemId" , 
                                            "prodId" : "prodId" , 
                                            "qty" : "qty" 
                                         }
                                    ] 
                } 
              ]
}

 

 

If you 'flatten' this JSON using the above template, you will get the following output:

[
    {
        "id": "alfki",
        "name": "customer 1",
        "orderId": 1,
        "orderData": "12/1/2013",
        "lineitemId": 1,
        "prodId": 1,
        "qty": 3
    },
    {
        "id": "alfki",
        "name": "customer 1",
        "orderId": 1,
        "orderData": "12/1/2013",
        "lineitemId": 4,
        "prodId": 3,
        "qty": 2
    },
    {
        "id": "alfki",
        "name": "customer 1",
        "orderId": 3,
        "orderData": "12/3/2013",
        "lineitemId": 6,
        "prodId": 4,
        "qty": 9
    },
    {
        "id": "alfki",
        "name": "customer 1",
        "orderId": 3,
        "orderData": "12/3/2013",
        "lineitemId": 7,
        "prodId": 3,
        "qty": 1
    },
    {
        "id": "bolid",
        "name": "customer 2",
        "orderId": 2,
        "orderData": "12/2/2013",
        "lineitemId": 2,
        "prodId": 6,
        "qty": 6
    },
    {
        "id": "bolid",
        "name": "customer 2",
        "orderId": 2,
        "orderData": "12/2/2013",
        "lineitemId": 3,
        "prodId": 9,
        "qty": 7
    }
]

 

 

 

 

Notice that the template has omitted the '__a5crc' in the input property. The template indicated which properties were to be extracted from the input JSON. It also indicates that the property name should be called in the output JSON.

For example, the template indicates:

 "id" : "id"

Had that been:

 

 "id" : "CustomerId"

 

The output JSON would have named the 'id' property 'CustomerId'.

 

Here is a simpler example:

 

dim json as c
json = <<%str%
[
    {"id" : 1, "name": "John", "kids" : [ {"name": "callie"},{"name" : "griffin"} ]},
    {"id" : 2, "name": "Tom", "kids" : [ { "name" : "betty" } ]}
]
%str%

dim template as c
template = <<%str%
{"id" : "id", "name" : "firstname", "kids" : [ {"name": "name"} ] }
%str%

dim json2 as c
json2 = json_flatten(json,template)
json2 = json_reformat(json2)

 



Here is what json2 looks like:

 

[
    {
        "id": 1,
        "firstname": "John",
        "name": "callie"
    },
    {
        "id": 1,
        "firstname": "John",
        "name": "griffin"
    },
    {
        "id": 2,
        "firstname": "Tom",
        "name": "betty"
    }
]

 

 

 

The json_flatten() function can also be used to simply map property names in the input JSON to new property names in the output JSON. For example, consider the following script:

 

 

 

dim json as c
json = <<%str%
[
    {"id" : 1, "name": "John"},
    {"id" : 2, "name": "Tom"}
]
%str%

dim template as c
template = <<%str%
{"id" : "id", "name" : "firstname"}
%str%


dim json2 as c
json2 = json_flatten(json,template)
json2 = json_reformat(json2)
showvar(json2)
 

The resulting JSON will look like this:

[
    {"id" : 1, "firstname": "John"},
    {"id" : 2, "firstname": "Tom"}
]

 

 

 

 

PhoneGap-  Modified The Default Location For Persistent Files - Previous versions set the Persistent File Location property to "Compatibility" mode on both Android and iOS devices. It has now been changed to "Internal" for Android and "Library" for iOS. This is the recommended setting on Android to ensure the files are contained within the app folder and that the files are deleted when the app is deleted. Under iOS, the files are always in the app folder, however, files in the Library folder are not available to iTunes nor are they synchronized to iCloud.

When "Compatibility" mode is set as the persistent file location for an Android PhoneGap app:

When "Compatibility" mode is set as the persistent file location for an iOS PhoneGap app:

In general "Compatibility" mode is NOT the recommended setting.

If you have used the PhoneGap file plug-in in previous versions, the default setting will make your app files inaccessible. The setting will not change for existing PhoneGap apps because the previous "Compatibility" setting will remain within the configuration file. Your app will only be affected if you delete the previous PhoneGap project and create a new one. You can change this setting by enabling Show Advanced Options in the Configuration Options settings of the PhoneGap App Builder Genie. Once the Show Advanced Options is enabled, you can change the persistent file location as required

Web Applications - Web Projects Control Panel - 'Search all files in this Project' Command - This command will now search in report, label and letter file (.i.e. .a5rtp, .a5lab and .a5ltr). The data source definition of the report layout (not the report body itself) will be searched.

UX Component - Action Javascript - PhoneGap - File System Actions - A new action in Action Javascript allows you to perform actions on the file system of the mobile device on which your UX is running.

NOTE: File system actions are only supported for PhoneGap applications.

The actions currently supported are:

 

All of these actions are performed asynchronously. For each action you specify the Javascript to execute once the action has successfully completed. If the action fails, the Javascript you specify for the on failure action is executed.

Because the actions are asynchronous, you cannot simply define an Action Javascript that calls two file system actions sequentially. For example, assume that you defined an Action Javascript that did this

  1. Create a new directory
  2. Write a file to the new directory

This would likely fail because the second action (write a file to the new directory) would be executed immediately after the first action (before the new directory had actually been created).

In order to make the above work, the second action (write a file) needs to be called in the first action's onSuccess function.

The asynchronous nature of file system actions makes it tricky to write complex scripts that perform many file system actions

In the above example, you would need to convert your Action Javascript to text mode and then rearrange the code.

For example, assume you defined the above two actions using Action Javascript. Once you converted to text mode your code would look like this:

 

{dialog.object}.phoneGapCreateDirectory('dir1', function() { //ok}, function() { //fail } );

 

{dialog.object}.phoneGapCreateFile('dir1/file1.txt','some data',function() { //ok }, function() {//fail },false);

 

To re-organize the code so that the write file action happens after the new directory has been created, we simply paste the action into the create directory's onSuccess function:

 

{dialog.object}.phoneGapCreateDirectory('dir1', function() {

    //ok

    {dialog.object}.phoneGapCreateFile('dir1/file1.txt','some data',

    function() { //ok },

    function() {//fail },false);

 

}, function() { //fail } );

 

 

UX Component - PhoneGap File System Methods - The following methods have been added to the UX for working with files on the mobile device.

 

NOTE: File system actions are only supported for PhoneGap applications.

 

Create a directory {dialog.object}.phoneGapCreateDirectory(dirName, onComplete, onError)
Create a directory (recursively) {dialog.object}.phoneGapCreateDirectoryRecurse(dirName, onComplete, onError)
Read a directory {dialog.object}.phoneGapGetDirectory(dirName, onComplete, onError)
Read a directory (recursively) {dialog.object}.phoneGapGetDirectoryRecurse(folder, onDirComplete, onDirError)
Remove a directory {dialog.object}.phoneGapRemoveDirectory(dirName,onSuccess,onError)
Remove a directory (recursively) {dialog.object}.phoneGapRemoveDirectoryRecurse(dirName,onSuccess,onError)
Delete a file {dialog.object}.phoneGapDeleteFile(fileName,onSuccess,onError)
Check if a file exists {dialog.object}.phoneGapFileExists(fileName,onResult,onFailed)
Read a file {dialog.object}.phoneGapReadFile(fileName,onReadFile,onReadFileERROR)
Create a file {dialog.object}.phoneGapCreateFile(fileName,text,onCreatedFile,onCreateFileERROR,flagAppend)

 

 

 

UX Component - Action JavaScript - Stripe Checkout- A new Action JavaScript has been added to the UX component that allows you to easily use Stripe Checkout.

Stripe Checkout, and the Stripe API, allow you to process credit card payments from within your desktop web or mobile app.

You will need to obtain your unique test and live authentication/api keys from Stripe prior to working with Stripe Checkout within your app. See the Stripe Website to setup your account.


A typical use case is to assign the action to a button click event, once the total of all items to be purchased has been computed.

 

Watch Video

Download Component

 


Specifying your Stripe API Keys: Stripe will issue you a total of four authentication/api keys. One set is for testing and one set is for a live app. The keys can be entered in explicitly within the Action Javascript builder or you may specify the keys within your project properties (click the Project Properties button when the Web Control Panel has focus).



Entering the Stripe Checkout keys in the Project Properties
Entering the Stripe Checkout Keys in the Project Properties allows you to easily use Stripe Checkout within multiple components. Be careful to enter the test keys (typically prefixed with sk_test and pk_test) and the live keys (typically prefixed with sk_live and pk_live) in the appropriate fields.

The secret key is used server side when the server is communicating to the Stripe API with the token supplied by Stripe Checkout. The secret key is never revealed client side.



Stripe App Type: The app type can be Test or Live. Use Test for all of your testing and when you are ready to go live you must switch this property to Live and republish the app. If you are building a PhoneGap app, make sure to rebuild the PhoneGap app and upload to PhoneGap Build.

Icon Image: The icon image is displayed at the top of the Stripe Checkout component. The recommended minimum size is 128 x 128 px. Supported image types include .gif, .jpeg and .png.


Currency type: This specifies the currency of the amount being charged. The code entered here is the 3 letter ISO country code. Stripe offers support for a worldwide range of currencies. You can accept payments in your supported currencies from almost any credit card and debit card no matter where the customer lives. Customers in other countries may be charged additional fees by their bank.


Charge description: A general description of the product or service being purchased. The JavaScript you enter here can simply return a string (like the example below), return the value contained within a control or return the result of a JavaScript function, defined within the UX component's JavaScript Functions property.



Charge amount: The amount (in cents) that is being charged. The JavaScript you enter here may simply return a number (example: return 1235; for a $12.35 charge), may read the value of a control (make sure you convert to cents!) or may return the result of a JavaScript function, defined within the UX component's JavaScript Functions property.



OnStripeCheckoutComplete: This event fires after Stripe has attempted to process the payment with the token supplied by Stripe Checkout. The JavaScript you enter here can examine the results returned from Stripe by calling the {dialog.object}.getStripeResults() method (see the sample code below). The {dialog.object}.getStripeResults method returns either a Stripe charge object with a wide range of properties or an error.

See Stripe Charges Doc for more information.


HTTPS For Your Site All submissions of payment info using Stripe Checkout are made via a secure HTTPS connection. However, in order to protect yourself from certain forms of man-in-the-middle attacks, it is suggested that you serve the page containing the payment form with HTTPS as well.


 

UX Component - Image Upload Action Javascript - Mobile - Amazon S3 - When defining an Image Upload action for a UX component that is run on a mobile device you can specify in the image should be uploaded directly to Amazon S3 rather than to the Alpha Anywhere server.

This option is only available if the image is bound to a character field in the Table to which the UX component is bound.

Image upload in a mobile application uses the camera, or the photo library to select the image.

The option to upload to S3 is available for both HTML5 camera access and PhoneGap camera access.

NOTE: In the case where you are building a PhoneGap application, it is very important that when you build your PhoneGap project you include all of the necessary plugins when you define your PhoneGap project. You must include the File, FileTransfer and Camera plugins.

The ability to upload file images to Amazon S3 when using the Image Upload action in Action Javascript for the 'Desktop' mode was released previously. More information about this feature can be found in this topic: Action Javascript - Image Upload Action - UX and Grid Component - Amazon S3

 

UX Component - Android - Client-side Events -  onKeyboard Event - A new event has been added that fires when the keyboard comes up, or is dismissed. This event is only supported on Android devices.

NOTE: The reason that the event is not supported on iOS is that under iOS the reported screen size of the device does not change when the keyboard is up.

NOTE: If you have set the UX quirks mode keyboardAffectsScreenSizeCalc property to true for backward compatibility then the onKeyboard event will not fire. For example:

{dialog.object}._quirks = { keyboardAffectsScreenSizeCalc: true};

 

 

UX Component - List Control - .setValue() Method - New Options - Several  new options have been added to the List control's .setValue() method. The options allow

Examples:

Select all records in a List:

var lObj = {dialog.object}.getControl('MYLISTNAME');

lObj.setValue({select: 'all'});

 

Select records by Group name (deselecting any existing selections):

var lObj = {dialog.object}.getControl('MYLISTNAME');

lObj.setValue({

    select: 'group',

    groups: ['CA','MA'],

    additive: false

})

 

Select records by Group name (preserving any existing selections):

var lObj = {dialog.object}.getControl('MYLISTNAME');

lObj.setValue({

    select: 'group',

    groups: ['NY'],

    additive: true

})

 

Select all rendered records in a 'Virtualized' list (if there are 100 records per 'page' and the List has (say) 2,000 records then there are 100 rendered records that will be selected):

var lObj = {dialog.object}.getControl('MYLISTNAME');

lObj.setValue({

    select: 'view',

    additive: false

})

 

 

UX and Grid Component - Javascript Actions - Filter List - The Define Javascript Action dialog now has a filter control to allow you to easily filter the list of actions. This is useful because some developers now have a large number of Javascript Actions defined in their components.

 

 

a5_json_viewer()  Function - The A5_json_viewer() function can be used to open a viewer for JSON data.

 

 

Xbasic - CURL Genie - The code generated by the Xbasic CURL Genie is now more flexible. Instead of generating a constant for the post body length, it now generates a variable. For example, assume that you paste this CURL command into the genie.

 

curl --data "param1=value1&param2=value2" https://example.com/resource.cgi
 


The generated output from the genie will now be:


dim cf_1 as extension::CurlFile
dim flag_1 as l
dim ce as extension::Curl

ce = extension::Curl.Init()
ce.setOpt("URL","https://example.com/resource.cgi")
ce.setOpt("NOPROGRESS",1)
dim posted_fields as c = ("param1=value1&param2=value2")
ce.setOpt("POSTFIELDS",posted_fields)
ce.setOpt("POSTFIELDSIZE_LARGE", len(posted_fields) )
ce.setOpt("USERAGENT","curl/7.40.0")
ce.setOpt("MAXREDIRS",50)
ce.setOpt("CAINFO",a5.Get_Exe_Path()+"\caroot\ca-cert.pem")
ce.setOpt("CAPATH",a5.Get_Exe_Path()+"\caroot")
ce.setOpt("SSH_KNOWNHOSTS","C:\Users\Cian\AppData\Roaming/_ssh/known_hosts")
ce.setOpt("TCP_KEEPALIVE",1)
ce.SetOpt("FILE",cf_1)
flag_1 = ce.Exec()
if flag_1 then
    showvar( "Headers: "+crlf()+cf_1.GetHeaders()+crlf()+"Content:"+crlf()+cf_1.GetContent())
else
    showvar("error: " + ce.Error() )
end if
ce.close()

 


 

 

File.to_property() Function - Can now automatically de-serialize a file that was serialized using property_to_string(), property_to_blob() or json_generate().

 

Example:

dim src.fname as c = "john"
dim src.lname as c = "public"
file.From_string("c:\data\sample.txt",property_to_string(src))
file.From_string("c:\data\sample.json",json_generate(src))
file.From_blob("c:\data\sample.dat",property_to_blob(src))


dim p1 as p
file.to_property("c:\data\sample.txt",p1)
? p1
= fname = "john"
lname = "public"


dim p2 as p
file.to_property("c:\data\sample.json",p2)
? p2
= fname = "john"
lname = "public"

dim p3 as p
file.to_property("c:\data\sample.dat",p3)
? p3
= fname = "john"
lname = "public"


 

UX Component - Static HTML Web Sites - Publishing to Amazon S3 - If you have a static UX component (i.e. the component does not make any callbacks to an Alpha Anywhere server), you can publish the static HTML site to Amazon S3. The advantage of this is that you don't need to publish your site to an Alpha Anywhere server and the site will be accessible from any browser that has an internet connection.

 

VERY IMPORTANT - The Amazon S3 bucket that you publish to must be configured to allow 'Public Read' otherwise when you try to access the application Amazon will return a 'Permission Denied' error. To set the correct policy on your Amazon bucket, you can use this JSON setting string in the Amazon Web Services console.

 

{
    "Version": "2008-10-17",
    "Statement": [
        {
            "Sid": "AllowPublicRead",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": [
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::specify_the_name_of_your_bucket_here/*"
            ]
        }
    ]
}
 

 



Web Applications - Publishing - Check Security Before Publish - You can now check if any pages, components, or reports in the list of files to be published are set as 'Always Denied' in the web security. This is useful if publishing new pages or components to verify the security is set before the new elements are published. The check is only performed if security is active, and will check all pages, and components and reports if component security is activated. Most other files have security set by file extension.

If the option is selected and the file list to publish includes pages, components, or reports that are set as 'Always Denied', a list of these files will be shown before publish. You can continue with the publish or cancel and correct any errors.

This option can be selected at publish, and a default value for the option can be set in the publish profile. The option can also be set separately for right click publish.

Web Applications - Publishing - Publish Page Security as Binary - Some projects may have very large number of entries in the 'Pages.SecuritySettings' security file. The file is normally stored as a text file, but if it is very large (over 1 MB for example), it may load slowly on the application server when the security is loaded. This security file can be converted to a binary file when published which will load much faster. If the security cache timeout is set to 0 to never check for updates, a slow load time will only impact the first request for a project.
 

a5_url_fromStorageJSONformat() Function - Generates a signed URL to download a file from Amazon S3 storage.

The a5_url_from_storageJSONformat() function can be used to display/download a file from storage (e.g. Amazon S3) directly, with very little load on the Alpha server. The purpose of the function is to take a JSON string that defines the address of an object in storage (e.g. Amazon S3) and to generate a signed URL that can be used to download the object directly to the client from storage without having to first download the object to the Alpha server and then have the Alpha server send the file to the client.

 

The JSON string format that defines the address of an object in storage is:

{cs: 'storage connection string', object: 'name of object', source: 'vendor'}

 

NOTE: Currently the only vendor supported is Amazon S3 so vendor must be set to 'S3'

NOTE: The storage connection string is defined by selecting the Tools, Storage Connection Strings menu when the Web Projects Control Panel has focus. When you define storage connection strings you have the option of encrypting the storage connection string. You must NOT encrypt the storage connection string or else Alpha Anywhere will not be able to parse the storage connection string to determine your storage credentials.

 

For example, assume you have a named storage connection string called 'myS3bucket'. A JSON string that defines the address of an object called 'ProductPrices.pdf' would be:

{cs: 'myS3bucket', object: 'ProductPrices.pdf', source: 'S3'}

 

To generate a URL to display or download this object you would do the following:

 

dim address as c

address = <<%txt%

{   

    cs: 'myS3bucket',

    object: 'ProductPrices.pdf',

    source: 'S3'

}

%txt%

dim url as c

url = a5_url_from_storageJSONformat(address)

 

The resulting URL would look something like this (assuming that the bucket name specified in the connection string was 'myBucket'):

https://s3.amazonaws.com/myBucket/ProductPrices.pdf?AWSAccessKeyId=key&Expires=expiration&Signature=signature

Where:

key - your access key - as defined in the storage connection string

expires - indicates how long the URL can be used for (only applies if the object was uploaded to storage as 'Protected Read')

signature - a special signature based on the credentials specified in the storage connection string.

By default, the expires property is 240 seconds. That means that if the URL is used more than 240 seconds after it was generated, Amazon S3 will return a 'permission denied' error. The a5_url_from_storageJSONformat() function takes an optional second argument where you can specify how long the URL is good for in seconds. The default value for this parameter is 240.

 

 

 

File Upload - Amazon S3 - A new action has been added to Action Javascript for the UX component to upload files to a bucket in Amazon S3 storage.

NOTE: This action is not available for the Grid Component. However, the standard 'File Upload' and 'Image Upload' actions in Action Javascript, which are supported in the Grid now supports an option to target the upload to Amazon S3.


Watch Video - Part 1
Watch Video - Part 2

 

The benefit of this method is that the upload occurs directly to the Amazon servers without putting any load on the the Alpha Application Server.

NOTE: There is a small load on the Alpha Server for each file that is uploaded because a callback has to be made to the Alpha server to sign the URL used for the upload. This is necessary because the secret key for your Amazon account is stored on the Alpha server.

Features of the Amazon S3 File Upload include:

 

IMPORTANT: Before you can upload files to Amazon S3, you must configure your Amazon bucket to allow CORS support. CORS (Cross-Origin Resource Sharing allows you to make callbacks to a different server than the server (the Amazon server in this case) from which the page was originally loaded (your Alpha server). To configure your bucket you will need to open the AWS console.  You can click the 'Setting CORS Support on your Amazon Bucket' in the Action Javascript builder for more information.

 

In order to create an action to upload files to Amazon S3, use Action Javascript. Select the 'File Upload = Amazon S3 Storage' action.

 

 

The genie for this action is shown below:

 

 

 

Method for specifying Amazon S3 credentials and bucket - There are two ways in which you can specify the credentials for your Amazon S3 bucket. You can specify a named storage connection string, or you can use the 'Explicit' option, in which case you will need to specify your Amazon access key, secret and bucket name.

NOTE: To create a named storage connection string, go to the Tools menu when the Web Projects Control Panel has focus and select the Storage Connection Strings menu item.

 

 

Allow multiple files - If you check this box, the user will be able to select multiple files. The files will be uploaded in parallel.

If you check this box then you can specify value for the Max total file size property, which is the maximum combined size of all selected files. By default, this property is set to -1, which means no maximum.

Display progress during upload - If you check this property, then progress will be displayed during the file upload.

NOTE: If you do not check this property, you can still create your own progress display by adding custom code to the Javascript On Progress event.

Allow cancel - Specify if the user can cancel the upload after it has been started, but before it completes.

Progress indicator type - The progress can be displayed either as a text that shows the percentage complete, or as a bar.

In the image below, progress is shown for a multiple file upload using the 'bar' option. Note that the Allow cancel property was also checked, and so a small button to the right of the bar is shown where the user can click to cancel the upload.

 

This next image shows progress using the 'text' option.

 

 

Placeholder for progress indicator - You must specify the name of a Placeholder control where the progress will be shown.

Authenticated read - Allows you to specify whether the file that is uploaded to S3 is 'public read' or 'authenticated read'. A 'public read' file can be read by specifying the URL of the object on Amazon S3. For example, assume you upload a file called 'Image1.jpg' and you use the same object name on S3 (i.e. you don't specify any code in the Target object name on Amazon S3 event so that the name of the object on Amazon is the same as the filename of the file on the client-machine), you will be able to read the file using this URL:

 

http://<nameOfYourAmazonS3Bucket>.s3.amazonaws.com/Image1.jpg

 

If the Authenticated read property is checked then you can retrieve an object from S3 using Xbasic functions in server-side code.

For example, assume you wanted to retried 'Image1.jpg' which had been uploaded to S3 with the Authenticated read property turned on, you could perform an Ajax callback that executed this code to retrieve the file and save it to a local file called c:\myfiles\Image1.jpg.

 

dim cs as c

cs = "::storage::YourStorageConnectionStringName"

a5storage_getitem_as_file(cs,"Image1.jpg","c:\myfiles\Image1.jpg")

 

The full list of a5storage helper functions is shown below:

 

 

Validating File Selection

You can specify a maximum file size for any file that the user can select. By default this is set to -1, which means no maximum.

If the Allow multiple files property is checked you can also specify a maximum total file size for all files combined.

You can specify list of file types that the user can select in the Allowed file types property. You can enter a comma delimited list of file extensions. For example

.png,.jpg,.jpeg

 

You can also customize the error messages that are shown if a rule is violated. For example, in the image below, the message that will be shown if the user selects a file that is larger than 1,000,000 bytes is

File exceeds max allowed size of [maxfilesize]

[maxfilesize] is a placeholder that will be replaced at run-time.

You can also completely customize the display of validation error messages by defining your own on Validate Error event handler in the Javascript Events section. You can also use language and text dictionary tags (<a5:r>..</a5:r> and <a5:t>..</a5:t>) to translate the messages into different languages.

If you define a custom on Validate Error handler then you should blank out the default messages so that the system messages do not display.

 

 

 

Javascript Events

The genie exposes the following Javascript events:

Target object name on Amazon S3 - If this event is not defined, the name of the object in the S3 bucket will be the same as the name of the object on the client machine. For example, if the user uploads a file called 'sales_analysis_march_2015.xlsx', the name of the file in the Amazon bucket will be 'sales_analysis_march_2015.xlsx'.

Your code in this event can reference these variables:

 

However, you can add code to this event to compute a different name on S3. Your Javascript code must return the name you want to use. For example, assume you want to store the uploaded file in a folder called 'sales analysis' then your Javascript code in this event will be

return 'sales_analysis/' + e.name

 

Before file select - fires after the user clicks the button to initiate the action, but before any files are selected. If your code executes return false, the action is aborted.

After file select - fires after the user has selected the file(s) to upload, but before any uploads have actually started. Your code can reference a Javascript variable called e, which is an array of objects containing information about each file that was selected.  If your code executes return false, the action is aborted. You can use this event to perform custom validation on the selected files before initiating the upload. If you are writing a custom onProgress event handler you can use this event to set up the HTML for your custom progress indicator.

On progress - Fires each time progress information is returned by Amazon. You can use this event to create a custom progress handler. You code can reference these variables:

On Upload Complete - Individual File - (If multiple files are allowed) - fires after each individual file has been uploaded.

On Upload Complete - All Files - (If multiple files are allowed) - fires after all files have been uploaded.

On Upload Complete - (If only a single file is allowed) - fires after the file has been uploaded.

On validate error - Fires if any file violates the file rules (maximum size or allowed type).

 

 

File Download - Amazon S3 - A new option has been added to the File Download action in Action Javascript to allow you to download files that are stored in Amazon S3 storage.

The File Download dialog allows you to specify the File Download 'Type' as 'Amazon S3 Storage'.

 

Watch Video - Part 1
Watch Video - Part 2

 

 

Once you set the type as Amazon S3 Storage you can specify additional properties. These include:

 



 

 

Download Mode - Direct and Indirect Mode

When you download a file from Amazon S3  you have the option of using Direct or Indirect mode. Indirect mode is most like a regular file download, excepting that the file must first be retrieved from Amazon S3 before it can be sent to the user. The user will be prompted to save the file on his computer. This mode is inefficient because the file has to first be retrieved from Amazon S3 before it can be sent to the user. Depending on the size of the file being retrieved, this can place a heavy load on the Alpha Anywhere server.

The Direct method on the other hand is much more efficient because the file is downloaded directly to the client from Amazon S3 storage. A lightweight callback is still made to the Alpha Anywhere server to 'sign' the URL used to retrieve the file from S3, but this callback places very little load on the server.

When you download using the Direct method there are some additional considerations that you have to be aware of. The typical way in which the download is accomplished is by setting the URL of a hidden IFrame element on the page (which Alpha Anywhere automatically includes on the page) to the URL of the object on S3. So, for example, consider the case where the user wants to download a .xlsx file from Amazon S3. The URL to this object might be something like:

https://s3.amazonaws.com/bucketnameOnS3/myspreadsheet.xlsx

 

Setting the src property of the hidden IFrame to this URL will cause the browser to display a prompt asking the user if they want to save the file. The browser does this because it does not have a built-in handler for .xlsx files.

Now consider the case there the user wants to download a .pdf file from storage. In this case the URL to this object might be something like:

https://s3.amazonaws.com/bucketnameOnS3/mypdf.pdf

 

However, browsers typically do have built-in handlers for .pdf files and so setting the src property of the hidden IFrame to this URL will not result in the user being prompted to save the file. Instead, the browser will actually render the PDF, but the user will not see it because the IFrame is hidden.

Therefore, the Download Action builder prompts for the ID of the IFrame where PDFs will be rendered (TIP: Set the initial address of this IFrame to about:blank) . The user will still not receive a prompt to save the file, but they will see the PDF document rendered in the IFrame that they specified. Once the PDF has been rendered, they will be able to right click on it and then save it to their machine (since the PDF render feature of the browser exposes this option).

A similar situation exists for image files and therefore the ID of an Image element must be supplied to render the images that are downloaded from S3.

The ID of the elements for PDF and Image files are specified at these prompts in the builder:

 

 

Action Javascript - Image Upload Action - UX and Grid Component - Amazon S3 - The Image Upload action allows you to upload an image and store the image in a field in the table to which the UX or Grid component is bound.

In the case where the image is bound to a character field in the target table you now have the new option of uploading the image to Amazon S3 storage rather than to the Alpha Anywhere server.

Watch Video - Part 1
Watch Video - Part 2
Watch Video - Part 3

 

Uploading the image to Amazon S3 storage is an extremely efficient solution because it places minimal load on the Alpha server (both for uploading the image and then subsequently displaying the image when the component is run).

When you choose the option to upload to Amazon S3 storage you can either upload the image as:

NOTE: The Image Upload builder has a property called Authenticated read. To use the 'public read' option, the Authenticated read property should  not be checked. To use the 'protected read' option, the Authenticated read property should be checked.

When you upload using the 'public read' option, the image is uploaded to Amazon S3 and then the URL to the image is stored in the character field in the database. For example, this URL might look like:

https://s3.amazonaws.com/yourBucketNamehere/imageFileName

This URL can be pasted into a browser address bar and the image from Amazon S3 storage will be shown. In other words, it is not necessary to supply any credentials in order to see the image.

When you upload using the 'protected read' option, the image is uploaded to Amazon S3 as a protected file and the value that is stored in the character field in the database is a special JSON string that contains information about the storage connection string and the object name on Amazon S3. For example:

{cs: 'name of your storage connection string', object: 'name of object on S3', source: 'S3'}

 

 

NOTE: When you check the Authenticated read property you must use the Named Storage Connection String option as the Method for specifying Amazon S3 credentials.

 

When the component is rendered, the Alpha server automatically takes this JSON encoded string and computes a special signed URL that can be used to retrieve the image from S3. This special signed URL expires after a certain amount of time (current set to 240 seconds).

 

When an image is upload to S3 the work flow is as follows:

When the component is run, if the image field in the current row that is being displayed, contains the special JSON encoded string which is used for protected reads, the Alpha Anywhere server converts this JSON string into a signed Amazon S3 URL that can be used to retrieve the image.

 

To use the Amazon S3 image upload option in the Image Upload genie, select the Upload target property and set it to AmazonS3 as shown in the image below.

The options for the  Upload target property are:

 

Once you select AmazonS3 as the upload target the Amazon S3 Storage Properties section is displayed, allowing you to set your Amazon S3 properties. For a complete discussion on these properties see the topic that documents the 'File Upload - Amazon S3' action in Action Javascript.

 

 

 

Action Javascript - File Upload Action - UX and Grid Component - Amazon S3 - The File Upload action allows you to upload a file and store the file in a field in the table to which the UX or Grid component is bound.

In the case where the file is bound to a character field in the target table you now have the new option of uploading the file to Amazon S3 storage rather than to the Alpha Anywhere server.

 

Watch Video - Part 1
Watch Video - Part 2

 

Uploading the file to Amazon S3 storage is an extremely efficient solution because it places minimal load on the Alpha server when the file is uploaded. In addition, once the file has been uploaded to Amazon S3, when the file needs to be downloaded, there are options to configure the download so that the download takes place directly from Amazon S3 to the client, placing no load on the Alpha server, or in the case of a protected read (see below), placing minimal load on the Alpha server.

When you choose the option to upload to Amazon S3 storage you can either upload the file as:

NOTE: The File Upload builder has a property called Authenticated read. To use the 'public read' option, the Authenticated read property should  not be checked. To use the 'protected read' option, the Authenticated read property should be checked.

When you upload using the 'public read' option, the file is uploaded to Amazon S3 and the File Upload action builder gives you an option of storing the URL to the file in the character field, or a special JSON string that contains information about the file's location on S3.

If you choose the URL option, the format of the data stored in the field is:

https://s3.amazonaws.com/yourBucketNamehere/fileName

 

This URL can be pasted into a browser address bar and the file from Amazon S3 storage will be downloaded, (or shown -- if the browser has a built-in handler for the file MIME type).  It is not necessary to supply any credentials in order to retrieve image.

If you choose the JSON option, the format of the data stored in the field is:

{cs: 'name of your storage connection string', object: 'name of object on S3', source: 'S3'}

 

When you upload using the 'protected read' option, the JSON option is the only option.

 

NOTE: When you check the Authenticated read property you must use the Named Storage Connection String option as the Method for specifying Amazon S3 credentials.

 

When a file is upload to S3 the work flow is as follows:

To use the Amazon S3 file upload option in the File Upload genie, select the Upload target property and set it to AmazonS3 as shown in the image below.

The options for the  Upload target property are:

 

Once you select AmazonS3 as the upload target the Amazon S3 Storage Properties section is displayed, allowing you to set your Amazon S3 properties. For a complete discussion on these properties see the topic that documents the 'File Upload - Amazon S3' action in Action Javascript.

 

 

 

 

 

Xbasic Modules - Live Preview - If you do a 'Full Preview' when doing Live Preview, Xbasic Modules that are used in your Xbasic code are now automatically published to the Live Preview folder.

 

Reports - Layout Table Reports - 'Keep Row Together' Property - A new property is available for Layout Table reports. This property will prevent a page break in the middle of the row. This property is useful for 'growable' row content, such as HTML and Linked Reports.

 

 

Alpha DAO - ODBC - New SQL Connection Property = A5ODBCTableList - There is a new property available on the ODBC connection string dialog labeled 'ODBC Table List' and identified in the connection string as A5ODBCTableList.

The default value for A5ODBCTableList is false; meaning no change in behavior. When set to true, the selected vendor behavior will continue for most functionality. The one exception will be listing tables. This will defer to the ODBC driver as you would see if you used 'ODBC' as your vendor.

This new option provides a fallback for ODBC drivers giving better control over the list of tables than the native syntax implementation.

One use case for this option is to limit the number of tables displayed in AS/400 (DB2 iSeries); which tend to include an entire library list (like a path in Windows) and can be quite large. The DB2 iSeries driver has optional parameters for the library list that can be set when creating a DSN; and which our connection string is unaware of. Checking 'ODBC Table List' when connecting to the AS/400 DB2 iSeries driver through an ODBC DSN defers to the driver itself to create the table list.
 

UX Component - List Control - Export Data to Excel or Ascii - You can now export data in a List control to either Excel or to Ascii files.

Watch Video

 

After the export file has been created you can either download the file to the client, or call an Xbasic function to further process the exported file. A typical use case where you might want to call an Xbasic function to process the exported file would be if you wanted to email the file to a list of recipients, or upload the file to cloud storage, such as Amazon S3 storage.

In the case where the List is based on a SQL query you have the option of:

Consider the case where you have defined a List and have turned on the pagination feature. You might have set the page size to 100 rows. The query that the List is based on might have 1,000 records, but the List will only show 100 rows of data at a time. If the export is based on the 'Data in the List' the export file will have 100 rows in it (because the List only has one page of data - 100 rows - in memory at any time). However, if the export is based on 'Data in the List Query' the export file will have 1,000 rows in it (subject to the Max Records setting which might limit the number of rows in the export file).

To export data in a List you can use Action Javascript to define the code.

  1. Select the 'List Control Actions' in Action Javascript

  2. Select the 'Export List data to Excel/Ascii' action from the list of available actions.

  3. Click the smart field to define the 'Export list data settings'.
     

In the case where the List is based on a SQL query, the builder shows the 'Export what' property which can be set to 'Data in List query' or 'Data shown in List'.

If the 'Export what' property is set to 'Data in List query' the 'Maximum number of records to export' property is shown.

 

 

In the case where the 'Export what' property is set to 'Data shown in List' or if the List is not based on a SQL query (in which case the data that is exported is always the 'Data shown in List'), the 'Customize field sizes and column heading in export file' property is shown.

NOTE: The 'Customize field sizes and column heading in export file' property is only shown if the 'Export format' is Excel.

This property allows you to customize the column headings in the Excel file and control the data types of the data in the excel file.

 

 

 

To customize fields, click the smart field for the 'Customize field sizes and column heading in export file' property.

A build opens up where you can enter a CR-LF delimited list of definition - one for each field  you want to customize.

The syntax for the definition can be shown by clicking the 'Show syntax help' hyperlink.

The syntax allows you to specify the data type, size and column heading of each column in the Excel file.

 

 

UX Conponent - List Control - List with Detail View - .addTableRows() Method - Insert Rows - The .addTableRows() method now has new options to allow you to add the new row at a specified position in the List (i.e. insert rows), rather than at the end of the List (append rows). For information on the .addTableRows() method, click here.

 

 

Bugs

UX Component - Tab Controls - Method For Selecting Active Pane - Automatic - Nested Tabs - If you had nested tab controls and the outer tab was set to use the 'Automatic' method for selecting the active pane, the watch expression that selected the active pane was not being generated correctly.

UX Component - Android - Scrolling - Fixed an issue where (in certain cases), after editing in a text control in a component, you could no longer scroll a Panel Card to the top or bottom of the Panel Card.

UX Component - onSynchronize Server-side Event - Open UX in Window - Cached Option - If a data-bound UX component was opened in a pop-up window and the allow caching of the child UX feature was turned on, and if the child UX had a long-running onSynchronize event, it was possible for the primary keys in the child UX to get overwritten with the wrong values the second and subsequent times the child UX was opened. If this occurred, any edits to data made in the child UX would have been applied to the wrong record.

UX and Grid Component - Amazon S3 - File and Image Upload - Uploading files to S3 buckets that were not in the default US East region was not working correctly.

UX Component - Container Width 100% - Break - On some browsers, if you have a two consecutive containers, each with a width of 100% and you do not have the break between the containers turned on, you might get strange behavior when you scroll the Panel Card that contains that containers. Turning on the break between the containers resolves the issue. Now, if you set a container's width to 100%, the break in the Container End is automatically turned on.

TabbedUI Component - onLogout Event - Fixed various issues with the onLogout event.

Grid Component - AlphaDAO - Compound Primary Key - If you specified that a Grid had a compound primary key and you selected the columns in the Primary Key in the order in which they should appear in the Primary Key, Alpha Anywhere would define the Primary Key in the order in which the columns existed in the schema. For example, if you specified that the primary key was Lastname, Firstname, but the schema order was Firstname, Lastname, the primary key was defined as Firstname, Lastname. To fix the problem you must edit the existing grid and reselect the primary key columns.

UX Component - {dialog.object}.panelGet() Method - Previously, if you called this method with an invalid Panel name, the method returned the top-most Panel (root Panel). Now, false is returned.

UX Component - List Control - Multiple Layouts - onOrientationChange - If a List has a separate layout for Landscape and Portrait mode, now, when changing orientation, the selected row is remembered when the List layout is changed.

UX Component - Edit Combo - Different Stored and Display Values - Data Source Type Xbasic Function - Previously different display and stored values were only supported if the data source was AlphaDAO. Now, it is supported for Xbasic Functions.

Grid and UX Component - Export to Excel - Text Dictionary Tags - Text dictionary tags in column headings were not honored when exporting to Excel or Ascii files

Grid and UX Component - Export to Excel - SQL Databases - Dates - Dates are now exported using a date format that such that when the Excel file is opened the dates are shown using the regional settings of the machine. Previously the dates used a format that matched the regional settings of the server.

AlphaDAO - Postgres - Geography Searches - Fixed bugs in geography searches. Radius search was failing and case of search field was not properly preserved when the SQL WHERE clause was composed.

copy_folder() Function - Under some circumstances, the copy_folder() function did not copy files.

UX - List Control - Server-side Summary Fields - Under some circumstances the server-side summary fields values were not available in the 'summary' object when the afterServerSideSummaryFieldsComputed event was fired.

Grid Component - Read Only Grid - .getValue() Method - Empty Values  - If the .getValue() method was used to read the value in a control that was empty, the method would return '&nbsp;' for the value rather than a blank string.

Javascript Library - Date Object - .fromFormat() Method - The Alpha Anywhere Javascript library add a .fromFormat() method to the Javascript date object prototype. Under some circumstances (when using 'yyyy-MM-dd' as the date format string) strings representing date values were not correctly parsed into date objects.

UX Component Builder - Moving Controls Up/Down - Fixed an occasional error that was reported when moving controls up/down in the UX Component builder.

 

UX Component - onOrientationChange Event - Android - Fixed an issue where the onOrientationChange event did not fire on Android devices after the first orientation change, and then after that, it fired, but reported the wrong orientation. This bug resulted from know bugs with the Android orientation event that cause the screen size to be reported incorrectly when the orientation event is fired. We have worked around this issue by introducing a 300 ms delay after the system reports an orientation change before we read the screen size.

When computing the orientation on Android, the keyboard position is now ignored. Previously on Android if the screen was in (say) portrait mode and the keyboard came up, the onOrientationChange event would fire and report that the screen was in landscape mode. The onOrientationChange would also fire when the keyboard was dismissed. This is because when the keyboard is visible, the screen size that Android reports is affected by the size of the screen. On iOS, the keyboard does not affect the reported screen size.

If, for backward compatibility reasons, you want to use the old method on Android where the keyboard does affect the reported screen size, add this code to the onRenderComplete client-side event:

{dialog.object}._quirks = { keyboardAffectsScreenSizeCalc: true};

 

Navigation Component - iOS - Navigation component menus did not operate well on iOS devices.

Report Server - Temp File Cleanup - Under certain conditions temporary files created for SQL based reports were not being deleted when the report was completed. These files are now immediately deleted when the report is finished. The report server now uses the temporary file cleanup setting from the parent Application server to remove other old temporary files created by the report server.

UX Component - List with Detail View - Image Capture - Fixed an issue when a UX component had more than one Detail View image capture field on it.

UX Component - Panel Card - Text Area Control - Scrolling - Fixed an issue with scrolling text in a text area control when the control was in a Panel Card.

Excel Import - Determining Field Type of Imported Data - Made a change to Excel import so that more rows of the sheet are examined in order to determined the field type of each column in the Excel sheet.

UX Component - Arguments - Bound to Session Variables - If an argument value was bound to a session variable, the argument value was not getting updated on Ajax callbacks if the value of the session variable was changed after the component was initially rendered. Also, if the session variable was set in the onDialogInitialize or onDialogExecute server-side event, the argument values were not getting reset to the new value of the session variables.

Video Component - Opening from Button on uX Component - Under some circumstances, if you had a button to open a Video component on a UX component, it would fail.

UX Component - PhoneGap - Linked Javascript Files - {HeadSection} Directive - If a UX component linked a Javascript file and specified the special {HeadSection} directive, the linked file was not copied into the PhoneGap project folder.

Web Applications - Web Security - New Password Encryption - A new password encryption process has been added that generates a much longer encrypted value for a password. This is considerably more secure than previous encryption methods as a password cannot be decrypted even if a person has the project's password encryption key.

The security settings genie now has a new property on the 'User Id and Password Options' tab under 'Password Options'. If password encryption is selected, a 'Password use legacy encryption' option is shown. When checked, the system will use the legacy encryption method used in earlier Alpha Anywhere builds for any new passwords entered. If the option is not checked, any new passwords entered will use the new password encryption process.

New security systems will use have the 'Password use legacy encryption' property un-checked by default and will use the new encryption process. Existing security systems will initially have the 'Password use legacy encryption' property checked and will continue to use the older encryption methods. The property can be changed at any time and will only impact new passwords being entered. Existing passwords are not converted when the property is changed. The new process will still use any existing encryption key that has been defined for the web security.

This system is compatible with previous Alpha Anywhere builds as passwords encrypted in previous versions will still work. It is not necessary to convert any existing passwords.

However, all existing passwords in a project or published application can be converted to the new scheme if desired with a new utility function.

The function 'a5ws_RefreshPasswordEncryptionUtility()' can be run from the development program interactive window or the application server interactive window. When run from the development program, a list of all projects in the workspace that have security will be shown (unless there is only one project). When run on the application server, a list of all applications in the webroot that have security will be shown (unless there is only one application).

The function will convert all previously encrypted passwords in the selected application or project to the new password encryption. If the optional parameter 'UseLegacy' is set to True, all passwords will be converted back to the legacy encryption scheme.

 

NOTE: Only Alpha Anywhere builds after release build 2614-4409 can recognize passwords that are encrypted with the new method. If you want to roll back to build prior to 2614, you must first run the utility to convert all passwords back to the legacy encryption used in the earlier builds.


If you change the encryption key or add a new key, all existing passwords will be lost, and will need to be re-entered.

 

 Recommended Action

 

UX Component - Tab Controls - Fixed a bug where the UX would fail if the last control in a Tab Pane was hidden and the previous control was any type of container end control.

a5_merge_JSON_into_template() Function - Application Server - The a5_merge_JSON_into_template() function did not work when called from Xbasic code running in the Application Server. It only worked in the Development Server.

Xbasic Code - File System Dictionaries - Fixed a bug when exporting code to a File System Dictionary that was not relative to the Workspace.

UX Component - Arguments - OnSynchronize and OnDialogExecute Events - Under some circumstances argument values shown in the server-side onSynchronize and onDialogExecute events did not reflect the argument bindings that had been defined.

Javascript Code Editor - Code Colorization of Commented Out Code - Code in commented out sections was not always colorized correctly. This was a cosmetic bug - it had no effect on application.

Reports - SQL Data Source - Image File Reference Fields - Fixed a bug where Image File Reference fields were not working correctly.

Grid Component - Row Expander - Scroll Position on Page - If a Grid had been scrolled on the page and then a Row Expander for a row near the bottom of the page was opened and the user clicked on one of the rows in the Grid shown in the Row Expander, the parent Grid would scroll back to the top of the page. This is fixed now, but you can also work around the issue by using a master template in the child Grid and wrapping the master template in a div with a position:relative; style attribute. For example

<div style="position:relative;">

</div>

UX Component - Panel Cards - Tab Control - Hidden Controls - If a UX component used Panel Cards and you had a Tab Control in one of the Panels, if the last control in a given Tab Pane was hidden, the UX would fail. This is now fixed but you can also work around the bug by simply moving the hidden control up so that is is no longer the last entry for the Tab Pane.

UX Component - Pop-up Window - Google Map - As a result of a recent change Google made to Google Maps, the following pattern had stopped working:

  1. create a UX with a map control in a container window
  2. create a button to show the window

When the UX was run the map, which should have been hidden because the window had not yet been shown, should have been hidden, but was not. This is now fixed.

List Control - Image Fields - Missing Images - In some situations, the 'missing image' for a field that did not have an image, was not being displayed.

Grid Component - Geography Search - Radius Search - If you performed a search for all records within a specified radius of a point and you specified that the search result should be sorted by distance from the center point, then if you tried to navigate to the next page of records in the search result you would get an error.

Tips

UX Component - List Control - Using a Slider Control to Scroll a List - Say you have a List control and you want to put a Slider control under the List to scroll the List. Assume that the name of the Slider control is 'Slider1'

 

Step 1 - Put this code in the List's AfterRenderComplete event

var s = {dialog.object}.getControl('Slider1');
var l = {dialog.object}.getControl('{dialog.listId}');
s.min = 0;
s.max = (l._data.length -1);
s.refresh();

 

This code sets the min/max values on the slider to match the row count of the List.

 

Step 2 - Put this code in the Slider control's onSlide event:

var l = {dialog.object}.getControl('LIST1');

//the value of the slider while it is being dragged is in arguments[0].value
var val = arguments[0].value
l.scrollToItem(val);
 

 

 

UX Applications - PhoneGap - iOS Native Date Picker - If your UX component allows editing for date field fields you might want to use the native iOS Date Picker in your app. This is easily done by:

1. Setting the HTML5 type for the textbox where you edit the value to 'date'

2. Setting the display format for the textbox to yyyy-MM-dd

3. If the UX uses a List control with a Detail View the client-side display format for the date field can be set in the List Control, Fields tab.

 

UX Component - List with Detail View - Searching while Offline - When you use the List Detail View genie to create a List control with an associated Detail View and Search part, the genie inserts code like this in the Search button's click event:


{dialog.object}.getControl('name_of_the_list').searchList({searchMode : 'auto'});
 

The 'auto' in the .searchList() method means:

1. if the List is not dirty then do a server-side search
2. if the List is dirty do a client-side search (because doing a server-side search would repopulate the List and blow away your unsynchronized edits)
 

If your List is not dirty and you do not have a connection, the command will do a server-side search (because the List is not dirty), but because there is no connection, the search will obviouslyfail.

Once approach is to test for connectivity before doing the search, and if there is no connection, then automatically switch to a client-side search. For example, you can change the code in the button's click event to:


var flag = {dialog.Object}._getOnlineStatus();
if(flag) {
    // device is connected - ok to so a server-side search
    {dialog.object}.getControl('name_of_the_list').searchList({searchMode : 'auto'});
} else {
    // device is not connected - must do a client-side search
    {dialog.object}.getControl('name_of_the_list').searchList({searchMode : 'clientSide'});
}
 

 

 

UX and Grid Component - Tab Controls - Right to Left - For Hebrew and Arabic applications you might want the Tab buttons on a tab control to be displayed right to left, rather than the standard left to right format.

To do this, you can add the following CSS markup to the Local CSS property in the component.

 

.{dialog.style}TabTButton, .{dialog.style}TabTButtonSelected, .{dialog.style}TabBButton, .{dialog.style}TabBButtonSelected {

       float: right;
}
 

 

Application Server - Silent Install - The Alpha Anywhere server installation program can be run in 'silent mode' by using the /S command line switch.

 

For example:

 

a5v12_AppServer.exe /s

 

However, the first time you install the Alpha Anywhere server on a machine you will need to specify your license key. Since you are doing a silent install, you cannot enter the license key in the Application Server UI as you normally would do.

You can add the license key to a special registry key and Alpha Anywhere will automatically install the license if it is found in this registry location.

The registry key in which you must install your license number varies depending on whether you are running on a 32 bit or 64 bit operating system.

 

The following command line shows how you can add your license number to the appropriate registry key

 

For 64 bit operating systems

reg add "HKLM\SOFTWARE\Alpha Software\Alpha Anywhere Application Server 12.0\httpd" /v ActivateLicense /t REG_SZ /d "yourlicensenumber"

 

 

For 32 bit operationg systems


reg add "HKLM\SOFTWARE\Wow6432Node\Alpha Software\Alpha Anywhere Application Server 12.0\httpd" /v ActivateLicense /t REG_SZ /d "yourlicensenumber"

 

The commands to add the registry key should be executed before you run the Alpha Anywhere install.
 

You can also specify the install path and the install group when you run the installer by setting Environment variables before you run the installer.

The installer reads the following environment variables

For example, from the Windows command prompt:

SET A5_MAINDIR=c:\AlphaAnywhere\Server

 

PDF Report Print on Development Server But Not Production Server - Occasionally we here from developers who report that their PDF reports are working fine on their Development server but when they deploy their application to their production server, the PDF reports do not print. The error that is report is:

 

Report did not print. Error reported was:
Report Server: 'Alpha Five Printer' (for creating PDF, RTF and HTML output) is not installed. Re-install Alpha Anywhere Application Server at line: 27

 

The error indicates that the Amyuni Printer Driver (also called the 'Alpha Five Printer') did not install properly on your server machine when the Alpha Anywhere Application Server was installed.

Here are some things you can check to resolve the problem:

 

That indicates the print driver did not install.  This can happen for a couple reasons.

  1. If you were not logged in as an administrator when the Application Server was installed the driver may not have installed.
  2. The driver may have installed, but isn't assigned to a port.
  3. The Application server is running under a system account
  4. The server is running under Server 2012 or Win 8 and the Windows Print Spooler is not running


The first issue can be checked and corrected fairly easily.  Log onto the server machine with administrator rights.  Open the "Devices and Printers" from the Windows control panel and see if the driver for "AlphaFivePrinterV4p5" is installed.  If it is, then open the "Printer Properties" and verify the printer is assigned to a port.  Normally, it is assigned to a NUL port.
If the printer isn't listed, open Windows Explorer or My Computer, and look for the folder that contains the Alpha Anywhere Application Server program.  It would normally be at:


C:\Program Files (x86)\a5V12 ApplicationServer

Find the subfolder named "AmyuniV4" and find the file "InstallAmyuniPrinters.exe".  Right click on the file and select to "Run as Administrator".  A window should open showing the progress.  If it fails to install, check any error message.  If it fails, the last issue may be the problem as Windows may not install any print driver if the spooler is not running.

If the driver is installed, or installs correctly, then the problem may be is the user rights.  If running the Application Server as a service with srvany, or under AlwaysUp, make sure the user login is not the "Local System Account". That account does not normally have printing privileges.  Is is best to run the program under a user with full administrator rights

 

UX Components - Panel Cards - Child Components that Open in a Parent Component Panel -- A common pattern when building mobile applications using the UX component is to have a master component with one or more  Panel Cards and then have buttons that open child components in a Panel Card in the master component.

When utilizing this pattern be sure to turn off the 'Body can scroll' property for the target Panel (i.e. the Panel in which the child UX will be rendered).

 

 

 

Alpha Anywhere V3.11 - Build 2689-4440 4-Feb-2015

 

Videos

UX Component Hiding/Showing/Enabling/Disabling Buttons in a Button List Control You can use Javascript to dynamically hide, show, enable and disable buttons in a Button List control on a UX component. You can also dynamically add and remove buttons from the Button List.

In this video we show the Javascript to dynamically alter the Button List.

Watch Video
Download Component

Date added: 2015-01-30

 

 

Features

Web Applications - Publishing Using FTP - CURL - When you publish your web application to an ISP, your publishing profile will typically specify that the method for publishing the files is FTP.

You then have the option of using either the built-in FTP features in Alpha Anywhere, or using an external FTP client.

If you choose to use the built-in FTP features in Alpha Anywhere, you now have a new option of using CURL FTP. Unlike the standard FTP feature in Alpha Anywhere (which uses Active mode), the CURL FTP option supports passive mode. Passive move is more reliable as is has enhanced error checking and error messages.

NOTE: Some FTP servers require passive mode and will not support the standard built-in Alpha Anywhere FTP features, which use active mode. In this case you must use the CURL FTP option.

 

To select the CURL option, check the 'FTP Publish with CURL' property in the Profile Editor dialog.

Passive mode FTP is slower than active mode FTP, especially when uploading a lot of files, rather than one large zipped file. Therefore it is recommended that you only use the CURL FTP option when using the 'InternalOptimized' option (which zips all of the files to be published into a single zip file).

 

 

UX Component - List Control - Disconnected Data Entry - Preventing Duplicate Records when Connectivity is Lost - When you are working with disconnected data in a List control there is a small possibility of a synchronization request being submitted to the server more than once - resulting in the possibility of duplicate records in the database.

To understand how this might happen, consider what happens when the user clicks the 'Synchronize' button on a device to synchronize edits that were made while offline.

  1. A JSON packet containing all of the edits that were made to the List (including any child Lists) is sent to the server.
  2. The server processes the updates.
  3. After the server has completed processing the updates, the server sends a response back to the client indicating which rows were successfully synchronized and which rows have errors. This response will set the 'dirty' state of each row in the List that had been edited back to 'clean'.

Obviously, in order for the server to receive the synchronization request, the user must have a connection. But suppose that AFTER the user sends a synchronization request to the server, but BEFORE the server completes the work and can send a response back to the client, the client looses connectivity.

The server will continue processing the updates to the server and will do all of the synchronization requests contained in the package sent from the client. The server does not know that the client is now offline and so, after it completes all of the work, it will send a response to client indicating which rows were successfully synchronized. However, since the client is now offline, the client will not receive this message from the server. This means that all of the rows on the client that were edited are still marked as 'dirty' (even though the server has successfully applied all of the edits).

Now assume that the client gets its connection back and the user clicks the 'Synchronize' button again. The client will send a JSON package to the server and this package will include all of the updates that were previously sent to the server.

In order to protect against this possibility, a special server-side log can be used to prevent synchronization commands from being executed more than once.

In order to turn on the server-side synchronization log, edit the List control and on the Detail View pane, check the Use server-side synchronization log table property.

 

 

 

Before you can check this property however, you must first define the setting for the Synchronization Log Table. To define these settings, click the Project Properties button when the Web Projects Control Panel has focus.

Scroll to the Offline Data Synchronization Log Table Settings section and set the properties for the table. You can map this table to an existing table in your SQL database or Alpha Anywhere can create a new table for you with the correct table structure.

 

 

Bugs

UX Component - List Control - Dynamic Images - Client-Side - Fixed an issue with dynamic, client-side images in a List control. Image did not display correctly after data in the List had been edited.

Grid Component - Linked Grids - Detail View - New Record - If a child Grid was linked to a parent Grid, when going to the new record in the child Grid's Detail View, the linking fields in the Detail View were not filled in with the linking values as they should have been.

Reports - Native SQL - Dynamic Filter at Runtime - If a report was based on native SQL, rather than portable SQL, then if you tried to apply a dynamic run-time SQL filter to the report, the dynamic filter was ignored. Now, the dynamic filter will be added to the native SQL query for the report. However, because this may be combining a native SQL query with a portable dynamic filter, there is no guarantee that the resulting SQL statement will execute correctly.

Video Finder - A bug was introduced in the previous update that prevented the Video Finder from opening.

 

 

Alpha Anywhere V3.11 - Build 2684-4438 30-Jan-2015

 

Bugs

UX Component - Signature Capture - Build 2682 introduced a bug when saving data from a signature capture control.

Grid Component - Linked Grids - Up/Down Keys - In some cases when using the up/down keyboard navigation keys to navigate in the child grid, the keystrokes were being handled by the parent Grid.

 

Alpha Anywhere V3.11 - Build 2682-4435 28-Jan-2015

Videos

UX Component  Dynamically Re-populate the Choices in an Edit-Combo using Javascript The choices shown in an edit-combo can be dynamically repopulated at run-time using Javascript.

Watch Video

Date added: 2014-12-21
UX Component Constraining an UX that has Panels to an Element Rather Than Entire Window When a UX component that uses Panels is rendered, by default it consumes the entire window (only true if UX uses Panels). That means that if you have created an .a5w page to render the component and placed HTML markup on the page that you would like to be rendered in addition to the UX component, that markup will be overwritten by the UX. An advanced property of the UX now allows you to specify that the UX should be constrained to an element, rather than the entire window.

In this video we show how an .a5w page can be defined with a DIV to contain the UX and how the UX can be configured so that it is constrained to this DIV element.

(Requires build 4411 or above).

Watch Video
Download Component

Date added: