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.4.4 - Build 4346-4889 18-May-2017

NOTICE:  Alpha Anywhere is now being being built with Visual Studio 2015. Previously Alpha Anywhere was built using Visual Studio 2013.

 

IMPORTANT: If you have UX components with Lists that have updateable Detail Views and these UX components were defined as pre-rendered then you will need to edit these components and resave them so that the pre-rendered code can be re-generated. You can use the Edit, Bulk Operations, Recalculate UX Components menu item to do a bulk update of your UX components.

 

Videos

AlphaLaunch Publishing Apps to a Device using AlphaLaunch Publishing Apps to an App store (especially the Apple App store) can be a time consuming and frustrating experience. Using AlphaLaunch you can quickly and easily publish Apps to Apple and Android devices, completely bypassing the App stores.

In this video we show how you can publish an App to a device using AlphaLaunch

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

Date added: 2017-03-26
UX Component Mobile Applications with Persistent Logins A common pattern in mobile applications is to not require the user to login to the application after they have successfully logged in for the first time.  The login should be persistent until is is explicitly revoked by the action of an Administrator, or until the end of the persistent login period is reached.

Unlike a traditional Web application built using the Alpha Security Framework, the user will not have to log in again once their session expires, or when they restart the application.

In this video we show how this pattern is achieved.

(Requires build 4307 or above.)

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: 2017-04-29
UX Component - ViewBox Control Get Data for Current Row in ViewBox A common use case for a ViewBox is a light weight alternative to the List control. In a List control it is easy to get the data for the row that the user clicked on. 

In this video we show how a ViewBox that is configured to display a list of data can be configured so that the data for the row that was clicked on can be obtained.


Watch Video

Download Component

Date added: 2017-05-14

 

 

IMPORTANT: If you have UX components with Lists that have updateable Detail Views and these UX components were defined as pre-rendered then you will need to edit these components and resave them so that the pre-rendered code can be re-generated. You can use the Edit, Bulk Operations, Recalculate UX Components menu item to do a bulk update of your UX components.

If you have PhoneGap applications that use Lists with updateable Detail Views, and if you want to update the server that handles the Ajax callbacks from your PhoneGap applications, you will need to rebuild your PhoneGap applications.

Features

Xbasic - JSON - Reshape JSON - extension::JSON::FormatMapped() Method - It is sometimes necessary to 'reshape' a JSON document, changing property names, creating arrays and objects from properties, etc.

The extension::JSON::FormatMapped() method allows you to do this.

The method takes two arguments:

 

For example, consider the following input JSON file:

dim jsonIn as c
jsonIn = <<%str%
{
    "id" : "001",
    "fname" : "John" ,
    "lname" : "Doe",
    "address1" : "12 Main Street",
    "address2" : "Box 20"
}
%str%

 

Say you want to reshape this JSON document so that it looks like this:

{
    "person": {
        "id": "001",
        "firstname": "john",
        "lastname": "public",
        "address": [
            "12 Main Street",
            "box 20"
        ]
    }
}

Here is the Map that would define to achieve the above transformation:

 

 

dim jsonMap as c = <<%str%
{
    "person" : {
        "id" : "id" ,
        "firstname" : "fname" ,
        "lastname" : "lname" ,
        "address" : [ "address1" , "address2" ]
    }
}
%str%

 

Notice that in the input JSON, there is a flat list of properties. The firstname and lastname properties are called "fname" and "lname"

 

In the output document, the firstname and lastname properties are called "firstname" and "lastname", the two address fields are in an array called "address" and all of the properties are now a child of a new object called "person"

 

Here is how you would transform the input JSON (jsonIn) using the map (jsonMap)

 

dim jsonOut as c

jsonOut = extension::Json::FormatMapped(jsonmap,jsonin)

jsonOut2 = json_reformat(jsonOut) 'format the JSON

 

 

 

 

Xbasic - JSON - Flatten JSON - extension::JSON::ExtractMapped() Method - Creates a flattened JSON object from a complex JSON object. The flattened JSON object has all properties at the top level, with no nested objects are arrays.

 

The extension::JSON::ExtractMapped() method allows you to do this.

 

Assume you have a complex JSON document as shown below. Note that the only top-level property is "person"


dim jsonIn as c
jsonIn = <<%json%
{
    "person": {
        "id": "001",
        "firstname": "John",
        "lastname": "Dublic",
        "address": [
            "12 Main Street",
            "Box 20"
        ],
        "otherInfo" : {

            "x": "value of x",

            "y" : "value of y"

        }
    }
}
%json%
 

 

Say you want to flatten this JSON document so that all properties are at the top level and also change some of the property names. The resulting JSON document should look like this:

 

 

{
    "id": "001",
    "fname": "john",
    "lname": "public",
    "address1": "12 Main Street",
    "address2": "box 20",
    "x_value": "value of x",
    "this is the y value": "value of y"
}

 

 

Here is the Map that would define to achieve the above transformation:


dim jsonMap as c
jsonMap = <<%json%
{
    "person" : {
        "id" : "id" ,
        "firstname" : "fname" ,
        "lastname" : "lname" ,
        "address" : [ "address1" , "address2" ],
        "otherInfo" : {

            "x" : "x_value",

            "y" : "this is the y value"

        }
    }
}
%json%

 

 

Here is how you would transform the input JSON (jsonIn) using the map (jsonMap)

 


dim jsonout as c
jsonOut = extension::Json::ExtractMapped(jsonMap,jsonIn)
dim jsonout2 as c
jsonout2 = json_reformat(jsonout) 'format the JSON

 

 

UX Component - Style 'Tweaks' - When working with version 3 and above styles (these include iOS7, AndroidLight, AndroidDark, Alpha), you can now define style 'teaks'. Tweaks are adjustments to the style definition that are stored in a separate file in the Web Project folder. The adjustments include new sub-themes and CSS classes, and changes to existing sub-themes and CSS classes.

Normally when you edit a system style (such as 'Alpha'), a local copy of the style is saved in the Web Project folder and your edits are applied to the local copy of the style.js and style.sass files. The disadvantage of this approach is that if, in a future version of Alpha Anywhere, the style is changed (to fix a bug or to add support for a new control type), the changes made to the system version of style.js and style.sass will not be reflected in the local copy of these files that you created when you edited the style. You would need to manually edit the system copy of these files and copy changes to the local copy of these files. This would be complicated because it would not be easy to find the parts of the file that had changed.

On the other hand, since style tweaks are stored in a separate file, there are no local copies of the style files you are tweaking. Therefore if a future version of Alpha Anywhere updates the style, the tweaks are applied to this updated version of the style and your tweaked style will automatically have all of the changes made to the system style.

Style tweaks for a particular style are stored in this file:

<web project folder>\css\StyleTweaks\<style name>\styleTweaks.json

 

 

To define style tweaks, click the smart button for the Style sub-theme and CSS 'tweaks' property.

 

 

NOTE: If you customize the style colors and fonts using the smart field for the Customize style color and fonts property, the changes to the SASS variables that define the style's colors and fonts are also stored in the style's Tweaks file.

 

NOTE: You can also adjust the CSS and sub-themes in a style using these properties:

However, the adjustments made here apply ONLY to the component you are editing, whereas style 'tweaks' apply to all components in the Project that use the tweaked style.

 

UX Component - FormView Control - Pre-Defined Editors - TextArea - A new pre-defined editor for a FormView control is now available in the Defined Controls section of the UX toolbox. The [Editor-TextArea] pre-defined control creates an editor for a FormView value. The editor uses a TextArea control and it has a vertical scroller so that long text can easily be scrolled on touch devices.

 

Javascript Editor - Auto-complete for built-in Node modules - When you are editing Node Javascript code in a Javascript editor in Alpha Anywhere, you now get auto-complete for built-in Node modules. For example, assume that you enter this code into your Javascript code to get the Node filesystem module:

var fs  = require('fs')

 

Now, when you type

fs.

you will get auto-complete, as shown in the image below:

 

 

Node API s - The Web Control Panel now has a new category - Node APIs.

 

 

A Node API is similar to a Node Service in that they both allow you to call code written in Node from Xbasic. The difference is in how you call the code.

A Node service exposes a single piece of functionality to Xbasic. You can invoke the Node service using the node_request_result() function.

For example, assume you have a Node service called mergeData. You would call this service, passing in arguments to the service, as follows:

dim p as p

p.name = "Fred"

p.city = "Boston"

dim result as c

result = node_request_result("mergeData",p)

 

On the other hand, a Node API allows you to define an Xbasic class with multiple methods whose method are implemented using Node. Your Xbasic code invokes the Node code by calling methods on an Xbasic class instance. Your Xbasic code will create an instance of the class by declaring a variable of type ::NodeServices::name_of_your_Node_API and then calling methods of this class.

For example, assume you have created a Node API called myAPI and that this API exposes two methods, method1() and method2() and that each method takes a single character argument. Here is how you would invoke these methods from your Xbasic code:

 

'Dim an instance of the API class

dim x as ::NodeServices::myAPI

 

'now call methods of the class

dim result1 as c = x.method1("alpha")

dim result2 as c = x.method2("beta")

 

In effect, the Node API allows you to extend Xbasic with methods that are implemented using Node.

 

NOTE: Future versions of Alpha Anywhere will allow for another use of Node APIs. You will be able to expose REST APIs whose endpoints are implemented using a defined Node API.

 

How to Create a Node API

To create a new Node API, select the Node APIs category in the Web Control Panel and then click the New button.

This will open a dialog where you can name the Node API and define the methods and implementation for the API

The API methods are defined in the Definition pane (shown in the image below). The syntax used for defining the Node API methods is the same syntax used for defining an Xbasic class. Note that the Definition does not include any actual Xbasic code for implementing each method. It simply define the functions that the API will implement.

The actual implementation of the methods is coded in Node code on the Implementation pane.

 

 

The Implementation pane fills in the stub Node code to implement the API methods. You will fill in the actual code for each of the functions in the API.

 

 

When you click the Save button two files are created in the node_services folder in your Web Project

When you edit a previously create Node API, the .js file is opened in the Alpha Anywhere Javascript editor, but the editor toolbar shows a special button (API Definition...) at the right edge of the toolbar:

 

 

The API Definition... button will bring up the Create Node API dialog (shown in the above images) where you can edit the API definition. When you exit the dialog, the the Implementation file (i.e. the .js file you are editing) will be updated to reflect the edited API definition.

 

Example

In this example, we will show how to create a Node API with four methods:

 

Here is how this API is defined in the Definition pane of the Create Node API dialog:

 

 

The code is reproduced below:

 

define class fileoperations
    function readfile as c(filename as c)
        helptext "read file"
    end function
    function writefile as l(filename as c ,contents as c)
        helptext "write a file"
    end function
    function fileInfo as fileInfo(filename as c)
        helptext "return information about a file"
    end function
    function specialN as n(n1 as n ,n2 as n)
        helptext "does some math"
    end function
end class

define class fileInfo
    dim filename as c
    dim filesize as n
    dim fileTime as c
end class

 

 

Notice that the fileInfo method's return type is fileInfo. fileInfo is defined as a class that has these properties: filename, filesize and fileTime.

When you create Xbasic functions that return multiple values, it is common to define the return type of the function as P ( as pointer). In the case of a Node API definition, you cannot define a method whose return type is P. If you want to define a method that returns multiple values, you must define a class, as shown above, and set the function return type to the class.

The definition shown above simply defines what the methods of the Node API are and what input parameters each method takes. The Definition does not contain any Xbasic code to implement the functionality of each method.

The implementation for the above definition is shown below:

Note that the implementation is written using Node code.

 

exports.api = {
    //read file
    // inputs:
        // call.arguments.filename - string
    // returns: string
    readfile : function(call) {
        var fs = require('fs');
        var _cb = function(err,data) {
            if(err) {
                call.error(err);
            } else {
                call.return(data)
            }
        }
        fs.readFile(call.arguments.filename,'utf8',_cb);
    },
 

   

    //write a file
    // inputs:
        // call.arguments.filename - string
        // call.arguments.contents - string
    // returns: bool
    writefile : function(call) {
        var fs = require('fs');
        var _cb = function(err) {
            if(err) {
                call.return(false)
            } else {
                call.return(true)
            }
        }
        fs.writeFile(call.arguments.filename, call.arguments.contents,_cb);
    },

 

   
    //return information about a file
    // inputs:
        // call.arguments.filename - string
    // returns: fileInfo { filename : "" , filesize : 1 , fileTime : "" }
    fileInfo : function(call) {
            var fs = require('fs');
            var _cb = function(err,stats) {
            if(err) {
                call.error('file not found');
            } else {
                var _d = {filesize: stats['size'], 'fileTime' : stats['mtime'], filename: call.arguments.filename}
                call.return( _d );
            }
    }
    fs.stat(call.arguments.filename,_cb);
},
 

    //does some math
    // inputs:
        // call.arguments.n1 - number
        // call.arguments.n2 - number
    // returns: number
        specialN : function(call) {
            var n = call.arguments.n1 + call.arguments.n2
            call.return(n);
        }
};

 

The implementation is a Javascript file that exports an object with the same name as the Node API. This object has function for each of the methods in the API definition.

The prototype for the object is automatically created from the Node API definition.

Notice that the implementation of the fileInfo method returns an object with properties that match the definition of the properties of the fileInfo class in the Node API definition.

Each method defined in the Implementation takes as its input an argument called call. This argument is an object that has a property called arguments which contains the input parameters to the method and it also has two methods, return() and error(), that allow you to return a result from the function, or report an error.

 

To use this API from your Xbasic code:

 

'Dim an instance of the API class

dim fo as ::NodeServices::fileoperations

 

 

dim p as p
p = fo.fileInfo("c:\myfiles\file1.txt")
?p.filename
= "c:\myfiles\file1.txt"
?p.filesize
= 2942097
?p.fileTime
= "2017-05-10T14:26:04.193Z"

 

 

 

 

Xbasic - pdf_fillinFields_get() - Gets a list of the fill-in fields in a PDF file. If a PDF file is created with fill-infields, this function will extract the names of all of the fill-in fields in the file. You can optionally extract additional information about each field.

Syntax

c result = pdf_fillinFields_get(c pdfFilename [, L flagExtendedInfo])

 

 

IMPORTANT: This function wraps a 3rd party library which you must install yourself before you can use this function. The download link for this library is: https://www.pdflabs.com/tools/pdftk-the-pdf-toolkit/pdftk_server-2.02-win-setup.exe

 

Examples (from Interactive window):

dim fn as c

fn = "c:\mypdffiles\pdfform1.pdf

?pdf_fillinFields_get(fn)

 

= {
    "first_name": "",
    "last_name": "",
    "date": "",
    "football": "",
    "baseball": "",
    "basketball": ""
}

 

 

Get extended information (from Interactive window):

 

dim fn as c

fn = "c:\mypdffiles\pdfform1.pdf

?pdf_fillinFields_get(fn,.t.)

= [
    {"title": "first_name","fieldType": "Text","fieldFlags": "0","fieldValue": ""},
    {"title": "last_name","fieldType": "Text","fieldFlags": "0","fieldValue": ""},
    {"title": "date","fieldType": "Text","fieldFlags": "0","fieldValue": ""},
    {"title": "football","fieldType": "Button","fieldFlags": "0","fieldValue": ""},
    {"title": "baseball","fieldType": "Button","fieldFlags": "0","fieldValue": ""},
    {"title": "basketball","fieldType": "Button","fieldFlags": "0","fieldValue": ""}
]

 

 

Xbasic - pdf_fillinFields_merge() - Merges data into a PDF file that has fill-in fields, creating a new PDF file with the filled in data. You can use the pdf_fillinFields_get() function to get the name of the fill-in fields in the PDF file.

Syntax

L result = pdf_fillinFields_merge(c pdfFileIn, c pdfFileOut, c JSONData)

 

 

IMPORTANT: This function wraps a 3rd party library which you must install yourself before you can use this function. The download link for this library is: https://www.pdflabs.com/tools/pdftk-the-pdf-toolkit/pdftk_server-2.02-win-setup.exe

 

The field values that you use in the JSON data must match the defined 'Export value' in the PDF form. Win the PDF form designer, you can specify an 'export value' for each field. In the Example shown below, the 'Export value' for the 'football', 'baseball' and 'basketball' fields was defined as 'Yes'.

 

Example:

 

dim jsonData as c
jsonData = <<%str%
{
    "first_name": "Fred",
    "last_name": "Smith",
    "date": "12/18/2003",
    "football": "Yes",
    "baseball": "Yes",
    "basketball": "Off"

}
%str%
 

dim pdfIn as c

dim pdfOut as c

pdfIn = "c:\mypdffiles\pdfform1.pdf

pdfOut = "c:\mypdffiles\pdfform1_filled.pdf


pdf_fillinFields_merge(pdfIn,pdfOut,jsonData)

 

Xbasic - Functions - Arguments as Arrays - You can now specify that an input argument is an array by adding a suffix of [] to the argument name. Previously you had to set the input type of the argument to P if the argument was an array.

NOTE: The array is passed to the function by reference.

 

Example:

 

function asText as c(arr as c[])
    asText = crlf_to_comma( arr.dump() )
end function

 

Testing:

dim arr[2] as c

arr[1] = "alpha"

arr[2] = "beta"

?asText(arr)
= "alpha,beta"
 

 

 

Xbasic - Functions - Return Arrays - Previously, an Xbasic function could return an array by setting the return type of the function to a Pointer. Now you can explicitly set the return type to an array by adding a suffix of [] to the return type.

 

function asAnArray as c[] (commaList as c)
    commaList = comma_to_crlf(commaList)
    asAnArray.resize(line_count(commaList))
    asAnArray.initialize(commaList)
end function

 

 

Testing:

 

arr = asAnArray("one,two,three")
?arr.size()
= 3

?arr.dump()

= one
two
three

 

Xbasic - Functions - Return a typed Array - You can now define Xbasic functions that return arrays of an explicit type by adding a suffix of [] to the return type. Previously you could only return a generic Pointer value.

 

For example, assume you had defined the following class:

 

define class mynamespace::point
dim x as n
dim y as n
end class
 

You can now define a function that returns an array of the mynamespace::point type.

 

function ToPointArray as mynamespace::point[](points as c)
    points = strtran(points,";",crlf())
    ToPointArray.initialize_properties("x,y",points)
end function

 

Testing:

pa = ToPointArray("1,1;2,2;1,2")

? pa[1]
= x = 1
y = 1

 

 

Web Control Panel - UX Components - Pre-rendered Components - Warning Dialog -  If you update to a newer version of Alpha Anywhere and you open a web project that contains any UX components that have been set to pre-render and any of these components were last pre-rendered with an older version of Alpha Aynwhere, you will now get a warning telling you that these UX components need to be re-rendered. The warning dialog will allow you to click a 'Bulk Update' button to automatically update all of the UX components that need updating.

 

UX Component - List Controls - Offline Applications - PhoneGap - Using the File System to Persist List data - When you build a mobile app that is intended to operate offline, the typical pattern is to use List controls with Detail Views and to turn on the option to persist the List data to storage.

The data in the List are persisted to the browser's localStorage, which is limited to about 5mb of data.

Now, if your mobile application is run as a PhoneGap application, you can persist the List data to files in the device's file system. This will allow you to work with much more data while you are offline.

To turn on the feature to persist List data to the file system, set the Persist where property to FileSystem.

 

 

When you set the Persist where option to FileSystem, the Persist mode option is automatically set to Edits and the property is hidden.

If you set Persist where to LocalStorage, you can set the Persist mode to either 'Full', or 'Edits'.

In 'Full' mode, each time the data in the List are edited, the entire List is persisted to localStorage (this is the mode that is implicitly used in all versions of Alpha Anywhere prior to this version).

In 'Edits' mode, each time the data in the List are edited, only the edited rows are persisted to storage.

 

NOTE: f you select the FileSystem option and your component is not running in PhoneGap, Alpha Anywhere will automatically set the option back to LocalStorage.


How Persisting Data to the FileSystem Works

When you persist List data to localStorage, when the List is initially populated the List data is persisted to localStorage. Each time the List data are edited, the entire List is persisted again to localStorage (unless you change the Persist mode option to Edits).  Because writing to localStorage is so fast, and because there is a built-in limit (of approximately 5mb) to the amount of data that must be written to localStorage on each edit, there is no perceptible delay when you are editing the data in the List.

However, writing to the FileSystem is much slower than writing to localStorage and because there is no longer a built-in limit as to the amount of data in the List, a different approach is taken when the FileSystem option is used. When the List is initially populated, all of the data in the List are written to a file in the FileSystem. Each time the List is edited, the only the rows in the List that have been edited are written to a second file in the  FileSystem. This will file will typically be substantially smaller than the first file (that contains all of the List data), and since the file is likely very small, writing this file to the FileSystem will be very fast, and again, there will be no perceptible delay when you are editing data in the List.

When the List is synchronized data in the synced rows are written to a third file in the FileSystem and the primary keys of any deleted rows are written to a fourth file in the FileSystem.

The filenames of these four files in the FileSystem are:

 

Where:

<listName> - is the Id of the List.

<namespace> is the value of the Namespace property (see image below).

NOTE: If the List data are being persisted to localStorage, the Namespace property is used in constructing the localStorage key name. If the List data are being persisted to the FileSystem , the Namespace property is used in constructing the filenames for the four files used to persist the List data and edits.

 

Location of the List Data Files in the FileSystem

The files for the List data are stored in the device's 'saved' filesystem. The location of the device's 'saved' filesystem is returned by the {dialog.object}.phoneGapGetLocalDirURL('saved') method. The files are stored in a directory (called _offline by default) in this location.

The following methods can be use to get the file system URL and folder for the List data files:

{dialog.object}._persistFS() - the file system URL of the directory in which the List data sub-directory is located

{dialog.object}._persistFolder() - the sub-folder in which the files are actually stored - name has a trailing / character.

The actual folder name of the files is therefore:

{dialog.object}._persistFS() + {dialog.object}._persistFolder()

 

For example, the fully qualified name of the file that contains all of the data in the List when the list is initially populated is therefore (assuming the List id is LIST1 and the UX Local Storage Namespace property was set to NS1):

{dialog.object}._persistFS() + {dialog.object}._persistFolder() + 'NS1.LIST.LIST1'

 

NOTE: In the case where the component is running in AlphaLaunch, the base folder for the files is in a special folder returned by the  A5.shell.getAppFileStorageDir() method. The {dialog.object}._persistFS() will return the appropriate base folder name when the component is running in AlphaLaunch.

 

List Virtualization

If you are populating a List with a large amount of data, it is strongly recommended that you turn on the List's virtualization feature. With virtualization turned on, populating a List with a large amount of data is substantially faster than populating the List with virtualization turned off.

To turn on List virtualization, set the Virtualization type property to Dynamic as shown in the image below.

 

 

 

 

DetailView Button Genie

The DetailView Button Genie now has two new options as shown in the image below:

 

 

 

Delete List Storage - This deletes the files used to store the List data. (If the List is set to persist to Local Storage and the Persist mode is set to Edits, this option will delete the List data from localStorage)

Dump storage data - Dumps out the contents of the files that contain the List data (If the List is set to persist to Local Storage and the Persist mode is set to Edits, this option will dump the List data stored in localStorage). The data can be dumped to a file on the server, a bucket on Amazon S3, and can also be written to a DIV or placeholder on the screen.

 

NOTE The DetailView Button Genie is accessed by clicking the [List-Detail View-Buttons] item in the UX toolbox  Defined Controls section

.

 

 

Deleting Storage

You can delete the files that contain the List data using this Javascript:

var ls = {dialog.object}._localStorageSettings;
{dialog.object}._persistToLocalStorageInitializeKeys(ls,'listId',true);

 

Deleting the files that contain the List data can be useful when debugging an application.

 

 

Grid Components - Publish Meta Data Files - Published grid components do not include meta data that is needed to open the component in the Grid Builder. Therefore the published grid files found in the server webroot can not be edited in the Grid component Builder. A new option has been added to the publish profiles to 'Publish Grid Meta Data Files'. This option is selected by default and a special data file with the component name and a '_a5wcmp_metadata' file extension will be published when the grid is published.

NOTE: The motivation behind publishing meta data files is so that if a developer no longer has access to the original grid component files (.a5wcmp files) from the Web Project Folder, but does have access to the published .a5wcmp files, they will still be able to edit the Grid component files in the Grid builder (as long as they also have access to the published meta data files - _a5wcmp_metadata). The published files for all other component types (i.e. other than Grids) can be edited in the development program component builders (and therefore it is not necessary to publish meta data files for these component types).


The special _a5wcmp_metadata file is not used by the web server, but can be converted into the original editable grid using an option 'Create Grid Component From Meta Data File' found in the Web Control Panel 'More...' drop down.

This option should only be turned off if there are backup copies of the original grids available outside of the development system.

UX Component - Mobile Applications - Persistent Logins - A common pattern in mobile applications is to not require the user to login to the application after they have successfully logged in for the first time.  The login should be persistent until is is explicitly revoked by the action of an Administrator, or until the end of the persistent login period is reached.

NOTE: The canAjaxCallback server-side event previously would only emit user-defined Javascript if the event denied permission for the callback. Now, user defined Javascript can be emitted even if the Ajax callback is allowed. This change was made to support the Mobile Application with Persistent Login pattern.



For more information on the approach used to implement this pattern, please view this document.

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
 

When you create a new UX component a new template is available for the persistent login pattern.

 

 

Alpha Anywhere Application Server - Self-signed Certificates - A change has been made in the way self-signed certificates are generated.

Alpha Anywhere Application Server - Request Object - As part of an ongoing initiative to standardize functionality between the Alpha Anywhere Application Server (AA Server)  and the Application Server for IIS (AA Server for IIS), the Request object in the AA Server server will be undergoing a number of changes. While no immediate action is required from developers, there are a number of planned changes that will potentially introduce incompatibilities for existing Xbasic code. Alpha Software is committed to minimizing the impact of these changes, and this release of Alpha Anywhere includes several new properties and methods on the Request object to allow developers to begin transitioning their code at their convenience. Future releases will continue to add functionality to ease this transition. All new functionality will work identically when running under either the AA Server or the AA Server for IIS.

The goal of these changes is to ensure that your applications will work identically on both the AA Server and the AA Server for IIS, thus allowing for a seamless transition between servers should you decide to deploy your app using the AA Server for IIS

New Functionality
 

Request.Cookies will be changing to be a System::Web::HttpCookieCollection in the future. Currently it is an Xbasic property class ("dot variable"). Once changed, any Xbasic code expecting a property class will fail. To prepare for the upcoming change, the new HasCookie() and GetCookie() methods can be used to replace code that directly operates on Request.Cookies. These methods will continue to work even after the underlying type of Request.Cookies is changed. These methods also work consistently in both the AA Server and the AA Server for IIS.

Request.GetCookie() returns null if the specified cookie does not exist, or returns a System::Web::HttpCookie instance if the cookie exists. Existence of the cookie can be checked in advance with Request.HasCookie().

Sample to see if a cookie exists:

if Request.HasCookie("MyCookie") then
    'cookie exists in the request
else
    'cookie is NOT included in the request
end if



Sample to read a cookie's value:

dim GreetingName as c = ""
if Request.HasCookie("Greeting") then
    dim GreetingCookie as System::Web::HttpCookie = Request.GetCookie("Greeting")
    GreetingName = GreetingCookie.Value
else
    GreetingName = "new user"
end if
Response.Write("Welcome " + GreetingName)
 


Sample of updating legacy code:
Sample old syntax:

dim MyCookieValue as c = ""
if eval_valid("Request.Cookies.MyCookie")
    MyCookieValue = Request.Cookies.MyCookie
end if
 

Sample new syntax:

dim MyCookieValue as c = ""
if Request.HasCookie("MyCookie")
    MyCookieValue = Request.GetCookie("MyCookie").Value
end if


 

Headers will be changing to a System::Collections::Specialized::NameValueCollection. Currently it is a character string containing the raw header text of the HTTP request. To prepare for the upcoming change, the new GetHeader() method can be used to replace code that directly operates on Request.Headers. These method will continue to work even after the underlying type of Request.Headers is changed. This method also works consistently in both the AA Server and the AA Server for IIS.

The Request.GetHeader() method always returns a string value. If the specified header name does not exist in the request, the returned value will be an empty string. There is no distinction between a header that does not exist, and a header that exists with an empty value.

Sample old syntax to get the value of a specific header:

dim HeaderValue as c = ""
HeaderValue = alltrim(extract_string(wr.Headers,"MyHeader: ",chr(10)))
 


Sample new syntax to get the value of a specific header:

dim HeaderValue as c = Request.GetHeader("MyHeader")



Deprecated Properties


Additional Documentation

Full documentation for the .Net class System::Web::HttpCookie can be found at https://msdn.microsoft.com/en-us/library/system.web.httpcookie.aspx

Full documentation for the .Net class System::Web::HttpCookieCollection can be found at https://msdn.microsoft.com/en-us/library/system.web.httpcookiecollection.aspx

Full documentation for the .Net class System::Collections::Specialized::NameValueCollection can be found at https://msdn.microsoft.com/en-us/library/system.collections.specialized.namevaluecollection.aspx

 

AlphaLaunch - Install Mobile Apps to Apple and Android Devices - AlphaLaunch is a free AppStore app that you can install on an Android or Apple device. Once AlphaLaunch has been installed on a device you can install as many Apps as you want to that device without having to go through the Apple or Android App stores, or without having to go through a PhoneGap build process (either Adobe PhoneGap Build or the Command Line Interface). The Apps are installed into AlphaLaunch, not directly to the device. This makes it extremely easy and quick to install new Apps on a device.


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

 

NOTE: AlphaLaunch is not licensed for use in a production environment if you do not have a subscription to the Enterprise Edition of Alpha Anywhere.

 

The use cases for AlphaLaunch include:

Once an App has been installed into AlphaLaunch it operates largely identically to the way in which it would operate had it been installed directly on the device. For example, even when there is no internet connection, you will be able to start any App that is installed in AlphaLaunch.

AlphaLaunch is not suitable as a means of deploying a public facing App that will be installed by many users who will go to the App Store to find and install your App. When an App is installed directly onto a device the App icon will appear on the device's home screen. However, when you publish to AlphaLaunch, the App will not have an icon on the home screen. To launch the App you will first have to launch AlphaLaunch and then you will be able to select the App from the list of Apps installed in AlphaLaunch.

 

NOTE: Apps installed in AlphaLaunch are PhoneGap applications (even though you did not have to go through the PhoneGap build process) and they can use any of the PhoneGap plugins that AlphaLaunch exposes. For more information see the section Understanding AlphaLaunch Limitations below.

NOTE: On Apple devices, there are other ways that you can allow a user to test an App that you are developing using the Apple Test Flight system. However, setting up Test Flight is complex. Alternatively, you could get the UDID of a user's device and use a special Apple publishing profile with PhoneGap build that allows Apps that you build to be installed on that user's device  (without having to submit the App to the App store). However, this too, is complex and you are limited to only 100 devices.

 

Understanding AlphaLaunch Limitations

To see the list of plugins that AlphaLaunch enables, tap the Settings button in the footer of the AlphaLaunch home screen.

Then make sure that the Show Support Settings switch is on.

 

 

 

Then scroll the screen till you see this menu item:

 

 

How to Install AlphaLaunch on a Device

To install AlphaLaunch on a device, simply go to the App Store and search for 'Alpha Launch'.

 

How to Run an App That Has Been Installed in AlphaLaunch

To run an App that was previously installed in AlphaLaunch, simply launch the AlphaLaunch App on your device by clicking the Launch icon.

 

Then scroll the list of installed Apps until you find the App that you want and tap on the App name.

 

How to Install An App Into AlphaLaunch

To install a new App into AlphaLaunch, tap the Manage/Add button in the footer of the AlphaLaunch App.

 

If there are any existing installed Apps a screen showing these apps will be shown.

Note that for each installed App, the name of the server from which the App was installed is shown. When an App is run, all Ajax callbacks are made to the same server from which it was originally installed.

 

'

 

You can use this screen to reorder the installed Apps. You can also use a 'press-hold' gesture on any of the Apps in the List to bring up a screen that will allow you to uninstall an App or to update the App.

Tap the Add button to  bring up a list of the available Apps on the server that AlphaLaunch is currently configured to use.

For each App that is listed, there is either an Install or Reinstall button. The Install button will appear if the App is not currently installed and the Reinstall button will appear if the App has previously been installed. Reinstalling a previously installed App is effectively updating the App to a newer version of the App.

 

 

 

How to Select the Active AlphaLaunch Server

When you click the Add button on the Manage App List screen, the Apps that are available on the active AlphaLaunch server are shown. You can change the active AlphaLaunch server by tapping the Settings button at the AlphaLaunch home screen.

 

Then, tap on 'Server Web Address for Downloading Apps....

 

This will bring up the list of registered servers.

 

Tap on the server you want to select, then tap the Select button.

 

NOTE: The Active AlphaLaunch server only controls the list of available Apps that you can install when you press the Add button to install a new App. If an App (called 'App1' for example) was installed from 'Server1' and then the active server is changed to 'Server2', when App1 is running, it will make Ajax callbacks to 'Server1', regardless of what server is currently designated as the 'active' server.

 

 

How to Register a New AlphaLaunch Server

 

To register a new AlphaLaunch server, follow the instructions (above) for selecting the Active AlphaLaunch server. On the Server List screen (shown above), tap the Add button.

This will bring up the Edit Server Info screen where you can either type in the server address or scan a special QR code that encodes all of the necessary information.

 

 

 

How To Publish an App to AlphaLaunch

 

To publish Apps to AlphaLaunch open the Web Control Panel and select the project that contains the Apps that you want to publish.

NOTE: An 'App' is a UX component. The UX component can call child UX components, but these child UX components should typically be configured as Precomputed so that they can load directly from the device (so as not to be dependent on an Internet connection).

 

Before you publish Apps to AlphaLaunch you must first 'register' the Apps you want to publish. Registering an App involves defining how the App will appear when it is shown in the AlphaLaunch home screen and how it will be described when a user displays the list of available Apps that can be installed into Alpha Launch

 

Registering Apps To Be Published to AlphaLaunch

To register the Apps from a particular Web Project for publication to AlphaLaunch, tap the More... button on the extreme right of the Web Control Panel.

 

 

Then select the AlphaLaunch, Publish Apps to AlphaLaunch... menu item.

 

 

This will bring up the AlphaLaunch dialog where you can register the Apps from the Web Project that you want to publish to AlphaLaunch.

 

 

To register a new UX component, click the Add component button and then select the UX component you want to publish.

 

 

The AlphaLaunch dialog will then show the component that you selected and the orange icon will indicate that the settings for this component have not yet been defined.

Either double click on the component name, or click the Edit component settings button to open the AlphaLaunch Settings dialog box.

 

 

The important properties on this dialog include:

 

 

You can preview how the App will appear in the AlphaLaunch home screen by clicking on the Preview app template hyperlink at the bottom of the screen.  For example, here is a preview of a template that is using a purple background color and an SVG icon.

 

 

Once you have registered all of the Apps in a Web Project that you want to publish to AlphaLaunch you are now almost ready to publish to AlphaLaunch.

But before you can publish you must first define a Publishing Profile that indicates where the Apps will be published (i.e. the Alpha Anywhere server and folder on that server where the Apps will be published). To define a publishing profile, click the Profiles button on the toolbar when the Web Project Control Panel has focus.

 

 

 

NOTE Each Web Project will typically be published to its own AlphaLaunch server address. For example, you may have 3 UX components in 'Web Project1' that you want to publish to AlphaLaunch and (say) 2 UX components in 'Web Project2' that you want to publish to AlphaLaunch. In both cases you may want to use the same physical Alpha Anywhere server. The Publishing Profile that you define for 'Web Project1' might specify that you want to publish to a folder called 'webProject1', in which case the server address for the 3 Apps in this group of Apps might be something like 'http://www.myAAserver/webProject1'. On the other hand, the Publishing Profile you define for 'Web Project2' might specify that you want to publish to a folder called 'webProject2', in which case the server address for the 2 Apps in this group of Apps might be something like 'http://www.myAAserver/webProject2'.

 

 

Once you have defined the publishing profile, click the Publish Apps to AlphaLaunch Server button on the AlphaLaunch dialog.

 

This will bring up the Publish to AlphaLaunch dialog. You will need to select the Publishing Profile to use and you will also need to specify the Sever URL (i.e. the url of the location where the Apps are being published).

 

Once you have published your Apps you will need to register the server in AlphaLaunch. AlphaLaunch will contact the server to get a list of the available Apps.

For instructions on how to register a server with AlphaLaunch, see the section above titled How to Register a New AlphaLaunch Server . To make it easy to register a new AlphaLaunch server (i.e. to avoid having to type in a long server URL on a mobile device keyboard), you will probably want to generate a QR code with with server address. Check the 'Show a QR code...' property before you click the OK button.

 

 

 

 

You can use Advanced mode when you want to republish to AlphaLaunch after having made a change to the App settings (e.g. the App template, description, version number, etc.), but not the App itself. This will speed up the process of publishing the Apps because it will avoid having to recreate the static fileset for each App.

 

 

 

Adding an Exit Button to your App

When an App is run in AlphaLaunch you will typically want to add an 'Exit' button to your App to go back to the AlphaLaunch home screen. If you do not add an Exit button, then after the user launches the App they will not be able to get back to the AlphaLaunch home screen to launch a different App.

You can use Action Javascript to add an Exit button, or you can code the Javascript for the button yourself.

To use Action Javascript, select the 'AlphaLaunch Actions' action for the list of available Action Javascript actions.

To code the Javascript directly, use this code:

if(A5.shell) {A5.shell.exitComponent();};

 

The code tests if you are running in AlphaLaunch, then if you are then it calls the A5.shell.exitComponent() method.

 

Troubleshooting

The most common problem with AlphaLaunch is that after you have published Apps to your AlphaLaunch server and you then go to AlphaLaunch to install the Apps you just published, the Apps are not listed on the Apps to Install screen. This cause of this problem is either the Application Server has not been started, or the Server Addrtess (i.e. URL) that was entered in the Publish to AlphaLaunch dialog was incorrect.

You can test if you entered a valid server address by going to a browser and entering the following URL into the browser

 

<server URL>/availableAppInfo.txt

 

 For example, if your server URL was entered as:

http://192.168.70.157/AlphaLaunchDemo

You would enter this address into the browser address bar:

http://192.168.70.157/AlphaLaunchDemo/availableAppInfo.txt

 

 

If you do not receive a response, then it is likely that the server URL that you specified is incorrect.

 

App Install Errors

If you are installing an App from a folder on an Alpha Anywhere standard server (as opposed to the Alpha Anywhere Server for IIS), you might get an install error if the App has a large number of files. This is because the Alpha Anywhere server limits the number of files that can be simultaneously served. The error will not occur if you are using the Alpha Anywhere server for IIS. You can work around this problem by copying the folder that contains your App files to a bucket on Amazon S3 and then setting the Download location for the App to the URL of this S3 bucket.

 

AlphaLaunch Methods

 

 

A5.shell.exitComponent() -- Exit the App that is running an return to the AlphaLaunch home screen

A5.shell.getAppDir() - Returns the file URL of the local directory with the App's files

A5.shell.getAppFileStorageDir() - Returns the file URL of the local directory where the Apps data files are stored (this is separate from other Apps).

 

UX and Grid Component - Language Definitions - High Order Characters - When you tag strings in a Grid or a UX with language tags (<a5:r> ...</a5:r> you must then define how the tags are resolved in each of the different supported languages. Previously when entering high order characters, it was necessary to HTML encode the character. Now you can just type in the characters directly into the Language Definition dialog box.

 

 

UX Components - Pre-render - Working Preview - Internet Explorer - jQuery - When you do a Working Preview of a UX component and all of the following conditions are met:

then jQuery will not be loaded.

If you need to have jQuery loaded while you are in Working Preview then you can either switch to Chrome for Working Preview, or change where jQuery is loaded from.

If you cannot switch to Chrome for Working Preview, and you cannot change the location from which jQuery is loaded, then you will have to make an Ajax callback to load jQuery. For example, you could use the following Xbasic function to handle the Ajax callback that loads the internal version of jQuery.

 

function loadJQuery as c (e as p)
    loadJQuery  = __hidden__javascript__a5_jquery_core() + crlf() + __hidden__javascript__a5_jquery_ui()
end function
 

 

Xbasic Function Libraries, Modules and Classes - Encrypt - Password Protect - When you create Xbasic Function Libraries, Modules or Classes in your Web Project you can now specify that the files should be encrypted, or both encrypted and password protected.

In order to encrypt a file the first line of the file must be an Xbasic comment (with no leading spaces):

'ENCRYPT

 

In order to both encrypt and password protect a file the first line of the file must be an Xbasic comment (with no leading spaces) of this form:

'PASSWORD:your_password

 

For example:

'PASSWORD:mysecretpassword

 

At run-time encrypted files are automatically decrypted.

If a file is password protected, then when you try to edit the file from the Web Control Panel, you will be prompted to enter the password. Once you have successfully supplied the file password you will no longer be challenged for the password when you next edit the file (until you exit from the Alpha Anywhere IDE).

 

.Net v4.6.2 - The Alpha Anywhere Installers now install .Net V4.6.2 if it has not previously been installed. Previously, the installers were installing v4.6.1

Bugs

UX Component - List Control - onSelect Event - Detail View - If a List had a Detail View and the List was configured to Allow Null Selection, when the List was rendered, the onSelect event would fire, even though no row in the List was selected.

UX and Grid Component - Action Javascript - File Download - International Characters - If the filename of the file to download contained international characters, the download would fail.

UX Component - Action Javascript - SQLite Actions - Create Table From Data Action - If the Create Table From Table action was configured to get the data by making an Ajax callback, if the data returned by the callback contained null values or values with double quotes, the action would fail.

UX Component - Google Maps - The API for scaling bitmaps uses as markers on a map was changed by Google. Support for the new API has been added.

UX Component - List with Detail View - Sync Log - The sync log feature was not working.

UX Component - List Controls - .dbf Tables - Mapped Table - If a List control was based on .dbf tables and if any of the .dbf tables in the databasource definition was a mapped table that included date fields, an error was generated.

UX Components - jQuery - Pre-rendered - If a UX component was set to pre-render and jQuery was specified to be loaded then in Live mode, jQuery was not being loaded. In Working Preview, jQuery was loaded (as long as you were using Chrome for Working Preview).

NOTE: For pre-rendered UX components that are set to load the internal version of jQuery that are rendered in Working Preview using Internet Explorer, jQuery is not loaded.

UX Component - PhoneGap - Action Javascript - Image Capture for List Detail View Action -  onImageCapture Event - The onImageCapture event was not firing if the image was captured using using PhoneGap

UX Component - PhoneGap - App Icons - The utility to create app icons in the PhoneGap builder was failing. if you have not installed your own copy of ImageMagick. This is now fixed.

Desktop Applications - Forms - MS Word Mailmerge - Was failing if the merge data contained a double quote.

SQL Server Reporting Services - Fixed an issue with multi-value input parameters.

UX Builder Crash - If all of the following conditions were met, then when doing a Working Preview of a component, Alpha Anywhere would crash

Web Applications - Multi-file Upload - If you created your own .a5w page to do file uploads, the multiple attribute in the <input> element was not handled properly.

Consider the following .a5w page. Notice that the <input> element uses the multiple attribute. Therefore, the control name must end in [] to indicate that multiple instances of this variable must be created (i.e. the variable must become an Xbasic array when the form is processed).

 

<form action="fileupload.a5w" method="post" enctype="multipart/form-data">
    Select images:

    <input type="file" id="files" name="selectedfile[]" multiple>
    <input type="submit">
</form>
 

When the files are uploaded, the above example specifies that an .a5w page called fileupload.a5w page will be called. Here is an example of how the fileupload.a5w page might be defined:

<%a5
dim files as p
files = request.variables.selectedFile

'files will be an array. the number of items in the array will match the number of files that were selected

'save each uploaded file to a folder

'ensure that the folder exists

dim folder as c

folder = "c:\uploads"

dir_create_recurse(folder)

 

dim count as n

'get a count of the number of files that were uploaded

count = files.size()

dim i as n

 

'loop over each item in the files[] array

dim fn_i

for i = 1 to count

    'construct the local filename

    fn_i = folder + chr(92) + files[i].filename

    'each file in the array has a SaveToFile() method

    'call this method to persist the uploaded file to a local file

    files[i].saveToFile(fn_i) 

next i
 

'Note: Each item in the files[] array will have these properties and methods:

'Properties:
    'Name
    'FileName
    'ContentType
    'CharacterSet
    'Encoding
    'Data - the data that was uploaded.

        'NOTE: It is recommended that you do NOT reference the 'data' property (especially for large files)

        'as it causes the data to be read into memory.
    'Size
'Methods

    'SaveToFile - save the uploaded data to a local file
    'SaveToStorage - save the uploaded data to storage (e.g. S3, Azure, Disk, etc.)
%>

 

Tips

Grid Component - Detail View - Disable Input Controls when Update Not Allowed - In a Grid component if you have the Security Framework enabled and the user does not have permission to update data, the input controls are still enabled even though the user will not be able to save any edits.

It might be desirable to disable input controls when the user does not have update permission.

Here is how this can be done:

First, define the following Javascript function in the component's Javascript Functions property:

 

function enableControl(alias) {

    var obj = window[alias + '_GridObj'];
    var val = obj._editPermissions.allowUpdate;
    return val;
}

 

Next, add the following expression for the client-side Enable expression for each of the Detail View input controls:

 

enableControl('{grid.componentName}')

 

NOTE The enableControl() function takes the Grid alias as an input parameter.  This allows the Grid object to be dynamically computed. If the enableControl() function had used:

{grid.object}._editPermissions

Then you would run into trouble if you had multiple Grids that defined the function because the last Grid that was displayed would overwrite the previously defined global function and the {grid.object} placeholder would resolve to the last Grid displayed.

 

Web2Cal Calendar Control - Adding Server Side Event Handlers To Respond to Event Changes -

When using the Web2Cal calendar control you might want to execute server-side code for the following events:

There are no built-in hooks for these events, but you can easily define you own.

For the event added, edited, or deleted cases, you can add event handlers as follows:


function onEventDelete as v (e as p)
end function 
function onEventUpdate as v (e as p)
end function 
function onEventAdd as v (e as p)
end function

 

How to Update the afterDialogValidate Event Handler Function
Make the changes shown in red to the afterDialogValidate  event.

'update the event on the calendar
dim javascriptUpdateCalendar as c
dim po as p
if pv.eventsMode = "EditEvent" then
    po.eventId = convert_type(e.dataSubmitted.eventId,"N")
    onEventUpdate(e)
else
    po.eventId = eventId
    e.eventId = po.eventId
    onEventAdd(e)
end if

 

To handle the event is moved case, edit the Web2Cal component and add this code to the onComponentExecute server-side event:

if eval_valid("request.variables._XbasicFunction") then 
	if request.variables._XbasicFunction = "updateEvents" then 
		'event was moved -- event data is in request.variables._calEvent_eventId, etc.
	end if 
end if 

 

 

 

 

Alpha Anywhere V4.4.3 - Build 4254-4863 04-Apr-2017

Features

Xbasic - a5_json_to_excel() Function - Export JSON Data to Excel - Exports data in a JSON document to an Excel file. If the JSON document is an object with multiple arrays, each array is exported as a separate sheet in the Excel file.

If the JSON document is an array, the Excel file will have a single sheet called 'Table1'

Syntax:

L flag = a5_json_to_excel(c Json, c filename)

Where

 

For example, if the JSON document shown below was exported to Excel, the Excel file would have two sheets ('customers' and 'phoneNumbers'). Each sheet would have the data in the corresponding array in the JSON data.

			{
	"customers" : [
		{"id": "1", "firstname" : "Fred", "lastname": "Jones"},
		{"id": "2", "firstname" : "Mary", "lastname": "Nickerson"}
	],
	
	"phoneNumbers" : [
		{"id": "1", "type" : "Home", "number" : "555-555-1234"},
		{"id": "1", "type" : "Office", "number" : "555-555-1235"},
		{"id": "2", "type" : "Home", "number" : "555-555-1236"},
		{"id": "2", "type" : "Office", "number" : "555-555-1237"},
		{"id": "2", "type" : "Vacation", "number" : "555-555-1238"}
	]
}


			

TabbedUI - onLogin Server-side Event - This event can now set data values that will be available when the client-side afterLogin event fires.

For example, you could add this code in the server-side onLogin event:

e.eventDataObject = "{userName: '"+e.userName+"', var2: 'some other value', timeOfLogin: '"+js_escape("" + now())+"'}"
 

In the client-side afterLogin event you can refer to any value in the eventDataObject.

 

For example:

alert('Welcome: ' + e.eventDataObject.userName );
 

Reports - Free-form Reports - Vertical Lines - Growable - You can now set the Growable property on vertical lines in a report. When this property is set, the vertical line will grow to the full height of the report section it is in.

 

 

For example, in the report shown below, the vertical line extends the full height of each record in the Detail Section without any gaps between the lines.

Bugs

Application Server for IIS  - Password Expiration - When publishing an application to IIS, if the application has a password expiration set, the expiration time will not be set correctly and can lead to users getting password has expired messages.
 

UX Component - List Control - Detail View - Parent-Child Lists - New Records - If you entered a new record in a child List and then synchronized the data, if focus was on the new child record at the time the sync command was executed, focus did not remain on this record when the sync completed.

Reports - SQL Data Sources - Null Values - Fixed an issue with character fields that had null values.

Reports - SQL Data Sources - Long Text - Fixed an issue with long text fields not printing all of the data in the field under some circumstances.

 

 

Alpha Anywhere V4.4.1 - Build 4246-4859 31-Mar-2017

Videos

UX Component - List Control Showing Content in Row When Row Is Selected A common use case with the List is to only show certain content in each List row when the row is selected. This is easily done using CSS.

In this video we show how this is achieved.

Watch Video
Download Component

Date added: 2017-03-26
     

Features

Alpha Anywhere Application Server - TLS Protocol - The Alpha Anywhere Application Server now allows the server administrator to specify the minimum TLS protocol version supported. While SSL v2 and SSL v3 had been fully removed from the Alpha Anywhere Application Server some time ago, it has not been possible to fully disable older TLS versions until now. This setting allows TLS 1.0 and TLS 1.1 to easily be completely turned off, if desired.

TLS 1.2 is the most recent protocol and generally considered to be the most secure. Setting the minimum TLS version to 1.2 will disable TLS 1.0 and TLS 1.1 and provide what is currently considered the highest level of security. Note however that not all older web browsers or operating systems support TLS 1.2. Site administrators should evaluate the needs of their users before modifying this setting.

This setting defaults to TLS 1.0, in order to prevent unexpected client connectivity issues.

 

Bugs

Reports - SQL Reports - Null Numeric Values - Null numeric values were being displayed as 0 and not blanks in reports. This bug was introduced in v4.4.0.

Xbasic - AlphaDAO - SQL Server - In certain cases, when listing tables in a SQL Server database, the 'dbo' schema prefix was added to all of the tables that were listed. This was not necessary and now when tables are listed, the 'dbo' schema prefix is not shown in the list of tables.

UX Builder - Duplicate Control - A bug was introduced in the Duplicate Control command in V4.4.0.

Application Server - Server Settings Dialog - Dialog Height - The OK and Cancel buttons were not visible on machines with less than 800 pixels vertical resolution. This issue was caused because the new Administrative Alerts feature (introduced in V4.4.0) caused the dialog height to increase in size. The Alerts properties have now been moved to their own tab in the dialog.

 

 

Alpha Anywhere V4.4.0 - Build 4238-4856 28-Mar-2017

 

 

Videos

UX Component Alignment Container The Alignment Container makes it easy to Left, Center or Right align a series of control on a UX.

Watch Video

Date added: 2017-02-02
Xbasic Using Xbasic Classes in Server-side code You can define Xbasic classes in your project and then use those classes in any server-side Xbasic code.

In this video we show how an Xbasic class definition can be added to a web project and then used in the server-side code that executes when an Ajax callback is made.

Watch Video

Download Components

Date added: 2017-02-11
UX Component - Map Control Adding Multiple Markers to a Map Control using Client-side Data Action Javascript has an action to add multiple markers to a map. The data that defines the latitude/longitude for each marker on the map (and also for the marker titles, details etc). can either come from server-side data, or from client-side data.

In the case of server-side data you specify the name of a Data Series that specifies the properties for each marker.

In this video we show how to configure the Action Javascript 'Add multiple markers to a map' action to use client-side data. This client-side data can come from a Javascript function, a List control, the client-side Data Cache, or, in the case of a PhoneGap application, by querying a SQLite database on a device.

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

Download Component

Date added: 2017-02-12
UX Component - FormView Control Lookup Fields When you create a FormView control, you might want to display 'friendly' values for some of the fields in the form. For example, you might want to display the Product Name, rather than the Product Id.

In this video we show how you specify a lookup for any field in the Form View control.

Watch Video

Download Components

Date added: 2017-02-14
UX Component - PhoneGap Using the CLI (Command Line Interface) to Build PhoneGap Applications instead of PhoneGap Build When you build a PhoneGap application from a UX component that you have built, the easiest approach is to use the Adobe PhoneGap Build service. Direct integration with PhoneGap Build is built into the Alpha Anywhere IDE. While the advantages of using PhoneGap Build are clear - no software to install on your PC, and ability to build apps for iOS on your Windows machine - there are also disadvantages. These include having to wait an uncertain amount of time before PhoneGap Build finishes the build (wait time depends on how busy the service is) and inability to use certain plugins not supported by PhoneGap Build.

Another way in which PhoneGap applications can be built is by using the PhoneGap CLI (Command Line Interface). When you use the CLI, you are not restricted to only the plugins supported by PhoneGap build. The disadvantage of the CLI approach is that you will first have to install the CLI tools and platform SDKs on your machine. You will also need a Mac to build for iOS.

In this video we give an overview of using the CLI.
Watch Video
See documentation

Date added: 2017-02-18
UX Component Using 3rd Party jQuery Libraries in Control Javascript The UX Builder allows you to define 'Control Javascript' which allows you to easily configure a UX control to use a jQuery controls (such as a date or time picker). However, in the case where the jQuery control is defined in a linked file, you can run into timing issues that result because the control javascript is executed before the linked jQuery file has loaded.

This video describes how you can resolve these timing issues.

Addendum: In the video we show that the control javascript function is created using the syntax:
var clockpicker = function()
This should be changed to window.clockpicker = function()

Watch Video

Date added: 2017-02-19
TabbedUI Adding a Search Feature to the TabbedUI It is not uncommon for developers to create TabbedUI components with a very large number of items. Users may then struggle to find a particular item in the list of available menu items. Adding a search feature to the TabbedUI component makes it very easy for users to find the menu item they want.

In this video we show how the search feature is added to the TabbedUI component.

Watch Video

Date added: 2017-02-24
Reports Using SQL Server Reporting Services Reports in an Alpha Anywhere Project Many organizations who use SQL Server also use SQL Server Reporting Services (SSRS). Using reports created in SSRS in an Alpha Anywhere project is possible.

In this video we show how reports defined in SSRS can be used in Alpha Anywhere applications.

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

Date added: 2017-02-25
Node Calling a Node Service that Returns Binary Data When you call a Node service from Xbasic, the service can return both text and binary data.

In this video we show how a Node Service can return binary data.

Watch Video

Date added: 2017-02-28
UX Component Running Asynchronous Functions Synchronously Many Javascript functions in an application are asynchronous. For example, functions that make Ajax callbacks are asynchronous and many PhoneGap functions are also asynchronous. Often you will want to call several asynchronous functions, but you want to execute the functions synchronously. For example, you do not want to call the second function until the first function has completed.

Javascript Promises are typically used to run asynchronous code synchronously. But Promises can be hard to understand and it can be tricky to restructure your code to use Promises. The Alpha Anywhere Javascript library has a function called A5.runChain() that provide an easy way to run asynchronous functions synchronously. Also, minimal changes need be made to your function definitions to make them suitable for use with the A5.runChain() function.

In this video we show how the A5.runChain() function is used.

Watch Video - Part 1
Watch Video - Part 2


Date added: 2017-03-04
UX Component Semi-circular Number Display Control The semi-circular number display control displays the value of a number on a semi-circular chart. It is ideal for dashboard type applications.

This video shows how you can add a semi-circular number display control to a UX component and how you can configure the component.

Watch Video - Part 1
Watch Video - Part 2

Download Component

Date added: 2017-03-04
UX and Grid Component Code Glossary The code glossary is a great timesaver when editing Xbasic and Javascript code.

In this video we show how to use the code glossary in the editors.

Watch Video

Date added: 2017-03-17
UX Component - Javascript Charts Introduction Javascript Charts allow you to create a variety of different chart types using Javascript. Because the charts are created client-side, using Javascript, these types of charts are ideal for disconnected applications where the Chart control cannot be used (as this control type produces charts server-side).

In this video we show how to set up a basic Javascript Charts.
Watch Video

Date added: 2017-03-26
UX Component - Javascript Charts Binding Chart Data to a Javascript Function The data shown in a Javascript Chart can be obtained by calling a Javascript function.

in this video show show how to bind the Chart data to a Javascript function.

Watch Video
Download Component

Date added: 2017-03-26
UX Component - Javascript Charts Binding Chart Data to Data From a SQL Database - Using a Data Series for Chart Data The data shown in a Javascript Chart can be obtained by querying a SQL database.

In this video show show how to bind the Chart data to data from a SQL database table by binding the Chart data to the data in a Data Series. The Data Series is populated with data from a SQL database table.

Watch Video

Date added: 2017-03-26
UX Component - Javascript Charts Binding Chart Properties to a Javascript Function Any property of a chart can be made dynamic by binding the property to the result of a Javascript function.

In this video we show how properties of the Chart  (in addition to the Chart data) can be made dynamic.

Watch Video
Download Component

Date added: 2017-03-26
UX Component - Javascript Charts Action Scripting Methods for Working With Javascript Charts Action Scripting exposes several methods for working with Javascript Charts.

In this video we show how you can use Action Scripting to resize a Javascript Chart.

Watch Video
Download Component

Date added: 2017-03-26
UX Component - Javascript Charts Action Scripting - Setting a Chart Property Using Action Scripting vs. Binding a Chart Property to a Javascript Function Action Scripting allows you to dynamically change properties (such as the Chart colors, or title) after the Chart has been rendered. However, you can also achieve the same result by binding the Chart properties to Javascript functions.

In this video we contrast the two methods for setting Chart properties.

Watch Video - Part 1
Watch Video - Part 2

Download Component


Date added: 2017-03-26
UX Component - Javascript Charts Using Action Scripting to Refresh Chart Data Action Scripting allows you to refresh the data shown in a Chart. If the Chart data is based on a Data Series, an Ajax callback to the server will be made to refresh the data in the Data Series on which the Chart depends and then the Chart will be redrawn, showing the new data.

In this video we show how Action Scripting is used to refresh the Chart data.

Watch Video

Date added: 2017-03-26
UX Component - Javascript Charts In Depth Example - Chart Based on SQL Data This example shows a pie chart whose data is obtained from a multi-table SQL query against the sample Northwind database. The Chart is based on a custom Data Series to generate the Chart data. The user can select the country for which the Chart should be shown from a dropdownbox control.

In this video we show how this Chart is set up.

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

Download Component


Date added: 2017-03-26
UX Component - Javascript Charts Understanding the Structure of the Javascript that Defines a Javascript Chart The Javascript used to define a Javascript Chart has a well defined structure, described in this video.

Watch Video

Date added: 2017-03-26
UX Component - Javascript Charts Javascript Chart Events In this example we show a Chart with a Tooltip event. After the Chart is resized, the Tooltip events must be re-registered.

Watch Video
Download Component


Date added: 2017-03-26
     

Features

UX Component - Copy/Paste Controls - The UI for copying and pasting controls has been simplified.

Grid, UX and TabbedUI Builder - Collapse/Expand Property Grid Categories - You can now quickly collapse or expand all categories in the Property Sheets. This can make it easier to find a property without having to open the Properties search dialog.

 

 

PhoneGap App Builder - Icons and Splash Screens - The way in which icons and splash screens (iOS calls them launch images) has been completely rebuilt and a new option has been added to the Application Master Image Resources category that allows you to generate a series of 9-patch splash screen images for Android devices (iOS does not support 9-patch images without additional libraries).



 

VERY IMPORTANT: It is very important that you create a new PhoneGap Project when generating custom icons and splash screens for your app because the PhoneGap app config.xml file has been changed to support new functionality.

When you supply a single image that needs to be resized for the numerous aspect ratios required by all of the different types of mobile devices, the aspect ratio will typically change and the resulting image will be out of proportion. The new resizing code uses a center weighting technique to clip the image without any change to the image aspect ratio. This technique is used for the generation of all of the splash screens and you need to be aware of that when you supply the images for the portrait or landscape orientations.
 

Recommended Image Sizes
For portrait splash screens, the recommended size is 1536px x 2048px.
For landscape splash screens, tre recommended size is 2048px x 1536px.
You can also specify a square image (suggested size is 2732px x 2732px) for both orientations and the resulting images will not be distorted.

Android 9-patch images
A 9-patch image is a standard png file that has been divided into a matrix of 3 x 3 rectangles (like a tic-tac-toe board). Each region in the matrix has specific stretch properties that allow the image to be resized without altering the aspect ratio of the center weighted rectangles. As such, 9-patch images can be stretched to fit the different screen sizes without clipping or distortion. You need to supply a square image that will be used for both portrait and landscape modes and the graphics need to be center weighted. The recommended size is 2732px x 2732px.

For more info on 9-patch splash screen images see: Cordova Splashscreen Plugin Documentation

 

NOTE:  iOS Storyboard Launch Images -  If you open and inspect the new config.xml file you will see support for iOS storyboard launch images (which act much like Android's 9-patch images). While the support is included in the image builder module, it hasn't been exposed because the current version of PhoneGap Build does not support it. As soon as PhoneGap Build supports the inclusion of iOS storyboard images, we will expose iOS storyboard support within the PhoneGap App Builder.

PhoneGap App Builder - Use ImageMagick Option -  This option has been removed as all icons and splash screens are now generated using ImageMagick.

 

 

UX Component - List Control - deselectAll() Method - A new method has been added to the List control to un-select all selected rows in a List.

Contrast this method with the low level ._deselectAll() method which also un-selects any selected rows in a List, but does not perform any action on child Lists or the associated Detail View that the List may have..

The .deselectAll() method wraps the ._deselectAll() method, but in addition to un-selecting rows in the List, if the List has child Lists with pre-fetched data, the selected rows in all child Lists are also un-selected, and the Detail View for the List (and the Detail View for any child Lists with pre-fetched data) is disabled (if the 'No record in List selected' property for the top-most parent List is set to 'Disable Detail View').

For example:

var lObj = {dialog.object}.getControl('CUSTOMERLIST');

lObj.deselectAll();

 

 

UX Component - Data Series - Publish to Client-side - You can now specify that the data in Data Series should be published to the client-side so that it can be used in your Javascript code.

You define Date Series either by clicking on the smart field for the Data Series property (on the UX Builder Properties pane) , or by click on the Menu button.

 

 

 

 

Your Javascript code can reference the data in a Data Series using the following syntax:

{dialog.object}._dataSeriesData.SeriesName.SubSeriesName

 

If the Data Series has no sub-series, then syntax for referencing the Data Series is:

{dialog.object}._dataSeriesData.SeriesName

 

 

 

Understanding Data Series

A Data Series is a series of values. Say you have a SQL query that returns the data shown in the table below.

Each column in the table is a series of data. For example, the data series in the pink Firstname column is

Fred, John and Sally.

 

Firstname Lastname Age
Fred Smith 23
John Jones 35
Sally Harrison 29

 

The name of the Data Series represented by the pink column in the above table is:

Names.Firstname

 

(where 'Names' is the arbitrary name given to the data table)

 

A common use case for Data Series is in charting applications. Both the Chart and Javascript Chart control in the UX component consume data series for the data shown in the charts.

 

Action Javascript

There is a new action in Action Javascript to perform actions on Data Series. The Data Series Actions action allows you to:

 

UX Component - Javascript Charts - A new option for generating charts in the UX component is now available. Javascript Charts generate charts using client-side data. Because Javascript Charts are generated using Javascript with client-side data, they are ideal for disconnected mobile applications.

 

 

NOTE: Javascript charts are based on the open source RGraph charting library. Only the SVG charts in this library are built into Alpha Anywhere. If you want to use any of the Canvas charts in this library, you can, but you will need to write the Javascript yourself.  For more information go to http://www.rgraph.net.

 

Contrasting Javascript Charts with the Chart Control

The Chart controls is a server-side control. The chart is rendered as a bitmap on the server and then the client-displays the bitmap image. Because the Chart control is a server-side control, it is not suited for disconnected applications. Also, since the Chart control is a server-side control, it will be slower than Javascript Charts.

To add a Javascript Chart to a UX component, select the [Javascript Chart] control in the Other controls section of the UX toolbox.

 

 

NOTE:  Tthe Chart control (i.e. the server-side charting control) is available in the Data Controls section of the UX toolbox.


 

 

 

After you add a Javascript Chart to your UX, you can then edit the Javascript Chart properties by clicking the smart field for the Chart properties property.

 

 

This will open the Javascript Chart builder, as shown below.

The top half of the screen is where you enter the Javascript code that generates the chart and the bottom half of the screen allows you to get a quick preview of the Chart.

In most cases you will get a quick start by selecting one of the Sample Charts. This will enter the Javascript for the selected chart and you can then tweak the Javascript to get the chart appearance that you want. You will likely also want to base the chart on real data, not the sample data shown in the sample chart.

 

 

To select a sample chart, click the Select Sample Chart button. This will open up a dialog showing the available sample charts:

 

 

Select the sample chart that you want. It will then fill in the Javascript for that chart into the builder. For example:

 

 

The Javascript shown in the window is the Javascript used by the RGraph charting library to render the Javascript chart.

 

Understanding the Pattern Used for the Chart Javascript

All of the sample charts insert Javascript that follows the same pattern.

 

var _settings = function() {

        //function that returns an RGraph settings object

}

var _chart = new RGraph.SVG.Bar(_settings()).draw()

 

{dialog.object}._jsCharts['{chartName}'] = {};
{dialog.object}._jsCharts['{chartName}'].settings = [_settings];
{dialog.object}._jsCharts['{chartName}'].object = [_chart];
 

 

Depending the RGraph chart type (e.g. Pie, Line, Bar, etc.), the appropriate RGraph function is called to render the chart.

A settings object is passed to the RGraph function. This settings object is created by calling the _settings() function.

NOTE: You do not need to include the RGraph charting Javascript libraries yourself in your UX component. The libraries are automatically loaded by Alpha Anywhere.

The Chart settings are stored in the _jsCharts object in the UX component object. These settings are stored to enable the chart to be refreshed with new data, to be changed on the fly by changing any of the chart properties, or to be dynamically resized. Notice that the settings object and the object object are arrays. This is because a chart can actually be composed of multiple charts each drawn on the same DIV.

The Javascript for the chart uses two special placeholders:

 

 

Using Real Data in a Chart

When you select a Sample Chart, the Javascript that is inserted into the Javascript window in the Javascript Chart builder uses static data. This is fine initially when you are designing a chart, but at some point you will want to replace the static sample data with 'real' data.

The source of this 'real' data must be client-side data. For example, it might be data from a column in a List control. You will need to create a Javascript function that gets the data from the List and then set the data property in the Chart settings to the this function.

In many cases the 'real' data will be data that you want to get by querying a database, calling a service (REST, SOAP, etc.), or running some custom server-side code. In the case where the data you want to use in your chart originates on the server, you will need to define a Data Series that retrieves the necessary data. (When you define the Data Series you will need to specify that the Data Series data should be 'published' to the client-side.)

For example, here are the settings for a simple bar chart that uses static sample data:

var _settings = function() { 
   var settings = {
      id: '{chartDiv}',
      data: [8,5,9,3,5,2,4],
      options: {
          gutterTop: 50,
          hmargin: 20,
          xaxisLabels: ['Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday'],
          tooltips: ['Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday'],                
          title: 'A basic Bar chart',
          titleSubtitle: 'A chart showing daily values for a week',
          titleSubtitleItalic: true,                
          colors: ['#7e9cf6'],
          shadow: true,
          shadowOpacity: 0.2,
          attribution: false
       }
   };
   return settings;
}
var _chart = new RGraph.SVG.Bar(_settings()).draw();			

 

Notice that the chart data is defined by the data property in the settings object.

Say we have a Javascript function that returns an array of values and we want to use the data returned by this function in the Chart. For example, the function that return an array of values could be defined as follows:

function getData() {

    return [1,2,3,4,5,6,7];

}

 

To base the Javascript Chart on the data returned by this function, we simply change the data property in the Chart settings to:

 

....

id: '{chartDiv}',
data: getData(),
options: {....

 

In the case where the data comes from a column in a List control, the Javascript function that gets the data would be something like this (assuming that the column in the List that contains the data is called 'Sales'):

function getData() {

    var lObj = {dialog.object}.getControl('myList');

    var _d = lObj._data //get list data

    var _a = []; //make empty array

    for(var i = 0; i < _d.length; i++) {

        _a.push(_d[i].Sales); //push data from the 'Sales' column onto the array

    };

    return _a;

 

}

 

If the data you want to use in your chart originates server-side, then you will need to create a Data Series. Assume you have created a Data Series called Sales, with two sub-series, Amount and Month.

The data in the Sales Data Series might look something like this:

 

Month Amount
Jan 200
Feb 220
Mar 190
Apr 250
May 270
Jun 210
Jul 300
Aug 320
Sep 290
Oct 330
Nov 300
Dec 350

 

You can reference data from Amount column in the above Data Series using this syntax:

{dialog.object}._dataSeriesData.Sales.Amount

 

Using this syntax, you could change the settings object for the example bar chart to:

 

var _settings = function() { 
   var settings = {
      id: '{chartDiv}',
      data: {dialog.object}._dataSeriesData.Sales.Amount,
      options: {
          gutterTop: 50,
          hmargin: 20,
          xaxisLabels: {dialog.object}._dataSeriesData.Sales.Month,
          tooltips: {dialog.object}._dataSeriesData.Sales.Month,                
          title: 'A basic Bar chart',
          titleSubtitle: 'A chart showing sales by month',
          titleSubtitleItalic: true,                
          colors: ['#7e9cf6'],
          shadow: true,
          shadowOpacity: 0.2,
          attribution: false
       }
   };
   return settings;
}
var _chart = new RGraph.SVG.Bar(_settings()).draw();			

 

Notice that the chart data, X axis labels and tooltips are all based on Data Series data.

 

 

Any Property in the Chart Can Be Dynamic

In the above examples we have set the Chart's data property to the result of a Javascript function call (first example), or to the value in a Data Series (second example). However, it is not just the Chart's data property that can be dynamic. Any property in the Chart settings can be set to a Javascript function, or Data Series value.

For example, in the above example, the Chart Title is defined using this settings:

titleSubtitle: 'A chart showing sales by month'

 

This could be changed to:

titleSubtitle: getChartTitle()

 

 

 

Working in the Javascript Chart Builder

When you are working in the Javascript Chart builder, the dialog has these buttons and hyperlinks.

 

The purpose of each of these buttons or hyperlinks is:

 

 

 

Setting a Chart's Background Color or Border

In some cases, you will want to set the background color or border of a chart. For example, the Chart shown below has a black background.

You can set the Chart background color and border using the Javascript Chart's Style property.

 

 

Setting Javascript Chart Size to 100%

You can set the Javascript Chart width to 100% (useful when the Chart is shown in a Panel Card). However, setting the Chart's height to 100% is not supported. You must specify an explicit height for the Chart. Also, unlike many other UX controls, Javascript Charts do not have a Fill Container property.

NOTE: If you set the Javascript Chart width to 100% and the Javascript Chart is contained inside a Panel Card, the Javascript Chart will automatically be resized when the device orientation is changed.

 

Action Javascript Javascript Chart Actions

The Javascript Chart Action in Action Javascript allows you to:

 

Methods

The following methods are available for working with Javascript charts:

 

{dialog.Object}.jsChartResize(UXJavascriptChart,width,height[,redrawMethod[,methodParameter]])  

Resizes a Javascript chart. You can optionally pass in a draw method to redraw the chart without animation, or with a specified animation option.

Where:



{dialog.Object}.jsChartSetProperties(UXJavascriptChart, properties [,drawMethod [,methodParameters]])

Resizes a Javascript chart. You can optionally pass in a draw method to redraw the chart without animation, or with a specified animation option.

Where:

 

 


{dialog.Object}.jsChartRefreshData(UXJavascriptChart)

Refreshes the data in Data Series that the Chart uses and then redraws the Chart.  An Ajax callback is made to the server to refresh the Data Series and then the Chart is redrawn using the new data. If the Chart is not based on any Data Series, then no Ajax callback is necessary and the Chart is redrawn.

Where:
 

 

{dialog.Object}.jsChartRedraw(UXJavascriptChart [,drawMethod [,drawMethodParameters [,properties]]])

Redraws a Javascript chart. You can optionally pass in a draw method to redraw the chart without animation, or with a specified animation option. You can also
optionally change chart property values when it is redrawn.

Where:

 


Building Dashboard Applications

Javascript Charts are ideal for 'dashboard' applications. You can design a UX component with multiple Javascript Charts each of which displays data on one of the metrics your dashboard is designed to monitor.

In situations where a large number of users are connected to the dashboard, and where you want to update the dashboards frequently, you can use Alpha Anywhere's Web-sockets feature to create an efficient application. Instead of having the UX component make periodic callbacks to the server to refresh the data shown in the dashboard charts, a scheduled CRON job on the server can update data for the dashboard, then when broadcast the data to all of the connected UX components.
 

 

Speed Typing Glossary - Javascript and Xbasic Editors - You can now define abbreviations that get automatically expanded in the Javascript and Xbasic editors. This can significantly improve your productivity when you are writing Xbasic and Javascript code.

For example, say that in the Javascript editor you frequently type the following code:

 

var lObj = {dialog.object}.getControl(

 

You can now define an abbreviation for this code snippet. Every time you type the abbreviation, it is automatically expanded. For example, you might specify that the abbreviation for the above code snippet is .gc.

Every time you type .gc in the code editor, .gc will be replaced with var lObj = {dialog.object}.getControl(.

 

Watch Video

 

The replacement text for the abbreviation can be arbitrarily long. It does not have to be a single line of text as in the above example. You can also specify where the insertion point should be placed after the abbreviation has been expanded.

You can also set rules that control when an abbreviation is expanded. For example, you can specify:

You can also specify if the abbreviations should be shown in auto-complete (just like auto-complete for functions and variables), as shown in the image below. If you specify that an abbreviation should be shown in auto-complete, you can define an optional description that will also be shown in auto-complete.

To define a glossary while editing either Xbasic or Javascript, right click, and select the Edit glossary command from the menu. The glossary editor is shown below:

Each line shows the abbreviation, expansion for the abbreviation, and expansion options ( S - show in auto-complete, F - expand if first word on a line, W - expand if preceded by a word boundary)

 

To edit an individual glossary entry, double click on the item, or click the Edit button. The editor is displayed where you can define both the abbreviation and the replacement text. You can also set the options for the glossary item.

 

 

 

email_send_noprofile() Function - Now allows for a blank username or password. The third parameter for email_send_noprofile() is the security mode. The valid options are blank (""), SSL, and TLS. This parameter is now optional.

 

Flying Start Genie - Row Expanders - The Flying Start Genie allows you to quickly build Grid components for all (or selected) tables in a database. Now, the Genie will automatically detect if there is a relationship between the Grids that are created and it will add a Row Expander to each Grid if that Grid has related Grids.

For example, in the image below which shows the Grid that was created for the Customers table in the sample Northwind database you can see that each row in the Grid has a row expander that shows the Orders for the selected customer. Similarly, the Orders grid has a row expander to show the Order Details for the selected Order.

 

 

 

UX Component - SemiCircularNumberDisplay Control - A new control type is available in the UX component. This control allows you to display a numeric value on a semi-circular chart. It is ideal for using in 'dashboard' type applications. You can configure the color of the control so that it changes depending on the value. For example if a numeric value is in the 'safe' zone, you might set the color to green, and if the value was in the 'danger' zone, you might set the control color to red.

Watch Video - Part 1
Watch Video - Part 2

To add a SemiCircularNumberDisplay control to your UX component, select the [More...] control in the Data Controls section of the UX Toolbox. Like other controls in the Data Controls section of the UX toolbox, the SemiCircularNumberDisplay control has both a .SetValue() and .GetValue() method that allows you to set its value and read its values.

 

 

This will display the list of additional control types:

 

After you add the control to the UX you can configure the properties of the control by clicking on the smart field for Control Properties. This will open a dialog where you can set the properties of the controls.

 

 

Properties of note in the builder include:

 

Defining Dynamic Colors

When you set the Color type to Dynamic you can define a series of ranges and the corresponding color for each range. Click the smart field for the Values ranges property (shown when the Color type is Dynamic) to open the builder (as shown in the image below).

The builder allows you to define multiple ranges and for each range, you can specify a color.

 

 

 

 

 

UX Component - RadioButton - CheckBox Controls - Render as ButtonList - Align - When you set either a Radio Button, or CheckBox control to render as a ButtonList, you can not control the alignment (left or right) of the button labels.

Components - Styles - Customize Colors - Pre-defined Palettes - When you select the 'Alpha' style for a component, you can customize the colors used in the style by simply setting the values of SASS variables.

 

 

When you click the smart field for the Customize style colors and fonts property, a dialog is opened, as shown in the image below, where you can set values for each of the SASS variables used in the style.

Now, when you open the Edit Style SASS Variables dialog, a new button appears at the bottom of the dialog that allows you to select a pre-defined palette.

 

 

When you click the Use a Pre-Defined Color Palette button, the Palette Selector window is opened, as shown below.

When you select a palette from the list, the colors are applied to the items in the Edit Style SASS Variables dialog. If you want to use the colors, click OK. If you click Cancel, the colors are not applied.

If you have selected a palette, and you want to go back to the base theme with no palette, select <none> from the list.

 

 

Setting Min and Max Values at Run-time

The following Javascript snippet shows how you can dynamically set the control's min and max value at run-time.

 

var max = {dialog.object}.getValue('max');
max = Number(max)
//get a pointer to the control
var obj = {dialog.object}.getControl('semicircularNumber_1');

 

//set the min and max
obj.rgraphSettings.max = 200;

obj.rgraphSettings.min = 40;

 

//redraw the control
obj.redraw();

 

Application Server - Alerts - The Alpha Anywhere Application Server Classic server now has the ability to send administrative alerts by email and SMS. This can be configured on the Logging tab of the settings UI. There is also a Test Alerts button. This will send both a test email and a test SMS, if each are enabled, in order to confirm that the settings entered are working as expected.

NOTE: These comments do not apply to the Alpha Anywhere Application Server for IIS.

For email notifications, all that is required is a recipient email address. There is no email server configuration necessary, as emails will be sent using a special account, AppServerAlerts@alphasoftware.com. Multiple recipients may be specified by separating them with a comma.

For SMS notifications, the customer must have their own Twilio account and provide the appropriate account information in the server's settings, along with the recipient SMS number. This functionality will work with a free Twilio account, but Twilio may impose limits on free accounts. Multiple recipients may be specified by separating them with a comma.

Currently there are 4 different notification levels, detailed below. Each level includes all alerts from levels under it (higher number).

Level 1 - Emergency

(Indicates something that requires immediate attention, as the server is no longer operating normally)

Level 2 - Alert

(Indicates something that needs attention very soon, as server functionality will be impacted)


Level 3 - Warning

(Indicates a potential problem)

 

Level 4 - Notice

(Indicates an informational notice)

 

 

Xbasic - a5_ink_to_png() Function - Convert Ink to a PNG Image - The Ink control (in the UX component) uses a special syntax for the Ink data. The a5_ink_to_png() function converts the ink data to a PNG image.

Syntax

a5_ink_to_png(C ink,N heightInPoints,N widthInPoints,C filename)

 

Where:

Javascript Library - A5.runChain() Function - Run Asynchronous Functions Synchronously - A new function has been added to the Alpha Anywhere Javascript library to run asynchronous functions synchronously.

Many Javascript functions run asynchronously. For example, functions that make Ajax callbacks are asynchronous. In PhoneGap applications, most of the functions are asynchronous.
 

This helper function allows you to run a series of functions (some of which may be asynchronous) synchronously (i.e. the second function does not start executing until the first function has completed, and so on).

 

Watch Video - Part 1
Watch Video - Part 2

 

Syntax:

A5.runChain(actions,onAllDone,onStop [, context]);

Where:

Each function in the actions array must take a single object as its input parameter. Each function must call the .next() method of the input object to begin execution of the next function in the actions array. If the function is an asynchronous function, the call to the .next() method would be in the onSuccess callback of the asynchronous function.

The execution chain can be stopped if any function calls the input object's .stop() method.

 

Example

//define 3 functions you want to run asynchronously

 

//this is an asynchronous function

function action1(obj) {

    setTimeout(function() {

        console.log('wait 1 second');

        obj.next() // call the next function to be executed

    },1000 );

   

}

 

function action2(obj) {

    console.log('this is a synchronous function');

 

    obj.next()

}

 

function action3(obj) {

    setTimeout(function() {

        console.log('wait .5 seconds');

        obj.next()

    },500 );

   

}

 

//create an array with the functions to executed

var actions = [action1,action2,action3];

 

//run the actions synchronously

A5.runChain(actions,

    function() { alert('alldone'); },

    function(err) { alert('error: ' + err); }

);

 

//if we want to pass in values to the chain we can do as follows

var context = {var1: 'value of var1'};

A5.runChain(actions,

    function() { alert('alldone'); },

    function(err) { alert('error: ' + err); },

    context

);

 

//inside any of the functions we can reference 'this.var1'

//we can also set properties on the 'this' object.

 

 

 

When you run this code, the messages in the console will appear in the following order:

wait 1 second

this is a synchronous function

wait .5 seconds

 

If you had simply called the functions one after the other, then the messages would have appeared in the following order:

this is a synchronous function

wait .5 seconds

wait 1 second

 

Installing the Alpha Anywhere IDE on Multiple Machines - Deactivating a License - The Alpha Anywhere IDE license allows you to install the  Alpha Anywhere IDE on as many machines as you want, but you can only use it on one machine at a time.

If you have installed the AA IDE on two machines, for example, and you started the AA IDE on one machine and then exited the AA IDE on that machine and tried to start it on the second machine immediately after exiting the AA IDE on the first machine, this would not be possible because the activation 'lease' would not yet have expired. By default, the activation 'lease' for the AA IDE is 24 hours. (This can be changed in the View, Settings, Preferences menu command)

However, if you select the File, Deactivate License and Exit menu command, on the first machine, you would be able to go to the second machine and start the AA IDE immediately. You would not have to wait until the lease on that machine expired.

 

UX Component - List Control - Import Data - If a List control in a UX component is based on data from a SQL database you can now upload an Excel or Ascii file (containing CSV data - comma separated values) and then import the data in that file into the table in the SQL database that the List is based on. After the data are imported, the List is automatically refreshed.

NOTE: If a List is based on a stored procedure, you cannot import data.

The data in the uploaded file must use field names that match the column names in the target SQL table.

In the case of a CSV file, the field names are in the first row of data in the file. In the case of an Excel file, the field names are the column heading in the first row of data.

NOTE: In the case of an Excel file, if the file has multiple tabs, the data on the first tab is imported.

Field names in uploaded file cannot contain spaces, or special characters.

To create an Import Action, use Action Javascript and select the Import Data into a List Control from Excel or Ascii file action.

 

This will open the builder where you can define the define the target List control into which you want to import data.

 

 

The properties of note in the builder include:

Target List control name - The name of the List control into which you want to import data. The data are actually imported into the table in the SQL database that the List is based on. Only Lists that are based on SQL databases (and do not use stored procedures for the List query) are eligible targets.

Pre-process uploaded file Xbasic function - After the file has been uploaded you can call an Xbasic function to validate the data before it is imported into the target table. Your Xbasic function gets passed an array with all of the data to be imported. Your code can modify the data in the array or delete array entries that do not meet validation criteria

Maximum records to process - If the uploaded file contains more records that the specified maximum, no data are imported.

 

Xbasic - Context.Security.AdministrativeCreateUser() Method - Adds a new user with a password.

Normally Context.Security.CreateUser() is used to create users. When the security setting for Reset Password is set require a question and answer, a security question and answer are required to create a user.

This requirement is not practical when an administrative task creates a user.

The AdministrativeCreateUser() method can be used in this case. It does not require a security question and answer even if the security settings require one. Because of this, its use should be limited to pages/code that require administrative access and the application should require the user to set a security question and answer on first login.

 

Web Control Panel - Node Services Category - The Web Control Panel now has a new category - Node Services. This makes it easier to create Node services that can be called from your Xbasic code.

When the Node Services item has focus, the New button will create a new stub Node service that serves as a helpful starting point for defining a new service.

Once you have defined your Node service, you can call it from your Xbasic code using the node_request_result() function.

For example, say you have define a service called multiply and that this service takes as input x and y. Here is how you could call the service from Xbasic:

dim pIn as p

pIn.x = 4

pIn.y = 3

dim pOut as p

pOut = node_request_result("multiply",pIn)

?pOut.error

= ""  'empty string indicates no errors.

?pOut.result

= 12

 

 

Web Control Panel - Node Services Category - The Web Control Panel now has a new category - Node Services - that shows all of the Node services defined in the project.

 

Node_request() Function - Automatic Node Restart -  If you are in WorkingPreview or LivePreview and you have edited the code in a Node Services definition, when you call node_request() to run the service, the optional  flagRestartNode parameter will automatically be set to .T.. This makes iteratively testing edits to a Node service easier to test. Without a Node restart, edits to the Node service definition would not be picked up by Node.

Node_request_result() Function - A wrapper around the node_request() function, except that instead of returning a JSON string, the JSON is already parsed and the function returns a .result and .error property. If there was no error, the .error property is blank.

 

Session Folders - The Alpha Anywhere Application Server now uses A5Storage for session files. A5Storage allows for much greater flexibility in storing session data on local disk, network attached storage, Amazon S3, and Azure. This means that the physical folders previously located in a directory named session_folders within the webroot are no longer used in any way and will not be created by the server.

Direct access to these folders has never been supported by Alpha Software, and the Session.Session_Folder and Session.Session_URL properties were deprecated in version 11 and removed in version 12 (Alpha Anywhere). With this update, ServerSetting.SessionFolders has also been removed.

However, some developers may have written custom code to directly access these folders. Any existing code of this type will no longer function as expected and will need to be updated or replaced accordingly.

See https://www.alphasoftware.com/documentation/pages/Server/Guide/Design/Sessions/Storing%20Files%20in%20Sessions.xml for more information on working with files in Sessions.
 

 

Xbasic - create_table_sql() Function - Excel - You can now pass the name of an Excel file to the create_table_sql() function. This will create a SQL table based on the list of columns in the Excel data and also import the data into the SQL table.

The name of the Excel file is passed in as the fieldList parameter.

 

Xbasic - sql_import() Function - Excel - You can now pass the name of an Excel file to the sql_import() function. This will import the data in the Excel file into the SQL table.

The name of the Excel file is passed in as the data parameter.

 

SQL Server Reporting Services - Using Reports Created in SQL Server Reporting Services in an Alpha Anywhere Project - Many organizations use SQL Server Reporting Services (SSRS) and have a number of reports that were developed in SSRS. Using these reports in an Alpha Anywhere application is now possible using the SSRS integration features in Alpha Anywhere.

 

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

 

In order to use SSRS reports in an Alpha Anywhere project you must:

These steps are discussed in more detail below.

Once you have created a link to a SSRS report, the report link can be used just like any other Alpha Anywhere report. You can add the report to the TabbedUI, or you can create actions using Action Javascript to display the report.

Creating a SSRS Connection String

To create SSRS connection string, select the Tools menu when the Web Control Panel has focus and then select the SQL Server Reporting Services Connection strings menu item.

 

 

You can then define a new connection string, or edit an existing connection string:

 

 

Linking SSRS Reports

To link SSRS reports in your Web Project, go to the Web Projects Control Panel and select the Reports category.

 

 

Then click the New button. The dropdown menu shows these choices:

 

This will bring up a dialog where you can select the SSRS reports you want to link in your Alpha Anywhere project.

Select your SSRS connection string in the Connection String dropdown box. A list of reports defined in the selected SSRS server will be displayed.

NOTE: The first time you connect to a SSRS server, it can take quite a long time before SSRS responds with the list of reports.

Select as many of the listed reports as you want.

Notice that at the bottom of the dialog there is a Preview Reports hyperlink that will allow you to preview any report before you select it. If the selected report uses parameters, you will be prompted for the parameter values.

 

 

Links will be created for each of the selected reports. A link is a file in the Web Projects control panel with information about the SSRS report. The filename includes the .ssrs. string in the name just before the .a5rpt extension.

For example:

 

 

Once a report has been linked, you can set security on the report as if it were a native Alpha Anywhere report. You can add the report to a TabbedUI, or show the report when a button is clicked by using Open a Report action in Action Javascript.

 

Publishing Profiles

When you define a publishing profile to publish your application you can specify values for your SSRS connection strings, just as you can for all other types of connection strings (e.g. AlphaDAO, storage, etc.). This means that you can connect to a different SSRS server when you publish your application than you do when you are developing your application.

 

TabbedUI Component - Search - If a TabbedUI component has a large number of items, it can be difficult for a user to find the item that they want. You can now add a search feature to the TabbedUI to allow users to quickly find the items they are looking form. As the user types into the search box a filtered list of the matching items is displayed (see second image).

Watch Video

 

In the image below the search feature has been turned on, but the user has not yet typed into the search box.

 

 

In this image the user has typed a string into the search box and all of the matching items are displayed.

 

To turn the search feature on, go to the TabbedUI Properties pane in the TabbedUI builder and check the Enable search property.

Once you have turned on the search feature, there are a number of other properties you can set.

 

UX Component - Action Javascript - Get Server-side Data - A new action has been added to Action Javascript. The purpose of the action is to get server-side data and return the data to the client where you can then further process the data with Javascript code. For example, you might use the data returned to populate a List control, a dropdown box, a SpinList etc.

 

The builder for the action is shown below:

 

 

The server-side data can be obtained by performing a query against a SQL database, or by executing a Xbasic function (which can, in turn, call web services - REST or SOAP) to get the data that should be returned to the client.

The options for the Query type parameter are:

 

The onSuccess property allows you to define Javascript to execute once the data is received by the client. The data that is received by the client will be stored in a variable called:

{dialog.object}._serverSideData

 

 

 

UX Component - List Control - Dynamic Images - Image Sequences - Client-side - You can now specify dynamic images when you define a dynamic image field to a List and specify that the dynamic image computation is server side.

Xbasic - SQL_Import() Function - Import data into a SQL Table - The sql_import() function is a helper function that imports CSV or JSON data into a SQL table.

NOTE: The function is called a 'helper' function because it simply wraps the low level AlphaDAO methods for doing a bulk insert into a SQL table.

Syntax

p result = sql_import(c connectionString, c tableName, c tableOwner, c data [, L replicateIdentity [, c fieldMap]])

 

 

Where

Example fieldMap

Assume that the input data is as follows

fname,lname

fred,smith

john,jones

 

Assume that the target table has column names of firstName and lastName.

You would need to specify the following fieldMap:

fname=firstName

lname=lastName

 

Example:

dim cs as c
cs = "mydata"
tablename = "table1"
data = <<%str%
id,name,notes,dob,number
1,"Jones, Amy","Here are some notes",1992-12-18,34.56
%str%

'replicateIdentity = .f.
map = "name=fullname"
 

dim p as p
p = sql_import(cs,tablename,"", data,replicateIdentity,map)
 

?p.error

= .f.


 

UX Component - Map Control - Action Javascript - Google Map Methods - Two new actions have been added to the Google Map Methods action

 

Xbasic - what3words() Function - Add support for the what3words service. Allows you to translate an address or location to a what3words address, or a what3words address to a location. For more information on what3words go to www.what3words.com.

Syntax

p result = what3words(c key, c mode, c input)

Where

Examples

 

key = "Your api key"

mode = "wordstolocation"

input = "traps.plan.code"

dim p as p

p = what3words(key,mode,input)

?p.lat
= 42.423661
?p.lng
= -71.213213

 

mode = "addresstowords"
input = "70 blanchard road, burlington ma usa"

dim p as p
p = what3words(key,mode,input)
?p.words
= "newly.slams.roses"
 

 

 

Xbasic - create_table_sql() Function - Create a table in a SQL database.

 

Syntax

P result = create_table_sql(c fieldList,c connectionString,c tableName [, c mode])

 

Where

 

The fieldList parameter can be either a JSON array of objects defining each field, or a crlf delimited list of pipe delimited properties.

Example of a CRLF delimited fieldList:

 

id|N|6|0|AutoIncrement

name|c|20

dob|d

notes|m

 

In this example a primary key (that is not an AutoIncrement fields) is defined

id|c|6||PrimaryKey

name|c|20

dob|d

notes|m

 

When defining a primary key you can designate multiple columns:

firstname|c|20||PrimaryKey

lastname|c|20||PrimaryKey

dob|d

notes|m

 

 

 

Example of a JSON fieldList:

 

[

    {"name": "id", "type": "numeric", "size": 6, "decimals" : 0, "autoIncrement": true},

    {"name": "name", "type": "character", "size": 20},

    {"name": "dob", "type": "date"},

    {"name": "notes", "type": "memo"}

]

 

In this next example a primary key (that is not an Auto Increment field) is defined:

NOTE: Multiple fields can have the 'primaryKey' attribute set to true.

 

[

    {"name": "id", "type": "character", "size": 6,  "primaryKey": true},

    {"name": "name", "type": "character", "size": 20},

    {"name": "dob", "type": "date"},

    {"name": "notes", "type": "memo"}

]

 

Xbasic - JSON_shred() Function - Converts a complex JSON string representing an array of objects with nested arrays) into individual arrays that do not have any nested arrays.

Syntax:

c result = JSON_shred( c JSON, c schema [, c ParentArrayName])

where

 

Consider the following JSON string:

[
	{"Firstname": "John", "Lastname" : "Smith", "City" : "Boston", "State" : "MA", "Children": [
		{"Name" : "Callie", "Age" : 5},
		{"Name" : "Griffin", "Age" :3},
		{"Name" : "Luke", "Age" : 1}
		]
	}, 
	{"Firstname": "Henry", "Lastname" : "Rhodes", "City" : "New York", "State" : "NY", "Children": [
		{"Name" : "Howard", "Age" : 15},
		{"Name" : "Robert", "Age" : 11}
		]
	}
]
			
			

The JSON is an array in which each object in the array has a nested array of 'children'.

This JSON can be 'shredded' to produce this result:

			
{
    "__top": [
        {
            "Firstname": "John",
            "Lastname": "Smith",
            "City": "Boston",
            "State": "MA"
        },
        {
            "Firstname": "Henry",
            "Lastname": "Rhodes",
            "City": "New York",
            "State": "NY"
        }
    ],
    "Children": [
        {
            "Name": "Callie",
            "Age": 5
        },
        {
            "Name": "Griffin",
            "Age": 3
        },
        {
            "Name": "Luke",
            "Age": 1
        },
        {
            "Name": "Howard",
            "Age": 15
        },
        {
            "Name": "Robert",
            "Age": 11
        }
    ]
}

 

The result is an object with two arrays: __top and Children. Notice however, that since the 'Children' array is no longer nested inside each object in the top level array, the linkage between the entries in the 'Children' array and their parent has been lost.

In the above example, the JSON_shred() function was called using a schema that did not specify that any key fields should be added to the Children array.

The schema used to produce the above result was:

	
[
    {
        "Children" : [
            {
            }
        ]
    }
]

Notice how the  schema defines the 'shape' of the input JSON but does not specify that any additional 'key' fields should be added to the Children array.

In order not to loose the relationship between each object in the Children array to its parent, a key field must be added to each object in the Children array that points to its parent record. The desired output from the shredding operation is shown below:

	
{
    "__top": [
        {
            "Firstname": "John",
            "Lastname": "Smith",
            "City": "Boston",
            "State": "MA"
        },
        {
            "Firstname": "Henry",
            "Lastname": "Rhodes",
            "City": "New York",
            "State": "NY"
        }
    ],
    "Children": [
        {
            "key": "John Smith",
            "Name": "Callie",
            "Age": 5
        },
        {
            "key": "John Smith",
            "Name": "Griffin",
            "Age": 3
        },
        {
            "key": "John Smith",
            "Name": "Luke",
            "Age": 1
        },
        {
            "key": "Henry Rhodes",
            "Name": "Howard",
            "Age": 15
        },
        {
            "key": "Henry Rhodes",
            "Name": "Robert",
            "Age": 11
        }
    ]
}

 

Notice that each record in the 'Children' array now has a property called 'key' that points to its parent record. To obtain the above result, the following schema is used:

	
[
    {
        "Children" : [
            {
            	"key": "{../Firstname} {../LastName}"
            }
        ]
    }
]

 

The schema specifies that each object in the 'Children' array should have a property called 'key' whose value is the "Firstname' and "Lastname" property in the immediate parent object. The syntax used to specify a value from a parent object is ../.  You can reference properties at the grand parent level using ../../, and so on.

 

Here is a more complex example that shows multiple levels of nested arrays in the input JSON. Notice that the "Hobbies" array is an array of strings, not an array of objects. This array is converted into an array of objects in the result.

	
[
	{"Firstname": "John", "Lastname" : "Smith", "City" : "Boston", "State" : "MA", "Children": [
		{"Name" : "Callie", "Age" : 5},
		{"Name" : "Griffin", "Age" :3, "Hobbies" : ["Leggo","Star Wars"]},
		{"Name" : "Luke", "Age" : 1}
		]
	}, 
	{"Firstname": "Henry", "Lastname" : "Rhodes", "City" : "New York", "State" : "NY", "Children": [
		{"Name" : "Howard", "Age" : 15},
		{"Name" : "Robert", "Age" : 11, "Hobbies" : ["Soccer"]}
		]
	}
]		

Here is the schema that could be used to shred the above JSON:

	
[
    {
        "Children" : [
            {
            	"Hobbies" : [ 
            		{ 
            			"hobbyKey" : "{../../Firstname} {../../Lastname}|{../Name}" 
            		}
            	],
            	"key": "{../Firstname} {../LastName}"
            }
        ]
    }
]

And here is the resulting output from the shredding operation:

	
{
    "__top": [
        {
            "Firstname": "John",
            "Lastname": "Smith",
            "City": "Boston",
            "State": "MA"
        },
        {
            "Firstname": "Henry",
            "Lastname": "Rhodes",
            "City": "New York",
            "State": "NY"
        }
    ],
    "Children": [
        {
            "key": "John Smith",
            "Name": "Callie",
            "Age": 5
        },
        {
            "key": "John Smith",
            "Name": "Griffin",
            "Age": 3
        },
        {
            "key": "John Smith",
            "Name": "Luke",
            "Age": 1
        },
        {
            "key": "Henry Rhodes",
            "Name": "Howard",
            "Age": 15
        },
        {
            "key": "Henry Rhodes",
            "Name": "Robert",
            "Age": 11
        }
    ],
    "Hobbies": [
        {
            "hobbyKey": "John Smith|Griffin",
            "__value": "Leggo"
        },
        {
            "hobbyKey": "John Smith|Griffin",
            "__value": "Star Wars"
        },
        {
            "hobbyKey": "Henry Rhodes|Robert",
            "__value": "Soccer"
        }
    ]
}

 

 

PhoneGap App Builder - PhoneGap CLI Build Option - A new option has been added to the PhoneGap App Builder that allows the developer to select and use either PhoneGap Build or a local install of the Cordova CLI (Command Line Interface) to build a PhoneGap App.

Android builds are supported on PC's running Windows and iOS builds are supported on a Mac with Xcode. Using the CLI allows the developer to use the platform's native development tools to build and debug Cordova apps. This also allows the use of plugins that PhoneGap Build does not support because PhoneGap Build does not support the use of plugin hooks.



For the full documentation on the PhoneGap/Cordova CLI Builder, see PhoneGap/Cordova CLI Builder

For a video overview on using the PhoneGap/Cordova CLI Builder, see PhoneGap/Cordova CLI Builder Video Overview

Xbasic - CURL Object - Auto-complete - When you define a CURL object in Xbasic, you now have auto-complete for all of the options available to the .SetOpt() method.

For example:

 

dim c as extension::curl

c.setOpt(

 

As soon as you type the opening (, the bubble help instructs you to right click on the argument value (as shown in the image below) to get a list of the options for the .setOpt() method.

 

 

 

UX Component - FormView Control - Lookup Fields - You can now define lookup fields in the FormView. This allows you to display 'friendly' values in the Form (e.g. product name, rather than product id).

To define a Lookup field, go to the Fields tab in the FormView builder and check the Has Lookup value property.

You can then define the Lookup. The lookup data source can be a List control or a Javascript function.

 

 

 

TIP: You may want to use the client-side data cache or a query against a SQLite database (in a PhoneGap application) as the data source for your Lookup. This requires a two-step process because reading data from the client-side data cache, or from a SQLite database can only be done asynchronously. Therefore you must first execute some code that reads the client-side data cache or executes a SQLite query and puts the data in a variable in memory. You can then define the Lookup in the FormView builder to use the Javascript Function option, performing the lookup against the data you have loaded into memory.

 

Web Project Control Panel - Automatic Refresh - By default every time the list of files in your Web Project changes, or a file is edited, the Web Project Control Panel will refresh. However, if your project contains a very large number of files  (several thousand), then refreshing the Control Panel can be slow and you might want to turn off the automatic refresh of the Control Panel and only refresh it when needed.

You can turn off automatic refresh by clicking on the More... button in the Web Control Panel and selecting the Set Control Panel refresh options... menu entry.

 

 

 

If you turn off automatic refresh, a Refresh button will be shown in the Web Control Panel. Click this button to refresh the Control Panel.

 

 

UX Component - List Controls - Dynamic Images - Image Sequence - When you add a server-side dynamic image to a List control, you can now specify that you want to use an image sequence for the image.

 

 

 

UX Component - Map Control - Adding Multiple Markers to a Map Control Using Client-side Data - Action Javascript has an action to add multiple markers to a map. The data that defines the latitude/longitude for each marker on the map (and also for the marker titles, details etc). has previously been server-side data. Now, you can specify that the data should be client-side data.

In the case of server-side data you specify the name of a Data Series that specifies the properties for each marker. In the case of client-side data, the data can come from a Javascript function, a List control, the client-side Data Cache, or, in the case of a PhoneGap application, by querying a SQLite database on a device.

 

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

Download Component

 

To specify that the Google Map Method (UX Component) / Add multiple markers to the map action should use client-side data, set the Data type property to ClientSideData. You can then specify whether the client-side data comes from a Javascript function, or from data in a List control.

In the case where you specify the name of a Javascript function, you specify the name of a Javascript function (which must return an array of objects - each object has properties that must include the marker latitude and longitude values). You must also specify the names of the properties in the data returned by the Javascript function.

 

 

 

 

For example, assume that you specify the name of a Javascript function that returns data like this:

			
[
		{
			"name": "COYOTE FLATS",
			"city": "BISHOP",
			"state": "CA",
			"latitude": "37.20203",
			"longitude": "-118.47629"
		},
		{
			"name": "LOST HILLS SHERIFF\\'S STATION",
			"city": "CALABASAS",
			"state": "CA",
			"latitude": "34.14167",
			"longitude": "-118.5262"
		},
		{
			"name": "GOLDSTONE /GTS/",
			"city": "BARSTOW",
			"state": "CA",
			"latitude": "35.35053",
			"longitude": "-116.88837"
		}
]
			
			

In this case the property names that you specify in the Javascript properties property would be:

name,city,state,latitude,longitude

 

NOTE: If you want to use data from the client-side Data Cache, or (in the case of a PhoneGap application) data from a query against a SQLite database, you need to use a two-step process because reading data from a Data Cache (or a SQLite database) is an asynchronous action. Therefore your Javascript must read the Data Cache, or execute the SQLite query (you can use Action Javascript for this) and in the on success function for the action, you must put the data you have just read into a variable in the UX object (for example {dialog.object}._mapData) and then call the Action Javascript action to add the markers to a map using the Javascript function option. The Javascript function will read the data from the variable that contains the data.

 

Xbasic - Classes - The Web Control Panel now exposes a new category - Xbasic Class - that allows you to defined Xbasic classes that can then be used in any server-side Xbasic code.

 

To use an Xbasic class in your Xbasic code you use the loadClass() function to load the definition and then you can DIM and instance of the class.

For example:

dim flag as l
flag = loadClass("helloclass")
dim h as helloclass

 

 

NOTE: It is not strictly necessary to use the loadClass() function to load the class before DIMming and instance of the class. If the DIM statement fails, Xbasic will then try to load the class itself by searching for the class definition. But this will add a short delay to your code while Xbasic tries to resolve the class. Therefore it is recommended that you explicitly load the class before using it. Also, if you make an edit to the class definition, the edit will be seen immediately if you explicitly load the class.

 

 

Xbasic - loadClass() Function - Loads a class definition.

Syntax

L flag = loadClass(c className)

Where

 

 

 

UX Component - Integrated Login - Server-side onLogin Event - Enhancements have been made to the server-side onLogin event so the following actions in the onLogin event handler are now supported

 

For example:

 

e.arguments[e.arguments.ArgumentNumber("Arg1")].data = "Portugal"

e._set.field1.value = "foo"

e.control.field2 = "bar"
 

Web Components - Manifest Files - Using Source Control - Most web components use a special support file with a _a5wcmp_manifest file extension. When a component is published, the process checks for a manifest file built at the same time as the requested component. The publish process uses this manifest file to determine what other files need to be published to run the component.

Previously, the file name for each 'manifest' file contained a timestamp string to synchronize the file with its parent component. This caused a problem if the component files were stored in a source control system. (See release notes for 'Grid Component - Compiled Files - Using Source Control' for a complete explanation).

The new process stores the linking timestamp internally in the two files, and the manifest filename never changes. It can now be stored in a source control system with its parent component.


This new naming convention is only applied when a component is edited and resaved, or when the manifest files are updated by a bulk process. Existing components with the legacy file naming will still function normally. Some components such as login and navigation components do not use the new process as they do not build a manifest when saved.

 

UX Component - Alignment Container - The Alignment container makes it easy to left, center, or right align a series of controls.

When you select an Alignment container you can set standard set of properties for  container. If you set the alignment to left or right, then you can also set an offset property to control distance of the controls from the left or right edge.

All of the controls in an Alignment Container render on their own line, regardless of whether or not a break follows the control.

If you want multiple controls to be on the same line, you must wrap the controls in a container and then the Alignment container will align the enclosing container.

 

 

 

The image below shows how the above definition renders (but with the alignment set to Center, not Left as shown in the image).

The width of the Alignment container has been set to 100% and the width of the first three textbox controls have been set to 50%, 75% and 33% respectively. As you can see the controls are all horizontally centered  within the container.

The txt4 and txt5 controls both appear on the same line because they are wrapped in  standard container whose width has been set to 2.5inches. The container itself, which has a red border, is horizontally centered.

 

 

 

UX Component - PhoneGap - New Sample Template - PhoneGap - Sound Effects using Native Sounds - A new sample template component has been added that shows how you can add sound effects to your application using the PhoneGap Low Latency Audio plugin. When you create a new UX component you will see the template listed in the list of available samples.

UX Component - FormView Control - List DataSource - {dialog.object}.formViewCommit() Method - Commit Dirty Fields Only - You can now specify that only fields that were edited should be committed to Form's data source. Only applies if the Form's data source is a List control.

Syntax

var flagOnlyCommitDirtyFields = true;

{dialog.object}.formViewCommit('{form.id}',flagOnlyCommitDirtyFields);

 

Xbasic - csv_to_json() - Convert a CSV string to JSON.  Fields must be comma delimited. First row must be fields names. If a field contains a comma, enclose field in quotes. If a field contains quotes, escape quotes using two consecutive quotes


Example

 

dim txt as c
txt = <<%txt%
ticker,name,price:N,change:N,mktcap,chgPct
"AAPL","Apple Inc.",402.215,"-24.025",377.7B,"-24.025 - -5.64%"
"GOOG","Google Inc.",780.37,"-13.00",257.3B,"-13.00 - -1.64%"
%txt%
 

? csv_to_json(txt)
= [
{ "ticker" : "AAPL" , "name" : "Apple Inc." , "price:N" : "402.215" , "change:N" : "-24.025" , "mktcap" : "377.7B" , "chgPct" : "-24.025 - -5.64%"} ,
{ "ticker" : "GOOG" , "name" : "Google Inc." , "price:N" : "780.37" , "change:N" : "-13.00" , "mktcap" : "257.3B" , "chgPct" : "-13.00 - -1.64%"}
]

 

 

 

 

UX Component - onLogin and onLogout Server-side Event - Setting state variables. You can now use the

e._state.varname = varvalue

syntax to set the value of state variables in the server-side onLogin and onLogout event. Keep in mind that if the UX is set to do a full refresh on logout, setting state variables in the onLogut event is meaningless.

 

 

 

 

Action JavaScript - Stripe Checkout - A5.stripe.getEmbeddedStripeResults Function A new function has been added to Stripe Checkout to handle a unique situation that occurs when the Stripe Checkout control is used within an embedded UX component that is reloaded after its was initially loaded The new function may be called in the onStripeCheckoutComplete event.

Example: onStripeCheckoutComplete event handler

 


var e = {};
if ({dialog.object}.getStripeResults) {
    e = {dialog.object}.getStripeResults();
} else {
    e = A5.stripe.getEmbeddedStripeResults();
}


 

Bugs

UX and Grid Component - onChange Event - Fixed a bug introduced in V4.3.2.

PhoneGap App Builder - ImageMagick - UNC Paths - A problem with UNC paths when using ImageMagick to generate icons has been resolved.

UX Component - Stripe - Fixed an issue when setting the currency type to a non US dollar value.

UX Component - Dynamic Images - Fixed a bug introduced in build 4152 when support for image sequences was introduced.

Xbasic - .Net Integration - Fixed an issue when using Xbasic to work with a .Net assembly

Tips

SQL Server Performance Optimization - Indexes - Performance of queries against SQL Server can be affected by string arguments due to an issue with the SQL Server optimizer. 
 
It appears that when a query has a string value argument, the SQL Server optimizer does not always see the type as matching some types of columns (for example CHAR columns with a fixed size). As a result, the optimizer will ignore indexes and hints to use them and resort to a table scan.
 
For example:

 
SELECT AmountDue, AmountPaid, AccountNumber FROM Invoices WHERE AmountDue > 0 and CustomerId = :CustomerId
 


If CustomerId is defined in the database as Char(5), the optimizer may not recognize the :CustomerId argument contains a matching value because the type of the argument is VARCHAR.
 
In such cases, adding a CAST to the argument value causes the optimizer to choose the appropriate index because the types match:


 
SELECT AmountDue, AmountPaid, AccountNumber FROM Invoices WHERE AmountDue > 0 and CustomerId = CAST(:CustomerId AS CHAR(5))
 
 

 

 

 

Alpha Anywhere V4.3.2 - Build 4119-4825 30-Jan-2017

Features

 

Xbasic - SQL_Update() Function - Updates a record in a SQL table. This function is just a wrapper around the Xbasic AlphaDAO commands to execute a SQL update statement, but it convenient to use for simple cases.

NOTE: The record to update is specified by primary key, not by a generalized WHERE clause. This limitation is intentional so a to eliminate the possibility of unintentionally updating multiple records in the database. If you need to update multiple records you will need to write your own Xbasic code.

 

Syntax

    p result = sql_update(A connection,c tablename,c fieldValuePairs,c primaryKey, a primaryKeyValue [, L execute [, P e ]])

 

Where

 

Example:

 


dim cn as sql::Connection

cn.open("::Name::myconnstring")
tablename = "mytable"
fieldsValuePairs = <<%str%
name=fred smith

date of birth=1952/12/18

salary=78000
%str%
 

'You can also specify field values using JSON
fieldsValuePairs = <<%str%
{
    "name" : "fred smith",
    "date of birth" : "1954/11/25",

    "salary" : "78000"
}
%str%

primaryKey = "id"
primarykeyValue = "1"

p = sql_update(cn,tablename,fieldsValuePairs,primaryKey,primaryKeyvalue)
 

 

 

Xbasic - SQL_Insert() Function - Inserts a record in a SQL table. This function is just a wrapper around the Xbasic AlphaDAO commands to execute a SQL insert statement, but it convenient to use for simple cases.

 

Syntax

    p result = sql_insert(A connection,c tablename,c fieldValuePairs [, L execute[, P e ]]])

 

Where

 

 

Example:

 


dim cn as sql::Connection

cn.open("::Name::myconnstring")
tablename = "mytable"
fieldsValuePairs = <<%str%
name=fred smith

date of birth=1952/12/18

salary=78000
%str%
 

'You can also specify field values using JSON
fieldsValuePairs = <<%str%
{
    "name" : "fred smith",
    "date of birth" : "1954/11/25",

    "salary" : "78000"
}
%str%


p = sql_insert(cn,tablename,fieldsValuePairs)

 

?p.lastInsertedIdentity

= 5
 

 

Application Server - OpenSSL - A new version of OpenSSL is now used. The build is OpenSSL 1.0.2k. For details of the fixes in OpenSSL, see:

                https://www.openssl.org/news/cl102.txt

 

UX Component - {dialog.object}.debugInfoToFile() Method - This method is useful when debugging an application and you want to examine some client-side data. While you can typically use Alerts in client side code to examine data, or in some case use console.log() commands (not always possible when the app is running on a mobile device), this method allows you to write client side data to a file on the server.

In cases where you do not have permission to write to server files (e.g. when running under IIS or on the Alpha Cloud), the companion {dialog.object}.debugInfoToS3() method can be used to write to a file on an S3 bucket.

Syntax

{dialog.object}.debugInfoToFile(data,filename[, append [,silent]])

 

Where

UX Component - {dialog.object}.debugInfoToS3() Method - This method is useful when debugging an application. It allows you to write data to a S3 bucket. See {dialog.object}.debugInfoToFile() Method for more information.

Syntax:

{dialog.object}.debugInfoToS3(data,connectionString,objectName [,append [,silent]])

 

Where

UX and Grid Component - DevArts Zoho CRM ODBC Driver - The DevArts ODBC driver for Zoho CRM is now supported.

Xbasic - json_from_xml() Function - Ignore Attributes - In some cases, when you convert XML to JSON, the XML either does not contain attribute tags, or you want to ignore attribute tags when converting the XML to JSON. This will result in cleaner looking JSON. The json_from_xml() function now takes an optional '-A' attribute to ignore attributes.

For example, consider the following input XML:

 

dim xml as c = <<%str%
<qdbapi>
   <ticket>auth_ticket</ticket>
   <apptoken>app_token</apptoken>
   <query>{'11'.CT.'Bob'}AND{'19'.GTE.'5'}</query>
   <clist>6.7.9.11.16</clist>
   <slist>11.6</slist>
   <fmt>structured</fmt>
   <options>num-4.sortorder-D</options>
</qdbapi>
%str%


showvar(json_reformat(json_from_xml(xml,"qdbapi","-A")))

			

The following JSON in produced:

{
     "qdbapi": {
        "ticket": "auth_ticket",
        "apptoken": "app_token",
        "query": "{'11'.CT.'Bob'}AND{'19'.GTE.'5'}",
        "clist": "6.7.9.11.16",
        "slist": "11.6",
        "fmt": "structured",
        "options": "num-4.sortorder-D"
    }
}
			
			


Grid Component - Compiled Files - Using Source Contro
l - Grid components use a special support file with a _a5wcmp_compiled file extension.


When a Grid component is published, the process checks for a compiled file built at the same time as the requested Grid.
The publish process uses this compiled file to construct the published version of the Grid Component used at run time. If the compiled file is missing or out of date, it is reconstructed, which slows the publish process. In a large project this could add a significant amount of time to the publish operation.

Previously, the file name for each 'compiled' file contained a timestamp string to synchronize the file with its parent Grid. This filename changed every time the Grid was resaved. This caused a problem if the Grid component files were stored in a source control system, as explained below.

At publish time, the timestamp in the filename of the _a5wcmp_compiled file was compared with the last edited time of the Grid component file to determine if the _a5wcmp_compiled was up to date. However, if the Grid files in the project had been restored from a source control system, the last edited time on the Grid component filename would be different from their original value and would no longer match the timestamp stored in the local project _a5wcmp_compiled filename. Because the file name for each 'compiled' file changed at every save, it could not be stored in a source control system. As a result, when publishing the application, it would appear that the _a5wcmp_compiled files were out of date and the _a5wcmp_compiled would have to be re-created, thus slowing down the publishing operation.

Now, the _a5wcmp_compiled filename no longer contains a timestamp. Instead, the timestamp is stored as a property in the Grid and it's _a5wcmp_compiled file. The _a5wcmp_compiled filename never changes when the Grid component is edited and the Grid and its linked compiled file can both be stored in a source control system. If both are updated at the same time, they will still match when retrieved from the source control. You do not need to store the _a5wcmp_compiled files in source control if the Grid will not be edited in source control.

This new naming convention is only applied when a grid is edited and resaved, or when the compiled files are updated by a bulk process. Existing grids with the legacy file naming will still function normally.

 

UX Component - Static HTML Page Head Section - When you turn on the Application Cache for a UX component you can now inject custom markup into the head section of the static HTML page using the new Page head section property.

The common use case for customizing the head section is to include markup that specifies the icons to use should the user choose to make a home screen shortcut for the page.

 

 

When you click the smart field to edit the HEAD section, the editor has a hyperlink that will insert sample markup showing how the home screen icons are defined.

In the example below it is assumed that your project has icons called 'apple-icon-57x57.png', etc.

UX Component - List Control - Detail View - afterSynchronize and afterSynchronizeRecord Server-Side Events - Two new server-side events have been added to the List control.

NOTE: Both of these events must be defined for the top-most parent List in the List hierarchy. For example if your UX has a List showing Customers and a child List showing Orders (and if the child List is set to pre-fetch data), then these events must be defined for the Customer List. Defining these events for the Orders List is meaningless.

 

Xbasic - CURL to Xbasic Genie - The CURL to Xbasic genie has been substantially enhanced. You can now automatically generate sample CURL commands by clicking the Example commands... hyperlink in the genie.

 

When you click on the hyperlink a menu of available example commands is shown. You can use this genie to get a template for how the CURL command should be constructed. Then when you convert the generated CURL command to Xbasic, you will have an excellent starting point for fashioning your Xbasic CURL code to perform the task you want.

The list of examples in the menu is extensive, but if you need a specialized CURL command (for example, you need custom headers), select the More... option.

This will open up a generic CURL command builder, as shown in the image below.


Bugs

UX Component - Google Address Suggest - If you had a Google Address Suggest control on a UX and that control was opened in a TabUI, if the tab containing the UX was closed and then the tab was opened a second time, the Address Suggest control did not work.

REGEX Validation - A recent change in the Regex validator in Grid and UX control validation rules (to support international characters in Regex expressions) broke some regex validations that were previously working

UX Component - PhoneGap - Fixed an issue introduced in build 4015 when creating a PhoneGap appllcation.

SQL Trace - Working Preview - If you checked the SQL Trace checkbox in the AlphaDAO Connection String Builder dialog and then executed SQL in Working Preview, the SQL was not shown in the Trace Window.

Video Library - Refresh - The Refresh command on the Video Library did not always update the list of videos shown in the Video Library.

UX and Grid Component Components - onChange Events - Fixed a bug introduced in build 4095 for Grid and UX controls with onChange event handlers, if the Javascript code had any single quote characters.

Report Preview - E-mail Report - PDF - If you clicked the 'Email Report' button on the Report Preview window to send a report as a PDF, an error was generated.

 

Alpha Anywhere V4.3.2 - Build 4107-4820 24-Jan-2017

Bugs

UX Component - PhoneGap - Fixed an issue introduced in build 4015 when creating a PhoneGap appllcation.

 

 

Alpha Anywhere V4.3.2 - Build 4105-4819 23-Jan-2017

UX Component - Static HTML Page Head Section - When you turn on the Application Cache for a UX component you can now inject custom markup into the head section of the static HTML page using the new Page head section property.

The common use case for customizing the head section is to include markup that specifies the icons to use should the user choose to make a home screen shortcut for the page.

 

 

When you click the smart field to edit the HEAD section, the editor has a hyperlink that will insert sample markup showing how the home screen icons are defined.

In the example below it is assumed that your project has icons called 'apple-icon-57x57.png', etc.

UX Component - List Control - Detail View - afterSynchronize and afterSynchronizeRecord Server-Side Events - Two new server-side events have been added to the List control.

NOTE: Both of these events must be defined for the top-most parent List in the List hierarchy. For example if your UX has a List showing Customers and a child List showing Orders (and if the child List is set to pre-fetch data), then these events must be defined for the Customer List. Defining these events for the Orders List is meaningless.

 

 

Xbasic - CURL to Xbasic Genie - The CURL to Xbasic genie has been substantially enhanced. You can now automatically generate sample CURL commands by clicking the Example commands... hyperlink in the genie.

 

When you click on the hyperlink a menu of available example commands is shown. You can use this genie to get a template for how the CURL command should be constructed. Then when you convert the generated CURL command to Xbasic, you will have an excellent starting point for fashioning your Xbasic CURL code to perform the task you want.

The list of examples in the menu is extensive, but if you need a specialized CURL command (for example, you need custom headers), select the More... option.

This will open up a generic CURL command builder, as shown in the image below.


Bugs

 

SQL Trace - Working Preview - If you checked the SQL Trace checkbox in the AlphaDAO Connection String Builder dialog and then executed SQL in Working Preview, the SQL was not shown in the Trace Window.

Video Library - Refresh - The Refresh command on the Video Library did not always update the list of videos shown in the Video Library.

UX and Grid Component Components - onChange Events - Fixed a bug introduced in build 4095 for Grid and UX controls with onChange event handlers, if the Javascript code had any single quote characters.

Report Preview - E-mail Report - PDF - If you clicked the 'Email Report' button on the Report Preview window to send a report as a PDF, an error was generated.

 

 

Alpha Anywhere V4.3.2 - Build 4099-4819 20-Jan-2017

Bugs

UX and Grid Component Components - onChange Events - Fixed a bug introduced in build 4095 for Grid and UX controls with onChange event handlers, if the Javascript code had any single quote characters.

Report Preview - E-mail Report - PDF - If you clicked the 'Email Report' button on the Report Preview window to send a report as a PDF, an error was generated.

 

Alpha Anywhere V4.3.2 - Build 4095-4816 18-Jan-2017

Bugs

Grid Component - Query By Example - If you added two or more filter conditions, ran the query, then removed one of the two filter conditions and then added a third condition, you would get an error.

UX Component - onChange Event - Pre-render - If a UX component had an event handler for the onChange event for a control then if the component was set to pre-render and if the component was shown though an Ajax callback and if the event handler used single quotes in the Javascript, you would get an error.

 

Alpha Anywhere V4.3.2 - Build 4089-4815 15-Jan-2017

Bugs

UX Component - List Control - Detail View - Multi-Column Primary Key - Fixed an issue when adding a new record to a List that was based on a SQL table with a multi-column primary key. This issue was introduced in Version 4.3.2

UX Component - DropDownBox, RadioButton and CheckBox Controls - Choices - Connection String - The connection string builder did not open because of a recent bug that had been introduced.

Reports - Conditional Objects - Fixes to the Conditional Object in reports that resulted from a recent change to this control.

Alpha Anywhere V4.3.2 - Build 4081-4811 11-Jan-2017

Features

Xbasic - AlphaDAO - Date and Number Formats - The SQL::Connection object now supports three new properties that allow you to control the format for date and number fields when the .toJSON() or .toJSONObjectSyntax() methods are called.

 

 

By default, if these properties are not set, the the date format and the decimal separator are inherited from the machine's regional settings

 

 Note:  The properties must be set on the connection BEFORE the result set is created.

 

 

Example Usage


 
dim cn as sql::connection

?cn.open("::Name::Access_Northwind")
= .T.
cn.PortableSQLEnabled = .t.
cn.JSONDateFormat                                       = "yyyy-MM-dd"

cn.JSONDateTimeFormat                             = "yyyy-MM-dd hh:mm::ss 3"

cn.JSONDecimalSeparator                           = ","

?cn.tojson("select first 5 orderdate, freight from orders")

= [
{"orderdate" : "1996-07-04 00:00::00 000", "freight" : "32,38"},

{"orderdate" : "1996-07-05 00:00::00 000", "freight" : "11,61"},

{"orderdate" : "1996-07-08 00:00::00 000", "freight" : "65,83"},

{"orderdate" : "1996-07-08 00:00::00 000", "freight" : "41,34"},

{"orderdate" : "1996-07-10 00:00::00 000", "freight" : "58,17"}

]

 


 

Bugs

Reports - Conditional Objects - A bug was introduced recently that broke reports with conditional objects.

UX Component - List Control - Dates - A bug was introduced in the last update where, if the client-side data format did not match the server-side data format, dates with days less than 13 (e.g. 13 Oct 2017) were not being persisted to the database correctly

Alpha Anywhere V4.3.2  - Build 4077-4809  09-Jan-2017

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 Displaying a Custom Wait Message while a Large Mobile App is Loading in the Background If you have built a very large mobile App which takes some time to load, you might want to display a custom wait message to the user while the main UX component of your App is loaded in the background.

In this video we show how this can be done using a simple 'startup' UX component.

Watch Video

Download Components

Date added: 2016-12-11
UX Component - PhoneGap PhoneGap - Using the PhoneGap - Open File with Native Application Action to View PDF Files in a Mobile Application The PhoneGap cordova-open plugin allows you to open various file types using the associated native app on a mobile device. For example, if you open a .pdf file, the PDF file is displayed using the native PDF viewer app on the mobile device. If you open a .mp4 file, the video is displayed using the native video viewer on the device. A common use case for this plugin is to download several files when a connection is available so that the files can then be viewer later on when no connection is available.

In this video we show how an application is built that shows a list of PDF files. These files are downloaded from the server and stored in the filesystem on a mobile device. Then we show how each of the downloaded files can be viewed using the PDF viewer on the mobile device. Because the PDF files are stored in the filesystem on the device, they can be viewed even if the device no longer has a connection. The application uses the 'PhoneGap - Open File with Native Application' action to display the .pdf file.

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

Date added: 2016-12-27
UX Component - PhoneGap PhoneGap- Viewing Reports in PDF Format on a Mobile Device The PhoneGap cordova-open plugin allows you to open files (such as .pdf files) using the natvie application associated with that file type on a mobile device. This plugin is particularly useful for viewing PDF files. The Alpha Anywhere report writer can save reports as PDF files. The cordova-open plugin therefore fits really well with the Alpha Anywhere report writer because you can build applications that generate reports as PDF files and then display the reports on a mobile device using the cordova-open plugin.

In this video we show how you can use Action Javascript (the  'PhoneGap - Open File with Native Application' action) to generate a PDF file from an Alpha Anywhere report, then download the resulting PDF file to a mobile device and display it using the native PDF viewer.


Watch Video - Part 1
Watch Video - Part 2

Date added: 2016-12-27

Features

 

 

Xbasic - Javascript Web Tokens (JWT) - Additional Options - Additional options have been added to the Xbasic classes for generating Javascript Web Tokens. For more details refer to the documentation.

 

IIS Application Server - PKI Authentication - Support has been added for PKI authentication. For more details refer to the documentation.

Watch Video - Part 1
Watch Video - Part 2
 

Xbasic - Extension::JSON Class - New methods - New methods have been added to the extension::JSON class to make it easier to extract data from a JSON object.

NOTE: You can generally easily extract data from a JSON string by parsing the JSON to an Xbasic dot variable, using the json_parse() method. But if the JSON has property names that are not valid Xbasic variable names, then you cannot parse the JSON. Also, parsing an extremely large JSON string could be slow. The methods described here do not require the JSON to be parsed into an Xbasic dot variable, and work for all types of JSON property names.

 

Methods 1

extension::JSON::OffsetToPath(json,offset[,base])

where:

 

 Returns a 'path' to the JSON element that contains the text at the specified offset.

 

Example:

Assume that json is a variable that contains the sample JSON shown below

?extension::JSON::OffsetToPath(json,540,1)
= "[1].orders[1].orderItems[1]"
 

This means that the path in the JSON to the element that contains the text at position 540 is:

[1].orders[1].orderItems[1]

 

Method 2

extension::JSON::PathToOffset(json,path[,base])

where:

 

Returns the offset in the JSON string for the element specified by the path.

 

Example:

Assume that json is a variable that contains the sample JSON shown below


?extension::JSON::PathToOffset(json,"[1].orders[1].orderItems[1]",1)
= 355

 

Method 3

extension::JSON::PathExtract(json,path[,base])
 

where:

Extracts a JSON element for a specified path

 

Example:

 

?extension::JSON::PathExtract(json,"[1].orders[1].orderItems[1]",1)


= {
	"OrderID": "10643",
	"ProductID": "28",
	"Quantity": "15",
	"UnitPrice": "45.6"
}


Sample JSON string for above examples:


		
		[
        {
            "CustomerID": "ALFKI",
            "CompanyName": "Alfreds Futterkiste",
            "orders": [
                {
                    "OrderID": "10643",
                    "CustomerID": "ALFKI",
                    "OrderDate": "09/25/1995 12:00:00 00 am",
                    "orderItems": [
                        {
                            "OrderID": "10643",
                            "ProductID": "28",
                            "Quantity": "15",
                            "UnitPrice": "45.6"
                        },
                        {
                            "OrderID": "10643",
                            "ProductID": "39",
                            "Quantity": "21",
                            "UnitPrice": "18"
                        },
                        {
                            "OrderID": "10643",
                            "ProductID": "46",
                            "Quantity": "2",
                            "UnitPrice": "12"
                        }
                    ]
                },
                {
                    "OrderID": "10692",
                    "CustomerID": "ALFKI",
                    "OrderDate": "11/03/1995 12:00:00 00 am",
                    "orderItems": [
                        {
                            "OrderID": "10692",
                            "ProductID": "63",
                            "Quantity": "20",
                            "UnitPrice": "43.9"
                        }
                    ]
                },
                {
                    "OrderID": "10702",
                    "CustomerID": "ALFKI",
                    "OrderDate": "11/13/1995 12:00:00 00 am",
                    "orderItems": [
                        {
                            "OrderID": "10702",
                            "ProductID": "3",
                            "Quantity": "6",
                            "UnitPrice": "10"
                        },
                        {
                            "OrderID": "10702",
                            "ProductID": "76",
                            "Quantity": "15",
                            "UnitPrice": "18"
                        }
                    ]
                },
                {
                    "OrderID": "10835",
                    "CustomerID": "ALFKI",
                    "OrderDate": "02/15/1996 12:00:00 00 am",
                    "orderItems": [
                        {
                            "OrderID": "10835",
                            "ProductID": "59",
                            "Quantity": "15",
                            "UnitPrice": "55"
                        },
                        {
                            "OrderID": "10835",
                            "ProductID": "77",
                            "Quantity": "2",
                            "UnitPrice": "13"
                        }
                    ]
                },
                {
                    "OrderID": "10952",
                    "CustomerID": "ALFKI",
                    "OrderDate": "04/15/1996 12:00:00 00 am",
                    "orderItems": [
                        {
                            "OrderID": "10952",
                            "ProductID": "6",
                            "Quantity": "16",
                            "UnitPrice": "25"
                        },
                        {
                            "OrderID": "10952",
                            "ProductID": "28",
                            "Quantity": "2",
                            "UnitPrice": "45.6"
                        }
                    ]
                },
                {
                    "OrderID": "11011",
                    "CustomerID": "ALFKI",
                    "OrderDate": "05/09/1996 12:00:00 00 am",
                    "orderItems": [
                        {
                            "OrderID": "11011",
                            "ProductID": "58",
                            "Quantity": "40",
                            "UnitPrice": "13.25"
                        },
                        {
                            "OrderID": "11011",
                            "ProductID": "71",
                            "Quantity": "20",
                            "UnitPrice": "21.5"
                        }
                    ]
                }
            ]
        }
    ]


		
		

Sample Xbasic script that shows an Xdialog to show how these methods can be used:

 
'sample.json contains some sample json data						
dim json as c = file.to_string("C:\data\sample.json")

dim def.text as c = json
dim def.object as p
dim selection as c
dim subselect as c
ui_dlg_box("JSON",<<%dlg%
{watch=def.object.get_selection_start(.t.)!cursor}
[%M;K%.100,20def];
Path;
[.100path] <copy<;
[.100selection] <select>;
[%M;K%.100,5subselect];
%dlg%,<<%code%
if a_dlg_button = "cursor" then
	a_dlg_button = ""
	dim pos as n = def.object.get_selection_start(.t.)
	path = extension::JSON::OffsetToPath(strtran(def.text,crlf()," "),pos)
else if a_dlg_button = "copy" then
	a_dlg_button = ""
	selection = path
else if a_dlg_button = "select" then
	a_dlg_button = ""
	dim pos as n = extension::JSON::PathToOffset(strtran(def.text,crlf()," "),selection)
	if pos < 1 then		
		dim subselect as c = extension::JSON::PathExtract( strtran(def.text,crlf()," "),selection)
		def.object.select(pos,len(subselect) )
		def.object.show_caret()
	else
	   ui_msg_box("","Not found")	
	end if	
end if
%code%)						
					

UX Component - Client-Side Properties - On Get Value and On Set Value - Two new client-side properties have been added for Data Controls in a UX component.

 

 

In both cases, your Javascript can reference a variable called value and must return a value. For example, in the following example, the .getValue() method will return the upper case version of the control's value

 

return value.toUpperCase()

 

These methods can be used to translate a stored value into a display value and vice versa. For example, you might want to display a part description, but store the part number. The data used to to the translation might be stored in a client-side data cache.

 

UX Component - PhoneGap - Cordova-Open Plugin - The PhoneGap genie now exposes the Cordova-Open plugin. This plugin allows you to open files using their associated native application. For example, if you open a file with a .pdf extension the plugin will open the file using the native PDF application on the device. If you open a file with a .mov extension, the plugin will open the file using the native video player on the device.

The Cordova Open plugin is selected in the PhoneGap genie as shown in the image below.

 

 

There are many use cases for the Cordova-Open plugin, but PDF files is perhaps the most compelling use case. Displaying PDF files in a mobile application can be tricky because the browsers on mobile devices do not have built-in PDF viewers as is typical with desktop browsers.

Another great use case for this plugin is a mobile app that downloads multiple files (pdf, video, audio, excel, word, etc.) and then stores these files in the filesystem on the device so that they can be viewer later when the device is no longer connected to the internet. For more information on techniques for downloading files to a mobile device, see this topic in the Tips section: Downloading Files to a Mobile Device.

A new action in Action Javascript (PhoneGap - Open File with Native Application) makes it easy to use the Cordova-Open plugin in mobile applications.

The image below shows how a PDF file appears in the Native PDF viewer on an iPhone (in this case the PDF file was created by generating a report and saving the report output to a PDF file). Notice the Done button that will return you to the app when you close the Native Viewer.

 

 

UX Component - Action Javascript - PhoneGap - Open File with Native Application Action - This action allows you to open a file on a mobile device using the associated native application.

 

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

 

NOTE: You can only use this action in a PhoneGap application. The PhoneGap application must load the Cordova Open plugin.

The action allows you to:

 

When you select the PhoneGap - Open File with Native Application action in Action Javascript, the following dialog is shown:

 

 

If you specify that the file is remote, you must specify the File URL.

 

 

 

If you specify that you want to make an Ajax callback to get the file to open, you must specify the Ajax callback type

 

 

If you set the Ajax callback type to Report, you must specify which report you want to run.

 

NOTE: Alpha Anywhere will automatically send the following Javascript to the client once the report has been created:
{dialog.object}.hideWaitMessage();
This is useful because if you displayed a wait message when invoking the action to save a report as a PDF file, the wait message will automatically be closed once the report has been generated. You do not have to specify an onComplete Javascript property solely for the purpose of hiding a wait message.

 

Report Definition Genie

When you click the smart field for the Report definition property, the following dialog is shown where you can specify the name of the report to run and other properties of the report, such as the filter, and order, PDF options (such as whether the PDF file should have a watermark, etc.) and argument bindings.

 

The filter you define for the report in this dialog is in addition to any filter defined in the report definition itself.

When defining a filter, it is common to use arguments in the filter rather than literal values. For example:

Country = :whatcoutry

rather than

Country = '{country}'

where {country} is the value in a control called Country on the UX component.

To create an argument to use in a report filter click on the Define Arguments button shown in the above image and then bind the argument to a value (either a static value, or a value in a UX control) in the Set Argument Values section of the dialog.

 

Understanding the onComplete Javascript Property

When you set the Ajax Callback type to Report, the onComplete Javascript property allows you to define the name of a Javascript function that will be called after the report has been generated on the server.

Your function will take a single parameter as its input. This parameter is an object with these properties:

A common use case for this function is to store the name of the report and its associated properties (such as filesystem part, filename, etc), in a List control so that the user can quickly view a previously viewed report by simply viewing the file for that report (which is stored on the device after it is viewed for the first time). This allows the user to view reports even when there is no connection.

For example, the following function would store the report information in a List control called previouslyViewedReports:

 

(Assume that the List control has columns named filename, reportname, fspart and folder).

 

function afterReportGenerated(obj) {
 

    var l = {dialog.object}.getControl('previouslyViewedReports');
    var _d = [

        {

            filename: obj.localFilename,

            reportname: obj.reportName,

            fspart: obj.fileSystem,

            folder: obj.folder

        }

    ];
    l.appendRows(_d);
}

 

 

 

Alpha Anywhere Application Server - Building Connection Strings - If you have a remote server that does not have the Alpha Anywhere development version installed, building an ad-hoc connection string that you can paste into the a5_appllication.a5i file can be difficult.

There is now a hyperlink on the Web Server Settings dialog on the Other tab to Open the Connection String Builder Genie.  This opens the regular connection string builder where a new connection can be built and tested. It will also verify if the correct client driver is installed, as the test connection option will fail if the driver is not correct.  The generated string is shown in a simple dialog with an option to Copy to clipboard when the genie is closed. This allows creating and testing a connection in the same environment where it will be used.


Xdialog - {Condition_else} Directive - The {condition_else} directive makes it much easier to display Xdialogs that have conditional sections that render in the same place. Previously it was necessary to use the {start_pos} directive to get the second and subsequent condition to render in the same space as the first condition.

 

For example:

 

ui_dlg_box("Conditional Sections",<<%dlg%
{removeleadingspaces}
{removecomments}
{region}
    Condition: [condition^=conditions];
    {condition_begin=condition="condition1"}
        {region}
            This is condition 1;
        {endregion}  
    {condition_else=condition="condition2"}
        {region}
            This is condition 2;
        {endregion}  
    {condition_else=condition="condition3"}
        {region}
            This is condition 3;
        {endregion}
    {condition_else}
        {region}
            This is any other condition; 
        {endregion};
    {condition_end};
{endregion};

{line=1,0};
{justify=right}<Close>
%dlg%)

 

The images below show how the Xidialog renders for various conditions. Note that when 'condition4' is selected, the {condition_else} text is show because there is no handler for this condition.
 

 

 

Xbasic - Sys_shell_wait() Function -   SYS_SHELL_WAIT() now has two additional parameters (in addition to the command and the ShowWindow flag):

 Note: SYS_SHELL_WAIT() does not throw any errors if something fails.


 
There is a new function called Run() that accepts all of the same parameters (in fact is now called by sys_shell_wait() ) but will return an error if something doesn't work.

Example Interactive Window Session


Run("CMD.EXE /C \"DIR C:\*.* /s\"", .t.,1000,.t.)
ERROR: Application timed out.
 
SYS_SHELL_WAIT("CMD.EXE /C \"DIR C:\*.* /s\"", .t.,1000,.t.)
 

 

UX Components - List and ViewBox Controls - SQL Data Sources - Security and Server-side Show Hide Expressions - You can now apply security settings and server-side show/hide expressions to individual columns in the SQL queries that are used to populate List and ViewBox controls.

 

To define security and/or server-side show/hide expressions for individual columns in a SQL query, click on the smart field for the Security and Show/hide Expressions property (as shown in the image below)

 

 

This will open a builder where you can define settings for each column in the SQL query.

 

 

At run-time, before the SQL is executed, if any of the columns in the SQL SELECT statement have security or show/hide expressions, the columns that should not be shown are removed from the SQL SELECT statement. This means that if a user is not authorized to see a particular column in a SQL query, the data that are sent to the client does not include the excluded columns.

Contrast this with applying security or show/hide expressions to individual fields in the List (in the 'Fields' pane of the List builder). When you apply security to List fields that merely removes a hidden column from the List display. But the data for the hidden column is still set to the client and would be visible if the user viewed the source of the page.

NOTE: You can only apply security and show/hide settings to the SQL if Alpha Anywhere can parse the SQL statement. For example, if the data source for a List is a stored procedure, then, since this is not a parse-able statement, you cannot apply security and show/hide settings.

 

UX Component - Step Indicator Control - The Step Indicator control is used to show what step a user is on in a multi-step action.

The image below shows a Step Indicator control configured to show four steps, labeled One, Two, Three and Four

 

When you add a Step Indicator control you can specify as many steps as you want and you can define the labels for each step. You can also control the color of the completed steps (blue in the above example) and the un-completed steps (gray in the above example).

The Step Indicator control is a Data Control. This means that you can set its value using the {dialog.object}.setValue() method and you can read its value using the {dialog.object}.getValue() method.

For example, to set the above control so that it shows you are at the beginning of the sequence (on the first step) you would use:

{dialog.object}.setValue('name of control',0)

To set the control's value so that it shows you are on step Three (i.e. as shown in the above image) you would use:

{dialog.object}.setValue('name of control',2)

 

To add a new Step Indicator control to a UX, select the [More...] entry in the UX toolbox in the Data Controls section.

 

 

This display a list of additional control types.

 

To configure a Step Indicator control, click the smart field for the control's Control Properties property.

 

 

In the image below, the 'Dot' size has been increased, the 'Show step indicators as circles' property has been turned off and the 'Dot size' has been set to '40px'. A small border radius of 2px has been set so that the 'dot' (squares in this case) have slightly rounded edges.

 

 

Xbasic - a5Helper_SQL_ApplySecurity() Function - The a5Helper_SQL_ApplySecurity() function applies security and server-side show/hide expressions to a SQL SELECT Statement. Any column that is not authorized by the security group or server-side show/hide expression is removed from the SQL Select statement.

The SQL statement you pass to this function must be parseable. If Alpha Anywhere cannot parse the statement (e.g. the SQL is a call to a stored procedure), the function returns the original SQL statement.

If a column does not have a security setting or server-side show/hide expression is will be included in the SQL statement.

If a column has a defined security setting that the column will only be included in the SQL statement if the logged in user is a member of one of the security groups specified by the column's security setting.

If a column as a show/hide expression the column will only be included in the SQL statement if the expression evaluates to a true result.

Syntax

c SQLStatement = a5Helper_SQL_ApplySecurity(sql as c , securityDef as c , loggedInGroups as c)

Where:

 

securityDef is a JSON array of objects. Each object in the array has these properties

 

 

The column specify in the securityDef must match exactly how the SQL parser represents the column. For example, consider the following column expression

concatenate(customers.name , ', ', customers.contacttitle)

 

The meaning of this expression is unchanged if the expression is written as:

concatenate(     customers.name     , ', ',     customers.contacttitle   )

 

However, this is not how the expression is represented in the SQL parser. To get the correct representation of the expression, you can use the code below:

dim si as sql::Query::SelectItem
sql2 = "concatenate(   customers.name   , ', ',   customers.contacttitle)"
?si.Parse(sql2)
= .T.

?si.SQLStatement
= "concatenate(customers.name, ', ', customers.contacttitle)"
 

 

Example

sql = <<%str%
SELECT customers.CustomerID as cid, customers.CompanyName as compName, customers.ContactName, customers.ContactTitle, concatenate(customers.name,', ',customers.contacttitle) as exp1, orders.OrderID, orders.CustomerID AS CustomerID1, orders.EmployeeID, orders.OrderDate, orders.RequiredDate
FROM customers customers
 INNER JOIN orders orders
 ON customers.CustomerID = orders.CustomerID
%str%
 

'define the security settings

dim ss[0] as p
ss[].column = "customers.ContactTitle"
ss[..].security = ""
ss[..].showHide = "session.var1 = \"alpha\""
 

ss[].column = "concatenate(customers.name, ', ', customers.contacttitle)"
ss[..].security = "Sales,Marketing"
ss[..].showhide = ""
 

ss[].column = "customers.CompanyName"
ss[..].security = "Administrator"
ss[..].showhide = ""

 

dim security as c

'Generate a JSON string
security = json_generate(ss)

 

dim loggedInGroups as c

loggedInGroups = Context.Security.GetUserRoles()


sql2 = a5Helper_SQL_ApplySecurity(sql,security,loggedInGroups)
 

 

UX Component - PhoneGap Applications - Delay Function Calls Until PhoneGap is Ready - Typically, when a need to execute a method that can only be run after PhoneGap has loaded, you add code to the onPhoneGap ready client-side event. But in some cases this is not practical and you might already have some code that runs in the onRenderComplete, or onPrepareComplete event and some of the methods in these events need to wait till PhoneGap is ready.

The new {dialog.object}._delayTillPhoneGapReady() method allows you to register function calls that will only be made once PhoneGap is ready.

The syntax is:

{dialog.object}._delayTillPhoneGapReady(functionToExecute, scope, arguments)

 

For example, say you wanted to call the List Object's ._fetchMediaFiles() method.

Normally your code would be

var lObj = {dialog.object}.getControl('LISTNAME');

lObj._fetchMediaFiles()

 

This could be rewritten as

var lObj = {dialog.object}.getControl('LISTNAME');

{dialog.object}._delayTillPhoneGapReady(_fetchMediaFiles,lObj)

 

 

UX Component - Building Component Programmatically Using Xbasic - Absolute Layout Containers - You can now use the a5wcb_createDialogUsingXbasic() Xbasic function to create a UX component that define a component that contains an Absolute Layout container. This is made possible because the Absolute Layout's absolutePositions property now allows you to specify the variablename of the control in the absolute layout, rather than its idInternal property, which cannot be used because it is dynamically assigned when a5wcb_createDialogUsingXbasic() executes.

 

dim wp as p
DIM wp.page_fields[0] as P

with wp.page_fields[]
.controltype = "layout_directive_ContainerBegin"
.v.container.subType = "AbsoluteLayout"
.v.container.id = "ABS1"
.v.container.absolutePositions = <<%str%
[
    {
        variablename: 'c',
        top: '7px',
        left: '16px',
        height: '28px',
        width: '139px',
        style: 'position: absolute; top: 7px; left: 16px; width: 139px; height: 28px; '
    },
    {
        variablename: 'd',
        top: '156px',
        left: '141px',
        height: '27px',
        width: '132px',
        style: 'position: absolute; top: 156px; left: 141px; width: 132px; height: 27px; '
    }
]

%str%
end with

with wp.page_fields[]
    .v.variableName = "c"
    .v.breakType = "None"
end with

with wp.page_fields[]
    .v.variableName = "d"
    .v.label = "Field D"
    .v.hasWaterMark = .t.
    .v.waterMark.text = "Enter name"
end with

with wp.page_fields[]
    .controltype = "layout_directive_Containerend"
end with

a5wcb_createDialogUsingXbasic(wp,"genByXbasic",.t.)
 

PDF Reports - Embed Fonts - In certain cases, PDF reports generated will not render correctly on iOS devices. This is because, by default, the PDFs are generated with the 'Embed fonts' option set to false. The PDFs do not render on the iOS devices because they use fonts they are not native to the iOS device. The solution is to turn the 'Embed fonts' option on (this is done by opening the Project Properties dialog and going to the PDF Options section).

Now, the Embed fonts option is turned on by default. Since this will result in slightly larger PDF files, some developers might want to not embed fonts in generated PDF files. This can be done by setting the property in the Project Properties.

UX Component - Pre-render Option - Bulk Update - If you have a large number of UX components and you want to turn on the 'Pre-render at design-time' option for each UX component, opening each component, setting the property and then saving the component would be tedious. A new bulk operation allows you to automatically set this property in multiple UX components at once.

 

 

 

Xbasic - Regular Expressions - regex_valid() Function - The regex_valid() function can be used to test if a regular expression is valid.

 

Examples:


? regex_valid("[.+")
= .F.

 

The issue with the above failing regular expression is lack of a closing ']'.
 


? regex_valid("[.+]")
= .T.


? regex_match(".","[.+")
ERROR: Unmatched [ or [^ in character class declaration. The error occurred while parsing the regular expression: '[.+>>>HERE>>>'.
 

 

 

UX and Grid Components - <ProjectStyle> - Compact Styles - Certain of the built-in styles (e.g. 'Alpha') have a 'compact' option. If you set  <ProjectStyle> to 'Alpha' you can now specify that you want to use the 'compact' option by setting the  <ProjectStyle> to Alpha:compact . In an individual component that is set to use <ProjectStyle> as its style, you can override the global settings of 'compact' or 'non-compact' by specifying:

<ProjectStyle>:compact

or

<ProjectStyle>:notcompact

 

UX Component - List Control - Show/Hide List Column - A new method has been added to the List control that allows you to show or hide a List column.

Syntax:

<listObject>.showHideColumn(columnNumber,flagShow)

 

 

UX Component - Pre-render at Design-time Option - Warning Message - When you save a UX component that does not have the Pre-render Component at Design-time option turned on, a warning message now comes up telling you that it is recommended to turn this option on because of the significant speed improvement this options will give at run-time.

If you choose not to turn the Pre-render option on, you can specify that the message should not be shown again for this component, or for all components

If you choose to turn the option on you can specify that the option should automatically be set to 'on' for all future UX components that you create.

TIP: If you choose the option to turn on pre-render for all UX components, you can un-set the option by going to View, Settings, Preferences, UX Component.

Xbasic Functions - JSON_to_YAML() - YAML is a markup language that is sometimes used in place of JSON. This function converts JSON to YAML. YAML (yet another markup language) uses nesting to represent hierarchy.

Example

 

json = <<%str%
{
    "fname": "john",
    "lname": "public",
    "children" : [
        {"name": "callie","hobbies": ["minecraft","leggo"]},
        {"name": "griffin","hobbies": ["ballet"]}
    ],
    "address": {
        "street": "12 and main",
        "city": "Squares Ville",
        "State": "KY"
    }
}
%str%

 

?json_to_yaml(json)

 

fname: john
lname: public
children:
    - name: callie
      hobbies:
        - minecraft
        - leggo
    - name: griffin
      hobbies:
        - ballet
address:
    street: 12 and main
    city: Squares Ville
    State: KY
 

Note: This function is just a wrapper around the  extension::JSON class.

 

Xbasic Functions - JSON_from_YAML() - YAML is a markup language that is sometimes used in place of JSON. This function converts YAML to JSON.

 

yaml = <<%str%

fname: john
lname: public
children:
    - name: callie
      hobbies:
        - minecraft
        - leggo
    - name: griffin
      hobbies:
        - ballet
address:
    street: 12 and main
    city: Squares Ville
    State: KY

%str%

 

json_from_yaml(yaml)
= {
    "fname": "john",
    "lname": "public",
    "children" : [
        {"name": "callie","hobbies": ["minecraft","leggo"]},
        {"name": "griffin","hobbies": ["ballet"]}
    ],
    "address": {
        "street": "12 and main",
        "city": "Squares Ville",
        "State": "KY"
    }
}
 

 

Note: This function is just a wrapper around the  extension::JSON class.

 

 

 

UX and Grid Component - Live Preview - Edge - When you do a Live preview from the UX or Grid, you can now select Microsoft Edge as the target. (For Windows 10 and above)

UX Component - Google Visualization Libraries- Gantt - Because of a recent change Google made to how their visualization libraries are loaded, if you select the 'gantt' library, you would get a Javascript error. This is now fixed.

 

 

Alsp, the sample templates that are available when you create a new UX includes an update example for Google charts. This new component includes as Gantt chart, as shown in the second image.

 

 

Xbasic Arrays - DIMMing Arrays with Default Values - When you DIM a new array, you can now specify a default value for each array item. This is especially useful when DIMming arrays for use with .Net code.

Examples:

dim sb[6] as system::Text::StringBuilder = new system::Text::StringBuilder(1024)
? sb[1].capacity
= 1024
? sb[2].capacity
= 1024
...
 

 


dim nums[6] as n = rand()
? nums
= [1] = 0.680694580078125
[2] = 0.709716796875
[3] = 0.17425537109375
[4] = 0.60302734375
[5] = 0.752105712890625
[6] = 0.02587890625


dim strs[6] as c = Rand_String(6+int(rand()*10))
? strs
= [1] = "eimpzcugesd"
[2] = "chjhlwuzu"
[3] = "nioseq"
[4] = "gsrslnflqravo"
[5] = "rvaqfaqqu"
[6] = "joexbk"

 

 

Xbasic - AlphaDAO SQL::Resultset.toJSON() - The .toJSON() method has been changed so now it create a parseable JSON array of objects. Previously the .toJSON() method was used for an internal function and it generated a special format that was of no general use.

Contrast the AlphaDAO SQL::Resultset.toJSON() with the AlphaDAO SQL::Resultset.toJSONObjectSyntax() method. The later generates a CR-LF delimited string of JSON objects. To turn the output from this method into a parseable string, it is necessary to add the opening and closing square brackets and to terminate each line, except the last, with a comma.

Examples:

dim cn as sql::Connection
cn.Open("::Name::northwind")
cn.PortableSQLEnabled = .t.
cn.Execute("select customerid, contactname, city, country from customers where country = 'canada'")
rs = cn.ResultSet
? rs.tojson()
= [
{"customerid" : "BOTTM", "contactname" : "Elizabeth Lincoln", "city" : "Tsawassenn", "country" : "Canada"},
{"customerid" : "LAUGB", "contactname" : "Yoshi Tannamuri", "city" : "Vancouverr", "country" : "Canada"},
{"customerid" : "MEREP", "contactname" : "Jean Fresnière", "city" : "Montréal", "country" : "Canada"}
]

cn.Execute("select customerid, contactname, city, country from customers where country = 'canada'")
rs = cn.ResultSet
? rs.ToJSONObjectSyntax()
= {"customerid" : "BOTTM", "contactname" : "Elizabeth Lincoln", "city" : "Tsawassenn", "country" : "Canada"}
{"customerid" : "LAUGB", "contactname" : "Yoshi Tannamuri", "city" : "Vancouverr", "country" : "Canada"}
{"customerid" : "MEREP", "contactname" : "Jean Fresnière", "city" : "Montréal", "country" : "Canada"}

 

 

UX Component - Pre-render - Security and Server-side Show/Hide Expressions - The pre-render option for UX component can make a dramatic difference in the speed with which UX components are rendered. This is especially true of large UX components. Pre-rendering can result in 5 to 10x performance improvements in certain cases. However, if your UX component used security or server-side show/hide expressions to control the visibility of certain controls on the UX you were not able to turn the pre-render feature on.

Now, even if your UX uses security or server-side show/hide expressions, you can still use the pre-render option as long as you also turn on the Apply security and server-side show/hide expressions property.

When this property is turned on, the UX is not recomputed at run-time (as is normally the case when a UX which uses security and/or server-side show/hide expressions). Instead, at run-time, data are sent to the UX with information about what security groups the user is in, and which controls need to be hidden or shown as a result of evaluating server-side show/hide expressions. A client-side function will then hide the controls that should not be visible.

 

 

It is important to understand that when you turn on the option to apply security and server-side show/hide expressions client-side, the result is not as secure as applying security and server-side show/hide expressions on the server. That's because when security and server-side show/hide expressions are applied server-side, the HTML and data that are sent to the client does not physically include anything that should not be visible to the user.

But when apply these settings client-side, the HTML may contain sensitive information that the user could see by viewing the page source (even though this information is hidden on the page itself).

A side benefit of turning this option on is that any controls whose visibility is controlled by a server-side show/hide expression will be shown or hidden if any ajax callback sets the value of a session variable that is used in a server/side show expression.

 

UX Component - Action Javascript - SQLite Actions - Several new actions have been added to the SQLite Actions actions in Action Javascript.

The new actions are:

Get Fields in a Table - This action will get the fields in a table as well as some additional information. The onSuccess event handler gets an array of objects. The array has an entry for each field in the table. Each object in the array has these properties:

Delete a Database - Deletes the physical file for the SQlite database from the device.

Create a Table - Allows you to create a new table in a SQLite database. You can define the table structure and also the indices for the table. The image below shows the builder where you specify the table structure. The action will automatically drop any existing table with the same name.

 

 

Create a Table from Data - This action will create a new table from data (i.e. it will import data into a new table). The data from which the table is created is a JSON array of objects where each object represents a record. For example, if you specify the following data:

 

[

    {"id" : 1, "FirstName": "Bob", "LastName": "Smith", "Department" : "Sales"},

    {"id" : 2, "FirstName": "Terry", "LastName": "Jones", "Department" : "R&D"},

]

 

A new table with 2 records would be created. The fields in the table would be id, FirstName, LastName and Department and the type of each field (except the id field) would be TEXT. The type of the id field would be INTEGER.

NOTE: SQLite does not have Date or DateTime fields. Date and time values should be stored in TEXT fields and should appear in the data to be imported as string values.

When you specify the data from which the new table is to be created you have the following options:

When you specify that the data are to be computed by an Ajax callback you have two options

You can specify if a table already exists with the table name you specify that the existing table should be dropped. If you do not drop the existing table, the operation will fail.

You can also specify a batch size property. After the new table has been created (with no records in it initially), INSERT statements are executed to insert the data into the table. You can specify how many records should be inserted with each INSERT statement. The default batch size is 100, which means that each INSERT statement will insert up to 100 records into the table. If you set the batch size to -1, Alpha Anywhere will try to add the data to the table with a single INSERT statement. However, this may result in an INSERT statement that exceeds the maximum statement length supported by SQLite and the action will fail. If you set the batch size  to 1, Alpha Anywhere will perform one INSERT statement for each row of data to be added to the table. If you have a large amount of data, this could be slow. Therefore, if you want to optimize performance of this action, you will want to choose the largest batch size possible before the action fails.

If the action fails at any point while adding the records to the newly created table, the table is not created.

 

Import Data into a Table - This action is very similar to the Create a Table from Data action except that a new table is not created from the data. Instead, the data are imported into an existing table. All of the options for specifying the data that the Create a Table from Data action supports are supported by this action.

 

Delete All Records from a Table - This action deletes all of the records in a table.

 

UX Component - List Control and ViewBox Control - Text Select - A new property 'Allow text select' allows you to enable/disable the ability to select text in a List or ViewBox control. Previously this always defaulted to true. Now, this property defaults to false.

UX Component - List Control and ViewBox Control - Multi-select - Shift+Click - When doing a multi-select in a List or ViewBox that is configured to allow multiple selections, shift+click will now select multiple values, following the standard Windows conventions.

 

UX Component - FormView Control - Default Template and Named Templates - Formatting Directives - You can now use formatting directives in templates. For example:

 

Web Publishing - HTTP publish and Optimized Publish - These publish methods will now force a reload of the security data and will clear the UX component cache, so any changes should be reflected in the first request after publish.

UX Component - Action Javascript - PhoneGap File Download Action - This action has been enhanced. You can now specify that the list of files to be downloaded should be generated by making an Ajax callback. Of course, this same Ajax callback can also create the files to download (which is the most likely reason for choosing this option).

You can also specify where the file(s) that are downloaded should be stored in the device's filesystem.

You can set the Filesystem property to one of the defined locations. You can also set this property to the name of a Javascript function that will return the name of the Filesystem part, using this syntax:

javascript:myfunctionname

Your function must return the filesystem part (e.g. saved, private, public, persistent). Alternatively, you can return an explicit folder where you want to store files by prefixing the return value with 'explicit:' . For example:

 

function myfunctionname() {

    //return full path to folder with trailing /

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

}

 

 

 

 


 

UX Component - Action Javascript - SQLite - Delete a Database - A new SQLite action has been added. The 'Delete a Database' action will delete a SQLite database file that had previously been downloaded to the device.

UX Component - List Control - Refresh List Data Action - Keep Focus - Child Records -  If you refresh List data and you select the option to keep focus on the current selection, child records (if any) will also keep their focus. Previously only the record in the parent List kept its focus.

 

 

UX Component - Captcha Controls - You can now define the style for the captcha control error message and you can control where the message is displayed.

 

UX Component - Application Cache - Spaces in Filenames -  If a file in the manifest had spaces in the name, the application cache was not created. This is now fixed as all filenames in the manifest are now URL encoded.

 

Bugs

UX Component - List Control - iOS Devices - List Freeze - Fixed an issue where the List control could freeze if it was being scrolled at the same time that the List was being repopulated. This issue could also have affected scrolling on PanelCards.

 

UX Component - Video Player Control - Action Javascript - SSL - YouTube - The action to set the YouTube video id was not honoring the SSL flag set in in the VideoPlayer properties.

 

UX Component - DetailView - Media Files - Incremental Refresh - After performing an incremental refresh on a List control, remote media files referenced in new data displayed in the List were not being fetched.

 

Xbasic - a5storage_listitems() Function - The a5storage_listitems() was limited to 1,000 items. Now, all of the items in the bucket are listed

 

UX Component - ControlBar Control  - Disclosure Button - Placeholders in Button Text - If a disclosure button had a placeholder in the button text, the placeholder was not resolved when the Disclosure was in its open state.

 

UX Component - List with Detail View - PhoneGap - Fetch Media Files - If a List with a Detail View was configured to fetch the media files referenced in the List from a remote server and store them in the file system on the device, when the PhoneGap app was loaded you would occasionally get a 'PhoneGap not ready' error message. This is now fixed. The reason for the error was that the method that downloads media files was firing before the PhoneGap ready event.

 

UX Components - Repeating Sections - Date Fields - If the client side date format for date fields in a Repeating Section did not match the server-side date format, when submitting data to the server, the client-side date fields in the Repeating Section were not being translated to the server-side date format.

UX Component - Client-side Calculated Fields - International Formats - If the client side decimal separator was set to a comma, then client-side calculated fields that involved decimal numeric fields were not being computed correctly. This bug was introduced in version 4.3.

 

UX Component - Ink Control - If a UX component was a child of a parent UX component, and the child UX component contained an Ink control, the Ink control would, in certain cases, not operate the second or subsequent time the child UX was opened.

Tips

Downloading Files to a Mobile Device - This topic discusses two different techniques for downloading files (such as PDF, Video, Audio, Excel, Image files) to a mobile device so that the files are stored in the filesytem on the device and can be viewer later on (presumably when the device no longer has an internet connection) using the Native app associated with the particular file type.

NOTE: The comments in this topic apply only to PhoneGap applications. Your PhoneGap application will need to load the following plugins: Cordova Open, Device, File, File Transfer.

The first technique uses the PhoneGap - File download action in Action Javascript. Using this action you can define an action that will download a list of files and store them in the filesystem on a mobile device. The action downloads a list of files returned by a Javascript function.

The second technique uses features of the List control to automatically download files when the List is populated. The data with which the List is populated should contain a field that has the URL for file you want to download. For example:

 
Filename URL
pdffile1 http://alphafiles.s3.amazonaws.com/pdffile1.pdf
pdffile2 http://alphafiles.s3.amazonaws.com/pdffile2.pdf
pdffile3 http://alphafiles.s3.amazonaws.com/pdffile3.pdf
pdffile4 http://alphafiles.s3.amazonaws.com/pdffile4.pdf
etc....  

 

To use this technique:

The advantage of this second technique over using the PhoneGap - File download action in Action Javascript is that the downloading of files is automatically handled for you.

 

 

 

 

 

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

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.

TIP: In some cases, instead of populating the List with static data, you might want to generate the List data by querying a SQL database. See the video 'Displaying Hierarchical Data From a SQL Table in a List' for a demonstration of how this can be done.


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 (a5_sqlToJSONTree() ). 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 Prope