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.5.5.0 - Build 5667-5254 16-FEB-2019

Bugs

Application Server - Fixed a race condition that could potentially lead to a server crash.

Control Panel - Fixed some issues that primarily affected Desktop applications.

 

Alpha Anywhere V4.5.4.9 - Build 5663-5253 14-FEB-2019

Videos

UX Component - List Control Setting the order and visibility of columns in a List Layout You can allows users to dynamically show/hide List columns at run-time and also to change the order in which the columns appear in the List by adding a List column show/hide button to a UX component.

In this video we show how a List column show/hide button can be added to a UX and we show how it can be used to change the columns in the List are run-time.

NOTE: In the video we show how an event is fired when the List layout is changed. This event is defined in the List builder - onListColumnSelectorChanged event.

Watch Video

Date added: 2018-02-13

 

 

Features

UX Component - List Control - Column Show/Hide and Re-order - The List columns show/hide feature has been enhanced and you can now also control the order in which the List columns are shown.

You can add a List column show/hide button to your UX by selecting the List column show/hide control in the Defined Controls section in the UX builder.

When you click on the button at run-time you will see a drop-down menu (as shown in the image below). To turn a column's visibility on/off, click on the checkbox. To change the order of a column, drag on the hamburger icon and drop the column at the desired position.

When the user makes a selection in the show/hide menu, a client-side event in the List is fired (onListColumnSelectorChanged). This event could be used to persist the state of the List.

Grid Component - Search Part - Initial Value for Date Fields - Client-side Date Format - In some cases you may have a Grid that is running on a server that uses US Regional Settings (for example, Alpha Cloud). In your Grid you may have defined the client-side date format to use a dd/MM/yyyy format.

In order to set the initial value in a search field to today's date (honoring the client-side date format defined in the Grid) you can now use the {grid.clientSideDateFormat} placeholder in your initial value expression.

For example

=time("{grid.clientSideDateFormat}",date())

 

 

 

Bugs

Reports - Memory Leak - Fixed a memory leak in freeform report that had an embedded bitmap as the report background.

Control Panel - Maximize - Fixes focus problems when the Control Panel is maximized.

 

HTML5 Input Range Control - Panel Cards - iOS Devices - The HTML5 Range control implements a slider. On iOS devices, if the control is inside a Panel Card, the slider could not be moved by dragging on it. This is now supported.

If you do have a Range input control in the Panel Card, it is recommended (but it is not strictly necessary) that you wrap the Range control inside a DIV and then add this code to the onRenderComplete client-side event:

 

This will improve the user experience when dragging on the Range control's slider.

 

var ele = {dialog.object}.getPointer('DIV_1'); //DIV_1 is the id of the enclosing DIV.

A5.u.drag.add(ele,'prevent');
 

 

 

Alpha Anywhere V4.5.4.8 - Build 5647-5251 09-FEB-2019

Bugs

UX Component - List Builder - Fixed a bug in the Property Grid when editing column properties. This bug was introduced in build 5644.

Layout Table Reports - Fixed an issue with rendering HTML reports in a pop-up window or Tabbed UI pane. This bug was introduced in build 5644.

 

Alpha Anywhere V4.5.4.8 - Build 5644-5250 07-FEB-2019

 

Hotfix - List Control Builder - Fixes a problem in the Property Grid for editing column properties in a Columnar Layout.

Hotfix - Layout Table Reports - Rendered as HTML in a window or Tabbed UI Pane - Report content was not displayed.

 

How to install a hotfix

 

 

UX Component - Pinch to Zoom - A new property has been added to Panel Cards to allow you turn on support for the pinch gesture to zoom the size of a Panel's contents.

 

 

UX Component Builder and TabbedUI Builder - Security Groups - When working with large components, it can be difficult to get a good overview of which controls has security settings. A new option allows you to get a quick overview of the security settings for all controls in a component.

 

To open the Bulk Security Settings dialog, click the lock icon on the toolbar above the control list. This will open the dialog as shown below.

The dialog can operate in two different modes. When you open the dialog the mode you last selected is automatically selected. In Control mode (shown in the second image below) you can see what security groups have been assigned to the selected control. You can change the security groups for the selected control and you can set security groups for multiple controls at once by multi-selecting controls in the left hand list.

 In Security Group mode you can see all of the controls that have the selected security group(s).  For example, in the mage below you can see that only the 4th control (a button) has Administrators in its security groups. You can multi-select Security Groups in the left hand list to see all controls that have all of the selected Security Groups. You can also set security groups for the controls that you select in the right hand list.

 

Bulk Security Dialog in Security Group Mode

 

Bulk Security Dialog in Control Mode

 

UX Component - List Control - Action Javascript - List Control Actions - Refresh Data Action - You can now specify that when you refresh data in a List any server-side order and filter expressions that were applied by the user should be retained. To set this option, check the Preserve current filter/order property. If this property is not checked, then when the List data are refreshed, if the user has applied a server-side filter and/or order to the List, the filter and order are removed.

 

 

UX Component - Panel Navigator - onBeforeRemove Event - If a Panel Navigator is configured to use a TabBand to change the active Panel, a new Javascript event is available. The onBeforeRemove event will fire before a Panel is removed. Dynamic Panels can be removed from a Panel Navigator when the user taps on the close button in the Tab for the Panel. Panels can also be removed programmatically using the {dialog.object}.panelRemove() method. If the onBeforeRemove does not return true, the Panel is not removed.

 

 

NOTE: Your Javascript code can reference arguments[0] to get an object with information about Panel being removed.

 

UX Component - Javascript - {dialog.object}.panelRemove() Method - Allows you to remove a Panel from a Panel Navigator. You can either specify the Panel name or title. For Dynamic Panels, it is likely that you will only know the title and not the name.

Syntax:

{dialog.object}.panelRemove(panelNavigatorName, panel, type)

 

Where:

UX Component - List, ControlBar, ViewBox and FormView Builder - Javascript Functions - You can now import and export functions defined at the object level.

UX Component - ActionSheet - Events - The events now wait till the Action Sheet is closed before firing.

Bugs

Desktop Applications - Browse - Toolbar and Menus - In some circumstances when you opened a Browse window, the correct menu and toolbar was not shown until you first gave focus to some other window and then returned to the Browse window.

UX Component - List Control - Kanban Layout - User Defined Edits to Kanban CSS - User edits to the system generated Kanban CSS were getting overwritten when the List definition was saved.

 

UX List with Detail View - Media Files - Errors Uploading Media Files  - If you have a List with a Detail View and the List has media files (pictures, audios, etc), then when you sync the List, in normal operation the media files get uploaded first and then once all media files are uploaded, the data is synced. If there were any errors while uploading the media files, the rows in the List that contained the media files with errors should not have been synced. These rows should have remained dirty so that on the next sync attempt, a second attempt would be made to upload the images.

 

 

 

 

Alpha Anywhere V4.5.4.8 - Build 5581-5237 10-JAN-2019

Web Component Builders - Property Grid - Hover Style - You can now specify that when the mouse is over a property in a Property Grid that a hover style should be shown. For example, in the image below, the mouse is over the Height property and therefore, the row is displayed using the hover style.

 

 

 

To turn on the hover style select View, Settings from the menu and navigate to the Preferences, Propgrid section. You can also customize all aspects of the Propgrid appearance, by setting the Propgrid style to custom. This allows you to define a custom "CSS like" stylesheet which can be stored in a file called propgrid.style in the Alpha Anywhere executable folder. Sample syntax for the propgrid.style file can be found in the sample_propgrid.style file (also in the Alpha Anywhere executable folder).

 

UX Component - List Control - Columnar Layout - Hide Columns - You can now set the initial state of a column to hidden. The user can subsequently show the column if your UX component contains a Show/HideList Columns  control (see below for more information).

 

 

UX Component - ControlBar - Pre-defined Button Builder - When you add a new button item to a ControlBar, the Pre-defined Buttons genie now allows you to create Docked Panel Controller buttons.

 

 

UX Component - List Control - Show/Hide List Columns - You can now control the visibility of columns in a List control.

 

For example, in the image below, a column selector is shown. You can toggle the visibility of any column by clicking on the column name in the menu that is shown when the column selector button is clicked.

 

 

To add a List Column Selector button to a UX, select the List columns show/hide item from the Defined Controls section of the UX Builder toolbox.

 

 

UX Component - Javascript Library - .listColumnSelector() Method - A new method has been added to the UX component's Javascript library. The {dialog.object}.listColumnSelector() method displays a pick-list of all columns in the currently active columnar List layout (a List can have multiple Layouts some of which are columnar, others might be freeform or Kanban). By clicking on the items in the pick-list you can toggle the visibility of columns in the List layout.

Syntax

{dialog.object}.listColumnSelector(ele,listName [, maxHeight]);

 

Where:

 

UX Component - List Control - Word-wrap - A new option is available when you turn on word-wrapping for columns in a List control. The break-word option will allow long words that do not have spaces to be broken. By default if you have a long word with no spaces (i.e. there is no break point in the word), the word is truncated and ellipsis are displayed at the truncation point.

 

 

Web Components - Backups - When you edit a component (i.e. Grid, UX, etc.) a backup copy is automatically made. The folder where the backups are stored can become quite large over time. You can now specify that backups that are more than a certain number of days old should be purged. When purging old backups you can also specify the maximum number of backups to retain and the minimum number of backups to retain.

 

 

Xbasic Functions - Return Value - You can now use the RETURN keyword to indicate the return value of a function. For example:

 

function f1 as c ()

 return "some value"

end function

 

Previously the function would have to be defined as:

 

function f1 as c ()

f1 =  "some value"

end function

 

Both styles are now supported.

 

Xbasic -  ENDIF Statement - You can now use ENDIF in addition to the END IF statement.

 

UX Component - TransForm Data Viewer Control - Data Groups - You can now add and delete items in the form data when using the TransForm Data Viewer Control.

NOTE: When you add or delete a group, the data are immediately saved.

 

 

UX and Grid Components - Action Javascript - Convert to Javascript Action - You can now convert actions in an Action Javascript to a Javascript Action.

For example, here is the onClick event handler for a button (notice that the event has 3 separate Actions and no Javascript Actions are defined):

 

 

And here is the onClick event handler after the first two actions are converted to a Javascript Action:

 

 

convert_color_name_to_hex() Function - Converts a color name to a hex value. To get a list of all supported color names, call the function specifying the name argument as <showcolors>.

UX and Grid - Switch Year for 2 Digit Dates - The default switch year for 2 digit dates has been changed from 20 to 30. This means that a date value of 12/25/22 is now considered to be 12/25/2022 rather than 12/25/1922. You can specify a different default value for the switch year in Project Properties.

 

OpenSSL - Alpha Anywhere is now built using OpenSSL version 1.0.2q

 

AlphaDAO - MySQL - utf8mb4 (and not utf8) is now the character set for the MySQL and MariaDB drivers. MySQLV4 – used for older versions of MySQL is unchanged.


 
cn.tostring("SELECT * FROM performance_schema.session_variables WHERE VARIABLE_NAME IN ('character_set_client', 'character_set_connection','character_set_results', 'collation_connection') ORDER BY VARIABLE_NAME;")


 
= character_set_client             utf8mb4
character_set_connection           utf8mb4
character_set_results              utf8mb4
collation_connection               utf8mb4_general_ci
 

Property Grid - Grid lines - The new property grid that was introduced in a recent build now displays horizontal and vertical grid lines (like the old property grid did). You can customize the color of the grid lines by selecting View, Settings from the menu and navigating to Preferences, PropertyGrid.

 

Bugs

UX Component - Signature and Ink Controls - Touch Enabled Screens and Browsers - On a touch enabled screen, when using a touch enabled browser (such as Chrome) you could only draw on the control using the mouse. Now you can also use a finger or stylus.

Lookup Grids - Fixed a Javascript error for nested Lookup Grids.

Application Server for IIS - Fixed an issue with the Context.Session.SetSqlCredentials() method. Fixed an issue with setting active language, client side decimal character and client side thousands separator character using __protected__ session variables.

 

Xbasic Script_schedule() function - Under some circumstances, this function failed to execute the target script.

Grid Component - Arguments - If you specified that an argument should be set the the id of the current logged in user, or to data from the Extended User Information table, the argument value was not getting set correctly on the initial Grid load.

Advanced Search Control - Daterangepicker Control -  If you used a 'daterangepicker' control in the Advanced Search control, the option to set the filter type (e.g. 'Starts with', 'Ends with', 'QBF syntax') is now suppressed and the 'QBF syntax' option (which is the only relevant option) is now assumed.

AlphaCloud - Publishing - After publishing to AlphaCloud, Windows Explorer was opened showing content of the temporary CloudLocal folder.

UX Component - List Control - Client side conditional style - Fixed bug in Javascript expression validation.

 

 

 

Alpha Anywhere V4.5.4.7 - Build 5487-5217 27-NOV-2018

Hotfix - List Control - Client-side conditional style - Javascript expression validation, Style Builder - copying a style, Grid - setting an argument to current logged in user id.

 

Hotfix - Under some circumstances, a UX component built with an older version of AA will not run. This hotfix fixes this issue. The hotfix must be applied to both the IDE (developer version) and also the Server. The circumstance under which this issue occurs is as follows: If a UX component uses the 'Alpha' style and it has not been edited using build 5487 (i.e. the component was built using an older build) and if the UX has one or more controls that have security settings or server-side show hide expressions, and if the UX is not pre-rendered, the error will occur. If the UX is pre-rendered and the 'Apply security and server-side show/hide expressions client-side' is checked, the issue will not occur.

 

Hotfix - Under some circumstances when running a Grid for which arguments have been defined you will get an error: Script:A5_ArgGetValue() line:61 Variable "flagInquery" not found.

 

How to install a hotfix

 

 

Features

Component - Editing Styles - Inherited Styles - When you try to open an inherited style in the style builder (e.g. 'Alpha-Rose'), you now have the option of creating a 'detached' version of the style (i.e. a style that is no longer inherited from its base style). The advantage of creating a detached copy of that you can then use the style builder to modify all aspects of the style. If you edit an inherited style in the style builder you can only add new sub-themes. You cannot edit all aspects of the style.

 

UX Component - List Control - Client-side Group Breaks - Javascript - You can now automatically collapse or expand all or selected groups in a List.

You can select which groups to collapse or expand using a function.

If your List contains multiple level of grouping you can collapse/expand groups at a particular level

Syntax

<listObj>.setGroupCollapse( groupSelectionObject, flagCollapse, flagAnimation)

 

where

 

 

Examples

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

lObj.setGroupCollapse({groups: 'all'},true,false); // collapse all groups without animation
lObj.setGroupCollapse({groups: 'all'},false,true); // expand all groups with animation
 

Assume list has two levels of grouping - 'Country' and 'City'

lObj.setGroupCollapse({groups: 'level', level: 0},false,true); // expand all "country" groups with animation

lObj.setGroupCollapse({groups: 'level', level: 1},true,false); //collapse all "city" groups without animation



Setting certain groups to be collapsed:


lObj.setGroupCollapse({groups: 'match', match:
    function(groupName,groupData){
        if(groupName.match(/^[A-z]/)) return true; // match any group with a name starting with a character
        return false;
    }},true); // collapse all groups that the passed in function returns true for
 

 

UX Component - TransForm - TransForm FormDataView Control - A new control type can be added to the UX component. The TransForm FormDataView control allows you to display the data in a TransForm form using a control that looks the same as the manner in which form data is displayed in the TransForm Central Management Console. You can also edit data in the form with the TransForm FormDataView control.

To add a TransForm FormDataView control to a UX, select the [More..] item in the Data Controls section.

 

 

Then select the TransFormDataViewer control.

 

Click the smart field for the Custom Control properties to configure the control. The configuration dialog is shown below.

 

 

The TransForm FormDataView must be populated with both the form data to display and also the form definition for the form you are displaying. You can specify where this data should come from. The choices are

The TransForm FormDataView control exposes a number of methods. Information about these methods can be obtained by clicking the hyperlink in TransForm FormDataView configuration dialog (shown in the above image).

 

Web Applications - Xbasic and Javascript Editors - When editing Xbasic files (function libraries, modules, scripts) or Javascript files, the editor toolbar has a new button that opens a selector window allowing you to quickly switch between open editors, create a new file, or open an existing file, without having to first return to the Web Control Panel

Bugs

HTML Reports - Fixed an issue that prevented HTML reports from printing.

Internet Explorer - Fixed some issues with running components using IE.

Internet Explorer - Fixed issue with certain controls (such as date picker) not working when using IE

Web Applications - Style Builder - The Style Builder would give an error when trying to edit a style that was inherited from the 'Alpha' style (e.g. 'Alpha-Green')

UX Component - List Control - Condition Style - Logical Javascript expressions that used the || operator did not work. Logical Javascript expressions that used a property of a field (e.g. data.Country.length > 10) were being incorrectly flagged as invalid.

UX Components - List Controls - SQL Data Source - Fixes a problem that was introduced in build 5445 with paginated Lists based on SQL data sources

SSRS Reports - Fixes a problem with SSRS reports not rendering.

iOS Scrolling - Fixes a problem with scrolling on iOS devices.

 

Alpha Anywhere V4.5.4.6 - Build 5447-5206 08-NOV-2018

Hotfix - Web Style Builder - Editing an Inherited Style

Hotfix - Action Javascript - Menus - Menus with security settings

 

How to install a hotfix

Bugs

UX Components - List Controls - SQL Data Source - Fixes a problem that was introduced in build 5445 with paginated Lists based on SQL data sources

SSRS Reports - Fixes a problem with SSRS reports not rendering.

iOS Scrolling - Fixes a problem with scrolling on iOS devices.

 

Alpha Anywhere V4.5.4.6 - Build 5445-5205 07-NOV-2018

 

Videos

UX Component - List Control Consuming Complex (Hierarchical) JSON Data in a List The JSON data you display in a List control may contain nested arrays of data. In this video we show two different ways in which the nested arrays of data can be displayed.


Watch Video

Download files

Date added: 2018-07-30
UX Component Understanding the screen.height Property When setting the height of a container you cannot use percentages. However, you use the special screen.height variable to represent 100% of the available height.

In this video we show how a container's height can be set using the screen.height property.

Watch Video

Date added: 2018-07-30
UX Component Ad-hoc SQL Query Builder This video shows a sample UX component that allows users to perform ad hoc SQL Select queries against any table in a database. The results can be viewed in a tabular format or exported to Excel.

Watch Video

Date added: 2018-08-03
UX Component - ExpandingMenu Control Dynamically Populating an Expanding Menu with Ajax Callbacks This video shows how you can dynamically populate an Expanding Menu control with data computed in an Ajax callback.


Watch Video - Part 1
Watch Video - Part 2

Download files

Date added: 2018-08-09
UX Component Displaying an "Action Sheet" A common user-interface technique in iOS applications is an Action Sheet - a popup menu with a series of options. In this video we show how easy it is to add an Action Sheet style menu to a UX component.

Watch Video

Date added: 2018-08-29
UX Component - Advanced Search Control Using the AdvancedListSearch Control to Search in a List Based on SQL Database For UX Components that contain List controls that are based on SQL databases,  the Advanced Search control exposes powerful features for users to search for specific records in a List. The Advanced Search Control allows users to define complex queries and to save these queries to a repository for future reuse.

In this video we show how the Advanced Search Control is added to a UX component and how it is configured.

Watch Video - Part 1
Watch Video - Part 2

Date added: 2018-09-08
Grid Component - Advanced Search Control Adding an Advanced Search Control to a Grid Component The Advanced Search Control provides an alternative to the Grid Search Part for enabling users to search for data in a Grid. The Advanced Search Control has advantages over the Grid Search Part in that it allows the user to search on all of the fields in the Grid, not just the fields selected for the Search Part.

In this video we show how the Advanced Search Part is added to a Grid component and how it is configured.

P.S. You may find it  helpful to watch the videos for using the Advanced Search Control in a UX component before watching the videos on using the Advanced Search Control in a Grid.

Using the Advanced Search Control in a Grid
Watch Video - Part 1
Watch Video - Part 2

Using the Advanced Search Control in a UX Component
Watch Video - Part 1
Watch Video - Part 2

Date added: 2018-09-08
UX Component - Transient Messages Displaying Transient Messages A common design pattern in Web and Mobile application is to display "transient" messages to the user. The messages typically confirm that an action was done or display progress to the user. The GMail web application, and also the GMail mobile applications make extensive use of transient messages.

In this video we show how you can easily add transient messages to the UX component using Action Javascript (transient messages are also available in the Grid component).

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

Date added: 2018-09-21
UX Component - Kanban Layout Introduction to Kanban List Layouts Kanban Lists display data organized by category. Users can move List rows from one category to another using drag and drop. Users can also re-order the data within a category using drag and drop.

In this video we show a List control with both a columnar and a Kanban layout.

Watch Video
Download files

Date added: 2018-10-03
UX Component - Kanban Layout Creating a List with a Kanban Layout In this video we show how a Kanban layout can be defined for a List.

Watch Video - Part 1
Watch Video - Part 2

Download files

Date added: 2018-10-03
UX- Component - Kanban Layout Adding Color Coding and Summary Values to a Kanban Layout In this video we show some advanced features of a Kanban layout. We show how you can add color coding to the layout (so that List rows in different categories are colored differently and how you can summary data to each category.

Watch Video - Part 1
Watch Video - Part 2

Download files

Date added: 2018-10-03
UX Component Persisting Edit in a Kanban List to a SQL Database In this video we show how a Kanban List can be based on a SQL database and how edits to the List can be saved in the database.

Watch Video - Part 1
Watch Video - Part 2

Download files

Date added: 2018-10-03
UX Component - List Control Responsive Columns In this video we show how to make a responsive List control where columns in the List are automatically hidden when the List width falls below a specified value.

Watch Video

Download files

Date added: 2018-10-17
UX Component - List Control Horizontal Scrolling When a List has a large number of columns, you may prefer to enable horizontal scrolling for the List rather than trying to dynamically adjust the width of each List column so that all columns are visible.

Watch Video

Date added: 2018-10-17
AlphaDAO - Multi-tenant Applications How to Create a Multi-tenant Connection String When you build multi-tenant SASS applications that use a shared database, each table in the database must  have a tenant id field and all of your SQL queries must include the tenent Id. When you use a multi-tenant connection string, the tenant id is automatically injected into all SQL statements before the statement is sent to the database. This makes it easier to build multi-tenant SASS applications, or to convert an existing application to a multi-tenant application because you do not have to manually adjust all of your SQL statements.

In this video we show how a multi-tenant connection string is defined and then we show the results when a SQL SELECT and INSERT statement are executed.

Watch Video - Part1
Watch Video - Part2
Watch Video - Behind the scenes


Date added: 2018-10-21
UX Component Defining Manifest for On-Device Data When you build PhoneGap applications for offline usage, you may want to store files on a mobile device so that these files can be accessed when the device is offline. The UX builder has an action in Action Javascript that allows you to download all of the files defined in a 'manifest'. This video shows how this manifest can be created.

Watch Video - Part1
Watch Video - Part2

Date added: 2018-10-27
Xbasic Audit-trail Driver This video shows how you can create a custom AlphaDAO connection string to create an audit trail every time a CRUD operation is performed.


Watch Video - Part1
Watch Video - Part2

Date added: 2018-10-28
UX Component - List Control Page Navigation Bar In a Grid component you can add a Navigation Bar to allow the user to navigate from one 'page' or records to another. In a List control (that is based on a SQL database, has pagination tuned on and has the pagination method set to Navigation Buttons), you can also add a Navigation Bar to allow the user to navigate from one 'page' or records to another.

In this video we show how to configure a List control to display a Navigation Bar.

Watch Video

Date added: 2018-11-05
     



Breaking Changes

 

File/Image Upload - UX and Grid Component - A change was made to this action to disable the Upload button while the file upload is in progress. As a result of this change it may be necessary (in some cases it was not necessary - depends on when the Action was last edited) to edit and resave the file and image upload actions in Action Javascript in order to re-generate the Javascript code for the function.

Features

REST Services - Calling - Xbasic Proxy - REST services are called from Xbasic by making an HTTP request. Typically, HTTP requests are made from Xbasic using one of the built-in http functions (e.g. http_get(), http_post(), http_fetch(), etc.), or by using the Xbasic CURL object.

Now, a new way of calling REST APIs from Xbasic is available.

You can now create an Xbasic proxy class and then call methods on this proxy class. The methods on the Xbasic proxy class correspond to the various API endpoints exposed by the service.

In order to create the Xbasic proxy for the REST service, you can supply the Swagger definition for the service, or you can select one of the pre-configured Google services (of which there are many) or you can generate a definition from a CURL command.

The following example will make it easier to understand what an Xbasic REST proxy is. In this example we will:

 

1. Create the Xbasic Class with a Method Called getCustomer

 

define class reasapi::class1

    function getCustomer as p (customerid as c )

        dim cn as sql::Connection

        cn.open("::Name::northwind")

        dim args as sql::arguments

        args.add("id",customerid)

        dim sql as c

        sql = "select * from customers where customerid = :id"

        dim flag as l

        flag = cn.Execute(sql,args)

        dim json as c

        json = cn.ResultSet.tojson()

        getCustomer = json_parse(json)

    end function

end class

 

2. Create a REST Service to Expose the getCustomer Method

 

The REST API service is called myservice. To create a new REST service, select the Web Services category in the Web Control Panel , then click the New button and select Create a new definition to create a REST service button.

 

 

Next, get the Swagger definition for the service. Click the Swagger definition button at the bottom left of the API Service Builder dialog.

 

Copy the Swagger definition to the clipboard. You will need it for the next step when the Xbasic Proxy is created.

Also, click the Live Test the API button. This will publish the REST Service to the LivePreview folder in the webroot of the Development Server.

When you Live Test the API, the browser will open and show a page for testing the API. Make a note of the URL shown in the browser address bar - You will need this address when you define the Xbasic Proxy. The URL should look something like this:

 

http://127.0.0.1:10444/LivePreview/__a5_system/swagger/index.html?url=/livepreview/myservice.a5svc/api-docs

 

The parts of the URL that we care about are highlighted in red. Taking the parts that are highlighted, we can construct the URL for your web service:

http::localhost:10444/livepreview/myservice.a5svc

This is the URL where your Web Service has been published.

 

3. Make an Xbasic Proxy For This Service

To make an Xbasic Proxy for your web service, select the Web Services item in the Web Control Panel, then click the New button at top left of the Web Control Panel.

Select the Create a new definition to consume a REST service button.

 

 

This will then bring up a dialog where you can name your Xbasic proxy.

Enter any name you want (for example, myxbasicproxy1) and then click the Import Swagger... hyperlink.

 

A dialog will open where you can paste in the Swagger definition for your service. (Recall that in an earlier step where you defined the service, you clicked the Swagger definition button to see the definition for your service and you copied this definition to the clipboard).

 

 

Paste in the JSON for your Swagger definition and then click the OK button.

 

A new dialog will be shown where you can configure the Xbasic proxy.

The dialog has a prompt for the Resource URL. This is the address of the service your Xbasic proxy will be accessing.

Paste in the URL that you constructed in a previous step. It should look something like (your URL will be different if you are running the server on a different port, or you gave your service a different name).

http::localhost:10444/livepreview/myservice.a5svc

 

Click the Save button to save your Xbasic proxy.

 

4. Use the Xbasic Proxy to Call the Service Endpoint

Next we want to use this Xbasic proxy to call your service. We will use another Genie that helps construct the Xbasic code for using the proxy.

We will create an Xbasic script to test the Xbasic code that uses the Xbasic proxy. To create a new Xbasic Script, select the Xbasic category in the Web Control Panel, then click the New button.  Then click the Create a new Xbasic Script button.

 

An editor will open where you can enter Xbasic code to test.

Right click on white space in the editor and select REST Reference Call from the Genies.. menu item.

 

 

 

The next window shows all of the Xbasic REST proxies that you have defined as well as some built-in proxies. Select the Xbasic proxy that you defined. This proxy only has a single method (getCustomer), but if the service that you are proxying had more than one method, you would then select which method you wanted to call.

The bottom part of the dialog shows the Xbasic code to use the proxy.

 

 

Click the OK button to insert the code into your Xbasic Script. Before you can run the code you will need to specify which Customer's information you want to retrieve. Set the args.customerid variable to some value as shown below.

 

 

dim obj as RESTReferences::myxbasicproxy1
dim args as p
dim args.customerid as c = "Bolid"

dim result as l = obj.getCustomer(args)

if result then
showvar( obj.result )
else
ui_msg_box("error",obj.error)
end if
 

 

Now click the lightening bolt icon on the toolbar to run your code.

You should see a window pop up with the result of the API call.

 

 

 

UX Component - List Control - Conditional Row Style - Syntax - You can now specify that the logical expressions in a conditional row style definition should be Javascript, rather than an intermediate syntax that gets converted to Javascript.

 

 

UX Component - List Control - Fields - Conditional Style - Client-side - You can now define client-side conditional styles for fields in a List control. You can define a conditional style for the field itself and also for the cell in which the field is rendered (columnar layout only).

 

The image below shows a List with:

 

 

To define conditional field and cell styles, set the Conditional style and Conditional cell style properties in the List builder, Fields tab as shown in the image below.

 

 

To define a conditional row style, set the Client-side computation property in the Conditional Row Style section of the property grid on the List Properties pane.

 

 

Xbasic - FTP - FTP over SSL and FTP over SSH - Two new .Net classes have been exposed to allows FTP over SSL and FTP over SSH.

You can read more about these classes in the documentation.

FTP over SSL

FTP over SSH

 

 

UX Component - Button List Control - Select Button - You can now use the Enter or Spacebar key to select a button in a Button List. The button that has focus is selected.

NOTE: Some styles (such as 'Alpha' and styles inherited from 'Alpha') do not currently indicate which button in a Button List has focus.

 

UX Component - Action Javascript - Dropdown Menu Action - Window Size - When you use Action Javascript to define a dropdown menu you can now specify a height and width for the dropdown window.

 

 

 

UX Component - List Control - SQL Data Source - Paginated - Navigation Bar - You can now automatically add a Record Navigation Bar to List controls that are based on a SQL data source and have pagination turned on (with the Pagination method set to NavigationButtons).

Watch Video

 

The image below shows a List with a Navigation Bar. The Navigation bar has been configured to show an input control for the current page number. The user can enter a target page number into the input control and press Enter to navigate directly to the target page. The Navigation Bar also shows a 'records per page' selector so the user can dynamically change the number of records per page.

The number of target buttons before and after the current page number can be configured. In the image below, the Navigation Bar has been configured to show a total of 6 target buttons.

In the image below, the Navigation Bar does not show a 'records per page' selector. The current page number is shown using a disabled button (rather than an input control as shown in the above example) and there are no target buttons before or after the current page number.

Also, the Navigation Bar has been configured to display in the List itself (in the List Footer section). In the above example, the Navigation Bar display outside the List at a location specified by a placeholder DIV in the UX component.

 

 

If you are using a 'version 4' style (e.g. 'Alpha', or any style inherited from 'Alpha', such as 'Alpha-Rose') you can choose a compact style for the Navigation Bar buttons, as shown in the image below.

 

 

To turn on the Navigation Bar, check the Has Navigation Bar property in the List Builder on the Data Source pane.

 

To configure the Navigation Bar, click the Navigation Bar settings smart field.

This will open the builder where you can set properties for the Navigation Bar.

 

 

 

UX Component - List Control - SQL Data Source - Server-side Column Sorting - You can now turn on server-side column sorting for all of the columns in List by checking the new Server-side sorting property. Previously, you had to go to each column in the List layout to turn on server-side column sorting for that particular column.

 

 

 

 

Web Control Panel - Xbasic Scripts - You can now create Xbasic Scripts from the Web Control Panel. The sole purpose of Xbasic Scripts is to allow you to develop and test Xbasic code from within the Alpha Anywhere IDE. Xbasic scripts are not published when you publish your application and are not intended to be used at run-time.

To create a new Xbasic Script, select the Xbasic category in the Web Control Panel, then click the New button.

Click the Create a new Xbasic Script button.

Enter the code you want to test and then click the lightening bolt on the toolbar to execute the code.

 

 

Xbasic - word_unique_c() function - A case-sensitive variant of the word_unique() function is now available.

Example

dim txt as c

txt = comma_to_clf("NO,no,NO")

?word_unique_c(txt,crlf())

= NO

no

 

Web Applications - Stylesheets - Alpha Theme - The Alpha style sheet has been enhanced. New sub-themes are available for buttons, button lists, and lists.

Many of the sub-themes can use a 'pulse' effect (inspired by Google Material Design). The pulse effect can be turned on/off using the Show 'pulse' effect property.

 

 

The list of available sub-themes for a button is shown below:

 

 

The image below shows the appearance for some of the new button sub-themes.

 

 

The 'pulse' effect is available for ButtonList, Switch and List controls.

For the 'Alpha' style you can turn the 'pulse' effect on or off by setting the Show 'pulse' effect property.

TIP: You can turn the 'pulse' effect on for just a portion of a component by enclosing that portion in a container and setting the container class to 'pulse'.

 

 

 

AlphaDAO - Custom Connection String - Audit Trail Driver - A new sample driver is available when you create a new connection string and select the Custom option. This driver automatically updates an audit table when CRUD operations are executed.

NOTE: Contrast the Audit-trail driver with the built-in Audit Trail feature which is turned on by going to the Web Project Settings dialog. The built-in feature does not require a special connection string, can automatically create the audit-trail table and is therefore easier to set up. The image below shows the relevant section of the Project Properties dialog where you can turn on the built-in audit trail feature.



 

A sample Xbasic class that implements an audit-trail driver can be selected when you define a Custom connection string.

The Audit driver is a "pass-through" driver (i.e. SQL commands are passed through to the base SQL connection) but a new record is added to the audit table for each successfully executed CRUD statement.

Watch Video - Part1
Watch Video - Part2

 

When you create an audit driver you must specify these properties in the connection string definition dialog:

 

 

The audit table must have this structure (the actual field names can be different as the connection string builder allows you to map the actual field names) :

 

PhoneGap and TransForm Applications - On-Device-Data Genie - When you build TransForm applications, or regular Alpha Anywhere mobile applications (that use PhoneGap), you may want to store data (SQLite databases, images, movies, audio files, PDF files, etc.) on the mobile device so that the files can be accessed when there is no internet connection.

Watch Video - Part1
Watch Video - Part2

 

In Alpha Anywhere applications you can use Action Javascript / PhoneGap Manifest actions to define an action that downloads all of the files specified in a special manifest.

In TransForm applications you can go to TransForm Central to specify the manifest URL for On-device-data (Note: This feature may not yet be turned on for your TransForm account at this time).

The new On-Device-Data Builder makes it easy to define the manifest and to upload the manifest files to an Amazon S3 bucket from where they can be downloaded to a mobile device.

To open the On-Device-Data Builder select the Tools/More.../On-device-data builder for TransForm/PhoneGap applications... menu item.

 

 

This will then open the builder, as shown in the image below.

 

 

The builder allows you to specify the data (i.e. files) you want to store on the mobile device. The builder allows you to define multiple item types of data.  The available types are:

For each item, you can also specify an optional version number. This is used by the Javascript method that downloads the manifest files to the device to determine if a file specified in the manifest must be downloaded. If a file has been previously downloaded it will not be downloaded again if its version number does not exceed the previous version number.

 

After you have defined all of the items in your manifest, you can save your definition by clicking the Save button. The settings are saved in a file in the Web Projects folder. You can then click the Generate manifest files button. This button will create the SQLite database files (if you specified that the SQLite database file should be created by executing queries) and it will create the necessary zip files (for example, for the Folder item type, all of the specified files are zipped into a single zip file).

Once the manifest files have been created, you can then upload them to Amazon S3. Click the Upload manifest files to S3 button to upload the manifest files. A manifest file will also be created and uploaded to S3. The manifest is a JSON file that describes each file in the manifest. The URL for this manifest file is used in your Action Javascript when you define an action to Fetch manifest files. For TransForm users, the URL for this manifest must be specified when you define the on device data for your account in TransForm Central.

After the manifest files are uploaded you can click the Show manifest URL/JSON to see the manifest URL and the actual JSON data in the manifest.

Before you can upload manifest files to S3 you must first click the Define S3 Properties hyperlink to define properties of the S3 bucket where your manifest files will be uploaded. You must specify the storage connection string that points to your S3 bucket (go to Tools, Storage connection strings when the Web Control Panel has focus) and the folder within this bucker where the manifest files should be uploaded.

 

 

List Control - Right Click - If you right-click on a row in a List, the List's onRightClick event is fired, but the system right click menu is not shown. Now if you add code in the List's onRightClick event that does this:

return true

the system right-click menu will be shown.

UX Component - E-mail Address - Client-side validation - You can now perform a client-side validation of an email address. To do so, add the following code to the input control's Validation Javascript property:

 

var flag = A5.emailValid(data);

if(flag) {return true;} else {return 'Not valid email';}

 

NOTE: Validation is performed using the RFC 2822 standard regex expression.

 

Thanks to Max Hammond for this suggestion.

 

UX Component - Pre-render - File Size - The file size of pre-rendered components (the .a5wcmp file) has been substantially reduced. This is achieved by storing the pre-rendered component definition as base64 encoded, gzipped data.

 

UX Component - Edit-Combo - Open List on Focus - You can now configure an edit-combo to open the pick-list when the control gets focus. Previously the user had to tap the icon to open the pick-list.

 

 

 

iPhoneX PhoneGap Styling - One-click Styling - Styling a PhoneGap app for an iPhoneX device can be tricky because special consideration has to be given to the notch and the soft home button. Apple has introduced special directives that can be used in your CSS classes to automatically account for the notch on the device.

Alpha Anywhere now makes it very easy to apply all of the necessary CSS to a mobile app so that it will render correctly on all iPhones, including iPhoneX.

In order to configure your PhoneGap app so that it will display correctly on an iPhoneX device check the Apply iPhoneX PhoneGap styling property.

NOTE: If you check this property, your app will still display correctly on other iPhone devices.

 

 

You can then set additional properties for your app.

 

 

AlphaDAO - Multi-Tenant Driver - SASS Applications - You can now create a new type of connection string for multi-tenant applications.

Watch Video - Part1
Watch Video - Part2
Watch Video - Behind the scenes
 

When you create a multi-tenant SASS application (using any development platform, not specifically Alpha Anywhere), you can either give each tenant their own database, or you can use a shared database for all tenants.

Giving each tenant their own database will work well if you do not have a large number of tenants. However, if your application has a large number of tenants, the only practical approach is to have a single database for the application that all tenants share.

If you use a shared database, you will need to have a 'tenant id' field in each table so that the records in the table can be associated with the correct tenant. Every time your code executes a SQL CRUD statement, you will need to remember to include the tenant id field in the SQL statement.

The Multi-tenant driver is used in cases where you have a shared database for all of the tenants. The multi-tenant driver will automatically inject the tenant id field into the SQL so you do not have to remember to do it.

For example, assume you have defined a multi-tenant driver with these properties

 

 

Now, assume you execute the following SQL query:

SELECT * from Employees

 

The SQL statement that will be sent to the database will actually be (assuming that the value of session.mytenantid is 23) :

SELECT * from Employees WHERE tenantId = 23

 

In the case of an INSERT statement, the tenant Id will automatically be set to the value of the current tenant

For example,  your SQL statement:

INSERT into Employees (firstname, lastname) values (:fname, :lname)

 

will automatically be converted to:

INSERT into Employees (firstname, lastname, tenantid) values (:fname, :lname, 23)

 

If there are some tables in your multi-tenant SASS application that are shared by all tenants (i.e. the tables do not have a tenant ID field), then when you query these tables you will not use the multi-tenant connection string. Instead you will use the base connection string.

 

How to Create a Multi-tenant Connection String

 To create a Multi-tenant connection string, create a new connection string (from the Tools, AlphaDAO Connection Strings menu) and then when the Create SQL Connection String dialog appears, click the button for the Connection Type prompt

 

 

The Select an API dialog will appear. You can either select the MultiTenant option, or the Custom option. Select the Custom option if you want to customize the Xbasic class that implements the Multi-tenant driver.

 

 

If you select the MultiTenant option, the next dialog allows you to set the properties for your multi-tenant connection string.

 

The properties you must set are:

 

If you select the Custom option, you will get this dialog where you must specify the name of the Xbasic class that implements the custom driver. Click the Show Example.. hyperlink to get an example Xbasic class that implements a multi-tenant driver.

 

 

 

 

Then select the Xbasic class that you created from the examples and fill in the property sheet, as shown below.

 

 

UX Component - PhoneGap - You can now open the PhoneGap builder and build an Instant Update directly from the UX Builder toolbar. You no longer have to return the Web Control Panel.

 

UX Component - PhoneGap - Instant Update - AjaxURL - If you change the AjaxURL when you do an Instant Update, the next time you do an Instant Update, the URL that you set is now remembered.

 

Web Applications - Styles - 17 new styles are now available. All of these new styles are inherited from the base Alpha style. Because they are inherited styles, changes to the base Alpha style (such as the addition of new CSS classes and sub-themes) will be seen in each of these inherited styles.

 

 

UX Component - List Control - Horizontal Scrolling - By default, in a columnar List, the column widths for each column in the List are automatically adjusted so that all columns are visible. Column widths are automatically adjusted if a column specifies its width using the flex() option.

Watch Video

 

If a List has many columns, the adjusted width of each column might render the List in such a way that the data is not readable. For example see the image below:

 

If you enable horizontal scrolling, the column widths will not scale down below the specified minimum column width, and the List will scroll horizontally. See image below.

 

 

To enable horizontal scrolling, check the Horizontal scrolling property on the List Properties pane in the List. When you check this property you can specify the minimum and maximum column width. These settings are automatically applied to all List columns that use the flex() option (as long as the width settings does not specifically set a minimum or maximum width). For example, if a particular column sets its width to (say) flex(1,250px), then that column's width will not use the Minimum column width property (i.e. the minimum width for that column will be 250px regardless of the Minimum column width property value).

 

 

 

 

UX Component - List Control - Column Width - Flex - Minimum and Maximum Width - The width of each column in a List can be configured to adjust automatically based on the overall width of the List. This is done by setting the column width using the flex() syntax.

Now when you use the flex() syntax to specify a column width you can specify an optional minimum width and maximum width for the column. For example:

flex(1,150px) - the column width is 1 flex unit, but never less than 150px

flex(1,150px,300px) - the column width is 1 flex unit, but never less than 150px or more than 300px.

 

UX Component - List Control - Client-side Group Breaks/Kanban Lists - Collapsible - Expand/collapse using Javascript - If you have a Kanban List, or a List with client-side group breaks turned on and you have set a group break to be collapsible, you can now expand/collapse a group using Javascript.

 

Example:

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

var groupName = 'Argentina';

var mode = false //false == expand, true == collapse, '' == toggle

var showAnimation = true;

lObj.setGroupCollapse(groupName,mode,showAnimation)

 

 

UX Component - List Control - onResize Event - List controls now support an onResize event. This event fires when the List is resized. For example, if the List is inside a Panel Card and the List is set to fill the container, when the Panel Card is resized, the List's onResize event will fire.

 

UX Component - List Control - Responsive Columns - You can now show/hide columns in a columnar List layout based on the overall width of the List. For each column in the List you can specify a Responsive column property. This is a value in pixels. If a column's Responsive column setting is less than the List's width, the column will be hidden. If the List width is greater than the specified value, the column is shown.

Watch Video

The computation that determines which columns should be show/hidden is made when the List's onResize event.

The List onResize event will fire automatically if the List is inside a Panel Card and the List is set to fill the container. The event will fire when the Panel Card size changes.

 

 

 

AlphaDAO - Connection String Builder - SQL Server - Changes to the SQL Server connection string dialog and to the SQL Server connection string:
 
The connection string dialog now uses tabs to provide more options.

  1. The AdditionalParameters and InitialCommand connection properties are now fully supported in the connection string dialog.
  2. A new connection property TrustServerCertificate is now supported at connection and the dialog level for SQL Server.  This parameter can be set to true to allow a self-signed certificate to be used on SQL Server for testing.  The default value is false.
  3. A new connection property EnableColumnEncryption is now supported at the connection and the dialog level for SQL Server.  This parameter enables Always Encrypted for the connection.  The default value is false.
     

If TrustServerCertificate or EnableColumnEncryption is set to true in the dialog (the box is checked) and included in AdditionalParameters as well, the dialog value will supersede the hand coded value.


 

AlphaDAO - PostgresSQL - New PostgreSQL ODBC Driver (10.3) - The PostgreSQL ODBC client shipped with Alpha Anywhere and installed in SQLDatabases\ClientInstallers\PostgreSQL under the binary directory as psqlodbc_x86.msi has now been upgraded to version 10.3.
 
 

UX Component - List Control - Kanban Layout - Dynamically Adding Categories - You can add categories to a Kanban layout after it has been rendered using this Javascript:

 

var layoutName = 'Default'; //name of the Kanban layout

var newCategory = 'New Category';

var lObj = {dialog.object}.getControl('name_of_list_control');
lObj.layouts[layoutName].group.auto[0].groups.push(newCategory);

lObj.refresh()

 

UX Component - List Control - Client-side Group Breaks - Collapsible Groups - When defining a List control that has client-side group breaks, you can now specify that each group is collapsible. If you turn this feature on, the Group Header row will have an icon at the extreme right edge. If you tap the icon, the group is shown as collapsed (as shown in the image below for the group for Austria). Tapping on the icon for a collapsed group will expand the group.

The collapse/expand of each group is animated.

You can define event handlers for when the collapse or expand of a group has completed.

You can customize the icons used to collapse or expand a group.

 

 

UX Component - List Control - Kanban Layout - Collapsible Categories - When defining a Kanban layout, you can now specify that a category should be collapsible. When a category is collapsed, only the category header is shown. As a result, the category will be narrower and more categories can be rendered on each 'row' of categories.

 

 

 

Grid Component - Javascript Actions Editor - Easier Access - It is now easier to get to the Javascript Action editor. Simply click on the Javascript Actions item in the navigation tree at the left of the Grid builder.

 

 

UX Component - List Control - Kanban Layout - You can now configure List controls to display the List data in a Kanban layout.

A Kanban layout is useful if you have List data that can be grouped in categories and you want to be able to drag and drop a row from one category to another, or drag and drop a row with a category to change its order within the category.

Example of the types of data where a Kanban view could be useful include:

 

 

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

 

 

In the image below, a Kanban layout is shown for sales pipeline data.

A List can have multiple Layouts. Any of the layout can be a Kanban layout. You can switch at any time from one layout (which might be columnar or freeform) to a Kanban layout.

 

 

 

In the image shown above each category has a group footer in which the total for the amount field in that category is shown. The user can click on the hamburger icon and drag the row to a new position within the category, or to a different category.

It is common that when you move a row, you will want to persist the data to a backend database. This is easily done by turning on the List's Detail View property and then putting a button on the UX to synchronize the List data.

To create a Kanban layout, set the Layout type to Kanban.

To configure the Kanban settings click the smart field for the Kanban settings property. This will open the Kanban Layout Setup Genie.

 

 

Properties of note in this dialog include:

Once you have defined the Kanban Layout properties, you will need to define the Kanban Layout. Defining the Kanban Layout is very similar to defining a Layout for a freeform List.

In the screenshot below the layout for the Kanban layout shown above is defined. The layout is an HTML template with placeholders for the data in each List row.

The {kanban:draghandle} placeholder is a special placeholder for the drag handle icon that displays in each row.

Note that the background color in the outer div has been set to: {@[scope].kanbancolor([root])}. This is the client-side templating syntax for calling a Javascript function. The value returned by the function will be used for the background color. See the documentation for client-side templating for more information on how to call Javascript functions in a template. Note that kanbancolor() is a special system generated function that will execute the code you defined in the Color Javascript property when you set the Kanban layout properties.

Note also that the list of placeholder at the left edge of the screen include the  {kanban:draghandle} placeholder.

 

 

 

When you are defining a new Kanban layout template, you can get a quick start by clicking on the Pre-defined Templates hyperlink. This will bring up a dialog (shown below) where you can select different sample layout templates.

 

 

 

 

If the data in the List are based on a SQL database, then it is likely that you will want to save the changes you make to the List back to the SQL database. For example, when you move a row to a new position within a category, or you move a row to a different category, you may want to update the underlying SQL database. This is easily accomplished. First, turn on the List's Detail View by setting the Has Detail View property.  If you want to edit the data in the List while you are offline, turn on the Persist data to Local Storage property.

 

 

You do not need to actually define a Detail View for the List. Simply turning on the Detail View property is sufficient.

Next, add a button to the UX to synchronize the List data. Your button should execute this code:

 

 {dialog.object}.saveListEdits('name_of_your_list_control',{rows: 'allRows', ajax: { timeOut: 15000, onAjaxFail: function() { } , onDeviceOffline: function() { } } });

 

TIP You can add the synchronize button to your UX by selecting the [List-Detail View-Buttons] item in the Defined Controls section of the UX builder. The advantage of adding the button using this technique is that Alpha Anywhere will add an appropriate Enable expression to the button so that it is only enabled if the List has edits that have not been synchronized.



 

 

 

Grid Component - Server-side Events - CanAjaxCallback and AfterAjaxCallback - The Grid component now supports two new server-side events

The CanAjaxCallback event can be used to authorize an Ajax callback. The AfterAjaxCallback event can be used to modify the Ajax response that is set to the client.

 

 

UX Component - Lists - Client-side Group Breaks - Multiple Layouts - If you define a List control with multiple Layouts, you can now define client-side group breaks for each Layout.

The property sheet for each Layout has a new property, Group breaks definition that can be set to <Use Default>, Custom-for this Layout, or None.

If you select <Use Default>, the client-side group breaks defined on the List Properties pane will be used.

 

TransForm - Reports - You can now use TransForm as a data source for reports.

The data in a TransForm form can be quite complex. For example, you may have multiple one-to-many relationships in the data (these are nested arrays in the JSON data) and each child may in turn have its own children (i.e. parent-child-grandchild relationships).

Data in this form is not suitable for the report writer, which needs a "flat" table of records. Therefore, when the data are retrieved from a TransForm form, it is "flattened" (search in documentation for json_flatten() for a description of what "flattening" means)

When you create a new report, the menu now shows <TransForm> as an option.

 

If you select the <TransForm> option, a dialog where you can configure the data source is shown:

 

 

Properties of note in the dialog include

 

You can filter on meta data fields. The meta data fields are different than the actual form data. The meta data fields include the id of the person who submitted the form, the form status, the timestamp (time on the server when the form was submitted) and the Forminstanceid (the primary key for the form instance)

You can filter on the following meta data fields

For the Person, Status and FormInstanceId properties, you can enter a comma delimited list of values, or you can use arguments. For example, you might set the Person filter to: :name_of_person

You can also filter and sort on the actual data in the form.

 

Field Data Type Overrides

By default, all data that is retrieved from TransForm is character data. You might want to explicitly change certain fields to be other types so that the report writer can do calculations and summaries with the data. For example, the form might have a field called Quantity which you would like to convert to a numeric field. The Overrides property allows you to set data type overrides.

Photo fields are an exception. Alpha Anywhere automatically sets photo fields to Image File Reference fields (so that the report writer will recognize these fields as images). You do not need to define overrides for photo fields.

You will need to define overrides for signature fields (use the Ink data type).

 

Web Applications Security - Export/Import Group Names - When you are setting up security for a Web application you can now export groups or import groups. The data interchange format is JSON.

 

 

UX and Grid Components - Transient Messages - A new action is available in Action Javascript to display transient messages.

A transient message is a message that is displayed for a short time and then automatically hidden (unless the user dismisses the message early, by clicking a close button).

Transient messages are used extensively by Google in their applications (for example in the GMail web and mobile applications). In the two images below, the transient messages in the Gmail web and mobile application are shown.

 

Transient Message in the GMail Web Application

 

Transient Message in the GMail iOS Application

 

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

 

To create a Transient Message in the UX or Grid, define a new Action using Action Javascript and select the Message box - Transient action

 

The builder is then shown:

 

 

 

 

Properties that can be set in the builder include:

 

A transient message can have the following positions:

 

The images below show a transient messages in the UX component using the Google and Default appearance:

Transient message using the Default Appearance (the component style is Alpha)

 

Same as above message, but using the Google Appearance

 

The minimum amount of Javascript to display a transient message (using the Default Appearance) is shown below:

{dialog.object}.transientMessage('center','Record was deleted.',

    {
        buttons: [{html: 'Undo', onClick: function(){alert('undo')}}]
    }

)

 

UX Component - List Control - Client-Side Grouping - Default Groups - By default, the group breaks shown in a List when client-side grouping is turned on, are dynamically computed from the actual data in the List. However, you might want certain groups to appear in the List regardless of whether the List contains any data for that group. You can now specify a list of default groups that should always appear in the List.

In the image shown below, default groups for the Country group have been defined. These default groups are 'South Africa' and 'Zimbabwe'.

 

 

The image shown below shows how a List that does not have any data for either South Africa or Zimbabwe would be rendered. Notice that the actual HTML shown for these two empty groups is defined by the Javascript specified in the Javascript for HTML for default group property.

 

 

 

 

 

 

 

UX Component - List and ViewBox Controls - .focus() Method - These controls now have a .focus() method to set focus to the control.

Example

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

lObj.focus()

 


Xbasic - JSON_flatten_default() Function - Takes JSON with nested arrays and "flattens" the JSON so that there are no nested array. This is same as the JSON_flatten() function, but the template required by the JSON_flatten() function is automatically generated from the input JSON.

 

Syntax

C jsonOut = json_flatten_default(c JsonIn)

 

Example:

dim json as c 
json = <<%str%
[
	{"name": "John", "Lastname" : "Smith", "City" : "Boston", "State" : "MA", "Children": [
		{"Name" : "Callie", "Age" : 5},
		{"Name" : "Griffin", "Age" :3},
		{"Name" : "Luke", "Age" : 1}
		]
	}, 
	{"name": "Henry", "Lastname" : "Rhodes", "City" : "New York", "State" : "NY", "Children": [
		{"Name" : "Howard", "Age" : 15},
		{"Name" : "Robert", "Age" : 11}
		]
	}, 
	{"name": "Allison", "Lastname" : "Berman", "City" : "Los Angeles", "State" : "CA", "Children": [
		{"Name" : "Jeff", "Age" : 35},
		{"Name" : "Roxanne", "Age" :33},
		{"Name" : "Claudia", "Age" : 31},
		{"Name" : "Denzel", "Age" : 11}
		]
	}
]		
%str%
dim json2 as c
json2 = json_flatten_default(json)
?json2

= [
{"name": "John","Lastname": "Smith","City": "Boston","State": "MA","Children_Name": "Callie","Children_Age": 5},
{"name": "John","Lastname": "Smith","City": "Boston","State": "MA","Children_Name": "Griffin","Children_Age": 3},
{"name": "John","Lastname": "Smith","City": "Boston","State": "MA","Children_Name": "Luke","Children_Age": 1},
{"name": "Henry","Lastname": "Rhodes","City": "New York","State": "NY","Children_Name": "Howard","Children_Age": 15},
{"name": "Henry","Lastname": "Rhodes","City": "New York","State": "NY","Children_Name": "Robert","Children_Age": 11},
{"name": "Allison","Lastname": "Berman","City": "Los Angeles","State": "CA","Children_Name": "Jeff","Children_Age": 35},
{"name": "Allison","Lastname": "Berman","City": "Los Angeles","State": "CA","Children_Name": "Roxanne","Children_Age": 33},
{"name": "Allison","Lastname": "Berman","City": "Los Angeles","State": "CA","Children_Name": "Claudia","Children_Age": 31},
{"name": "Allison","Lastname": "Berman","City": "Los Angeles","State": "CA","Children_Name": "Denzel","Children_Age": 11}
]

Notice that each parent record is repeated for each record in the nested array.

 

Xbasic - JSON_flatten_single() Function - Takes JSON with nested arrays and "flattens" the JSON so that there are no nested array. Data from the nested arrays is represented in the parent data as a set of repeating fields.

 

Syntax

C jsonOut = json_flatten_single(c JsonIn[, depth])

 

Where

The function will only operate on one level of nested arrays. For example if a row in a nested array has another nested array, this array will be ignored.

 

Example:

dim json as c 
json = <<%str%
[
	{"name": "John", "Lastname" : "Smith", "City" : "Boston", "State" : "MA", "Children": [
			{"Name" : "Callie", "Age" : 5},
			{"Name" : "Griffin", "Age" :3},
			{"Name" : "Luke", "Age" : 1}
		]
	}, 
	{"name": "Henry", "Lastname" : "Rhodes", "City" : "New York", "State" : "NY", "Children": [
			{"Name" : "Howard", "Age" : 15},
			{"Name" : "Robert", "Age" : 11}
		]
	}, 
	{"name": "Allison", "Lastname" : "Berman", "City" : "Los Angeles", "State" : "CA", "Children": [
			{"Name" : "Jeff", "Age" : 35},
			{"Name" : "Roxanne", "Age" :33},
			{"Name" : "Claudia", "Age" : 31},
			{"Name" : "Denzel", "Age" : 11}
		]
	}
]		
%str%
dim json2 as c
json2 = json_flatten_single(json)
?json2

= [
{"name": "John","Lastname": "Smith","City": "Boston","State": "MA","Children_1_Name": "Callie","Children_1_Age": 5,"Children_2_Name": "Griffin","Children_2_Age": 3,"Children_3_Name": "Luke","Children_3_Age": 1},
{"name": "Henry","Lastname": "Rhodes","City": "New York","State": "NY","Children_1_Name": "Howard","Children_1_Age": 15,"Children_2_Name": "Robert","Children_2_Age": 11},
{"name": "Allison","Lastname": "Berman","City": "Los Angeles","State": "CA","Children_1_Name": "Jeff","Children_1_Age": 35,"Children_2_Name": "Roxanne","Children_2_Age": 33,"Children_3_Name": "Claudia","Children_3_Age": 31,"Children_4_Name": "Denzel","Children_4_Age": 11}
]

Notice that data from the nested arrays is represented in the parent record as a set of repeating fields. For example, Children_1_Name, Children_2_Name, etc.

 

WCF and SOAP Services - Xbasic - IMPORTANT! – If you are creating and using Web References or generating Web Service Clients in Alpha Anywhere to use with WCF or SOAP services, please test the generation and execution of your service client under the most recent pre-release. We have made changes to accommodate some web services, and want to be sure that no one is adversely affected by these changes before we release the next version of Alpha Anywhere.

 

Grid Component - Textbox - Readonly  - Textbox controls in the Grid and Detail View parts now have a readonly property.

 

UX and Grid Components - Advanced Search - A new option has been added to both Grid and UX components.

The Advanced Search feature can be used to search for records in a Grid component, or for records in a List control in a UX component. The List control must be based on a SQL database.

 

Using the Advanced Search Control in a UX Component

Watch Video - Part 1
Watch Video - Part 2

Using the Advanced Search Control in a Grid Component

Watch Video - Part 1
Watch Video - Part 2

 

 

When you define a Grid component with a Search Part, you (the developer), pick the fields that you want the user to be able to search in at run-time. Similarly with defining a search feature for a List control.

With the Advanced Search control, however, you let the user pick the fields that they want to search in (the fields from which the user is allowed to pick is controlled by you - the developer).

The searches that are entered into the Advanced Search feature can be saved and then later retrieved.

The controls that the Advanced Search feature can display are:

 

When the Grid or UX is initially displayed, the Advanced Search control is rendered as follows:

 

 

If the Allow Saved Query Load option is enabled, the Advanced Search control is rendered as follows:

 

 

NOTE: All text in the buttons shown in the Advanced Search control, and the icons are fully customizable. You can also use language tags or text dictionary tags to translate strings into other languages.

 

To start defining a new search, the user will click the Add new search field button. This will display a drop down menu of the fields from which the user can select. This list of fields (and the corresponding control type to use for the field) is defined when the Advanced Search is configured.

For example:

 

The user will select one of the available fields and a new search control is added to the screen.

At this point, the Advanced Search control will look like this:

 

(In this example, the City field was defined as a combolist list control, so it has a button to open a picklist of choices. In addition, since the Save query button is shown if the Allow save query option is enabled.)

 

 

The user can continue adding as many additional search fields as needed. When a second or subsequent search field is added, the Advanced Search control shows AND/OR buttons for each search field (except the last selected field). This allows you to specify if the search items are joined with an AND operator or an OR operator. In the example shown below, the search is for City = 'London' OR Country = 'France'.

 

 

Each new item added to the Advanced Search control will have these two icons:

The trash can icon is used to delete the item from the Advanced Search control.

The funnel icon is used to set search options for the field. When the user taps this icon, a menu with these options is shown:

 

For Date and Time fields (Time is actually a Date-time field), an additional button (with 3 vertical dots) is shown.  This is the date menu button.

 

When the user clicks the date menu button, a menu of pre-defined date ranges is shown. For a datepicker control, the choices in the menu are:

For a daterangepicker control, the choices in the menu are:

 

 

 

When the user clicks on the Calendar icon for a daterangepicker control, the dropdown window shows two calendars so the user can select the start date and the end date for the date range.

 

 

The menu options determine the type of search that is performed. For example, say you have added an item to the Advanced Search control to search in the LastName field and you have entered JO into the input control. If you set the menu to Starts with then records where Lastname is Jones or Johnson will be selected.

The QBF Syntax allows the user to use the standard QBF syntax supported by Grid and UX searches. This syntax is summarized below:

The QBF Syntax allows you to enter multiple search commands, separated by comma. For example

2018/9/1..2018/9/15,2017/9/1..2017/9/15

will find records where the search field value is between September 1 and September 15 in either 2017 or 2018.

 

 

Adding an Advanced Search Control to a Grid Component

To add an Advanced Search control to a Grid component, go to the Grid Properties pane in the Grid Builder and check the Has 'Advanced Search' feature property. This will then show the Advanced Search definition property. Click the smart field for this property to open the dialog where you can configure the control. (See below for details).

 

NOTE: If it possible, although unusual, to have both a standard Search Part in the Grid and also turn on the  Advanced Search feature.

 

 

 

Adding an Advanced Search Control to a List Component

You can add the Advanced Search control to a UX by selecting the [More..] item in the Data Controls section.

 

 

Then select AdvancedListSearch from the dialog.

 

 

This will add an AdvancedListSearch control to the List. You can configure the control by clicking the smart field for the Control properties property. This will open a dialog where you can configure the Advanced Search control. (See below for details).

 

 

 

 

NOTES:

 

 

Configuring the Advanced Search Control

 

The configuration dialog for the Advanced Search control in a Grid is shown below. The left hand list shows the fields that the user can select from when adding a new field to the search at run-time. You can add new fields to this list by clicking on the Add new search field... button. The Property Grid control on the right shows the properties for the selected item in the list on the left.

 

 

 

When you click on the the Add Field button a dialog is shown that allows you to pick one of the available fields in the Grid or the List control.

For each field you select, you must also select the corresponding control type for that field.

For example, if you pick a logical field, you will likely want to select the switch control for that field. On the other hand, say you pick a field called Lastname, you might want to select the suggest control for that field. This will display an auto-suggest list as the user starts typing values into the search field.

 

 

 

 

You can customize all of the icons and prompts shown in the Auto Suggest control. To do so, click the Customize Buttons and Strings for the Advanced Search Control button. This will display the dialog shown below. You can use language and text dictionary tags in the strings (e.g. <a5:r>...</a5:r> or <a5:t>..</a5:t> )

 

 

You can customize certain aspects of the Advanced Search control by clicking the Customize Search Options button.

This will display the dialog shown below:

 

 

You can enable/disable the ability to save and load previously defined advance searches. You can also specify if debugging information should be shown. If you turn on debugging information, the WHERE clause computed from the search definition is shown, as well as the argument values for the arguments referenced in the WHERE clause.

If you turn on debugging information, you must specify where this information should be shown. In the case of a UX component, place a Placeholder control on the UX. The dialog will prompt for the name of the placeholder.

In the case of a Grid component, specify the id of a DIV control where you want the debugging information to appear. You must add the appropriate DIV to your component. A convenient place to add this DIV is in the Before HTML property, in the Additional Customization Options dialog (see below).

 

For example, in the image above, the DIV for the debugging information is specified as:

{grid.componentname}.SEARCHDEBUGGING

 

NOTE: By including the {grid.componentname} placeholder in the DIV id, we ensure that there will not be any conflict with the ID should more than one instance of this Grid be displayed at the same time.

The Unique key property is show if either the load or save query options is enabled. This property is added to the name of the saved query in the Repository table where queries are saved (see below for more information on Loading and Saving queries). This property allows you to ensure that when you click the Load Query button, only saved queries that match the Unique key are shown.

 

In the case of the Grid component, the configuration dialog displays an additional button with customization options specific to the Grid component. When you click the Additional Customization Options button the following dialog is shown.

 

 

 

In the case of the UX component, the builder will display a prompt where you can set the name of the List that the Advanced Search will operate on.

 

 

 

Loading and Saving Queries

In order to save queries you must define a Repository table in the Project Properties dialog. To open the Project Properties dialog, click the Project Properties button in the Web Control Panel.

 

 

You can define the connection string to the database where the Repository table will be stored. You can link to an existing table or create a new table. Click the smart field for any of the properties to open a builder.

 

 

Configuring the Grid to Show Debugging Information

When you run a query in the Advanced Search control you can display the WHERE clause that Alpha Anywhere computed from your query definition.

To turn on debugging information check the Display debugging information property when the Customize Search Options dialog is shown.

In the case of the UX you can specify a Placeholder control where the debugging information will be shown. In the case of the Grid component you specify the ID of a DIV element. You must manually add this DIV to the component. For example, say you specify the ID or the DIV as {grid.componentname}.ADVANCEDSEARCHDEBUGINFO then you would need to add the following HTML markup to your Grid component:

<div id="{grid.componentname}.SEARCHDEBUGGING"></div>

This markup can be added in several possible places. For example in a Freeform Edit Region, in the HTML that displays above or below the Advanced Search control (see the  Additional Customization Options button on the configuration dialog ) , etc.

 

 

 

Property Grid - International Characters in Strings - The Property Grid will now display international characters, rather than the HTML encoded strings. For Example:

 

All Components - Property Grid - Right Click Menu - The Property Grid right-click menu (shown when you right-click on the left hand border bar in the Property Grid) now has additional options. Most useful is the Find option that allows you to search for a property in the Property Grid.

 

 

UX Component - List Controls - Open UX as an alternate editing view for current record - You can now use this action in Action Scripting to edit the currently selected row in a List control in another UX component.

 

 

Xbasic - Read data from the Extended User-Information Table - a5w_getExtendedUserInfo() Function - Reads data from the Extended User-Information table.

Syntax

p Result = a5w_getExtendedUserInfo(userid as c )

Where

 

Example

dim p as p

p = a5w_getExtendedUserInfo('john.smith@acme.com')

?p.error

= .f.

?p.json = <<%txt%

{

    "FIRSTNAME" : "John",

    "LASTNAME" : "Smith",

    "COMPANY" : "Acme Corp"

}

 

 

Xbasic - Save data to the Extended User-Information Table - a5w_saveToExtenedUserInfo() Function - Saves data to the Extended User-Information Table. If a record for the specified userid does not exist, a new record is created. If a record already exist, the existing record is updated.

Syntax

p Result =  a5w_saveToExtendedUserInfo(c userId,c json)

Where


Example:

dim json as c

json = <<%txt%

{

    "FIRSTNAME" : "John",

    "LASTNAME" : "Smith",

    "COMPANY" : "Acme Corp"

}

%txt%

dim p as p

p = a5w_savetoExtendedUserInfo("john.smith@acme.com",json)

 

 

Xbasic - Get Fields in Extended User-Information Table - a5wcb_extendedUserInfoTableFields() - Returns a list of fields in the Extended User-Information Table.

Syntax

c Fields = a5wcb_extendedUserInfoTableFields()

 

UX Sample Component - Editing Data in the Extended User-Information Table - A sample template component is available to edit data in the Extended User-Information Table for the currently logged in user.

When you create a new UX component, select the SecurityFramework-Edit_ExtendedUserInformation template.

The template automatically generates a form based on the fields you have defined in the Extended User-Information table for your web project.

 

UX and Grid Components - Security Framework - Arguments - When you define Arguments for a UX or Grid component, you can now bind an argument to the the id of the currently logged in user, or to the security groups of the currently logged in user.

If you have defined an Extended User Information Table, (see below for more information), you can also bind the argument to any value from the  Extended User Information Table.

In the case where you bind an argument to the security groups for the logged in user, you can define an array argument. A user can be a member of multiple groups. By defining an array argument (the argument name must start with ARRAY_) you can use the argument in a SQL IN clause. For example

select * from tasklist where group IN (:ARRAY_USERSECURITYGROUPS)

 

NOTE: If you are using Active Directory, or IIS (with the Alpha Anywhere plugin), the Security Groups are the actual names of the security groups. In the case of the classic Alpha Anywhere server, the security groups are the GUIDS for each group.

To specify that an argument gets its value from the currently logged in user, set the Get argument value from property to Get value for current logged in user. Then set the Value property.

 

 

When you click the smart field for the Value property you will get a dialog allowing you to select which attribute of the currently logged in user you wish to set the argument to.

If you have defined an  Extended User Information Table, for the current project, the pick list includes fields in the  Extended User Information Table.

 

 

Example

Filtering records in a Grid to only show records that are assigned to the currently logged in user.

Assume that the table that the Grid is based on has a field called userid. The Grid should only show the records where the value in the userid field matches the userid of the currently logged in user.

Click the Define Arguments button to define an argument and bind that argument to the userid for the currently logged in user.

Define a filter for the Grid (assume that the argument you defined was called ARGUMENT_USERID).

userid = :ARGUMENT_USERID

 

 

 

 

UX and Grid Components - Security Framework - Arguments - Xbasic - You can now set an argument to the result of an Xbasic function.

When the component is initially rendered and the argument values are set, the Xbasic function will be called and the argument's value will be set to the value returned by the Xbasic function.

To specify that an argument gets set by an Xbasic function, set the Get argument value from property to Xbasic, and then specify the name of the Xbasic function to call. The Xbasic function can be defined in the component, or in a linked Xbasic Function Library.

 

 

Security Framework - Extended User Information Table - When you use the Security Framework in an Alpha Anywhere application, the table that contains the list of users and their passwords (or password hashes) is a system table and you cannot modify its structure to add additional fields to store additional information about each user.

In order to store additional information about each user in your system it is necessary to create another table in a SQL database. This table is called the Extended User Information Table. It can have any structure that you like, but it must have a primary key field that contains the user id of the user. This field should be indexed.

To create the Extended User Information Table open the Web Security dialog by clicking the Web Security button on the Web Projects Control Panel. Then launch the Security Settings dialog and click the Extended user-info table hyperlink at the bottom of the dialog.

 

 

This will bring up a dialog that will allow you to specify an existing table, or create a new table in the target SQL database.

 

 

 

 

If the user logs in from a UX or Tabbed UI (i.e. not the Login component), a client-side Javascript object will be created with values for each of the fields in the Extended User Information Table.
This object is called A5.extendedUserInformation 

 

TIP If your Extended User Information Table has a specially named field called ActiveLanguage then the value in this field can be used to set the active language for the app. Normally the active language is set by specifying the language in the session.__protected__activeLanguage variable.

 

UX Component - Action Sheets - A common user interface design in iOS mobile applications is the Action Sheet. An action sheet is a series of menu options that animates into display from the bottom of the screen. The menu can be divided into logical sections, as shown in the image below.


 

 

 

The {dialog.object}.actionSheet() method is used to display an Action Sheet. This syntax for this method is:

 

{dialog.object}.actionSheet(menu [, width]);

 

Where:

 

 

Example:

The following Javascript produces the Action Sheet shown in the image above

			
var menu = [
	[
		{html: 'This is the help text above the Action Sheet. It does not have an action'},
		{html: 'Save', action: function(){alert('save')} },
		{html: 'Save As...', action: function(){alert('saveas')} }
	],
	[
		{html: 'New', action: function(){alert('new')}},
		{html: 'Open...', action: function(){alert('open')}}
	],
	[
		{html: 'Cancel', action: function(){alert('cancel')}}
	]
]

;
{dialog.object}.actionSheet(menu);
			
			

UX Component - Action Javascript - Action Sheets - A new action in Action Javascript allows you to create Action Sheets.

 

 

Grid and UX Component - Dropdown Messages - Action Javascript - A new action in Action Javascript makes it easy to create Dropdown Messages. The Message box - DropDown Style action can be selected.

 

 

Grid and UX Component - Dropdown Messages - A new Javascript method has been added to both the Grid and UX component to make it easy to display dropdown messages.

Three styles of dropdown message are available:

 

'Wait' Style Dropdown Message

 

'Confirm' Style Dropdown Message

 

'Message' Style Dropdown Message

 

 

 

 

Syntax

{dialog.object}.dropDownMessage(type,title,body,width,okButtonLabel,cancelButtonLabel,onOK,onCancel,location,animationStyle)

{grid.object}.dropDownMessage(type,title,body,width,okButtonLabel,cancelButtonLabel,onOK,onCancel,location,animationStyle)

 

Where

 

 

 

 

Example:

var dropDownType = 'confirm';

var title = 'Message Title';

var msgBody = 'Message body text';

var width = '400px';

var oKButtonLabel = 'OK';

var cancelButtonLabel = 'Cancel';

var onOK = function() { alert('pressed ok'); };

var onCancel = function() { };

{grid.object}.dropDownMessage(dropDownType,title,msgBody,width,oKButtonLabel,cancelButtonLabel,onOK,onCancel);
 

 

Property Grid Control - The Property Grid control is ubiquitous throughout the Alpha Anywhere IDE. It is used extensively in the UX and Grid builder, and in the List, ViewBox, FormView, ControlBar etc. builders in the UX builder. Previously, the Property Grid control was based on a 3rd party ActiveX control licensed from CodeJock. Unfortunately, this CodeJock control had a resource leak that resulted in the Alpha Anywhere IDE having to be shut down and restarted after extended periods of use. While a later version of the CodeJock control has addressed this issue, we were not able to switch to this newer version as it introduced other issues.

Therefore, Alpha has built its own Property Grid control. The benefits of the Alpha Property Grid control are:

If you come across any issues with the new Property Grid control, you can revert to the old CodeJock control by executing this Xbasic command from the Interactive window:

a5.System_Mode_set("new_propgrid","off")

 

UX Component - Expanding Menu - Dynamically Populating - Ajax - Two new helper functions have been added that make it easy to dynamically populate an Expanding Menu control with data computed in an Ajax callback.

 

Watch Video - Part 1
Watch Video - Part 2

 

Download files

 

 

Xbasic - A5_sqlToJSONExpandingMenu() Function - A new helper function has been added to generate the JSON needed to populate an Expanding Menu control in a UX component from data returned by a SQL query.

Syntax

c JSON = a5_sqlToJSONExpandingMenu(C connectionString ,C table ,C fieldList [,C endPointFieldName [,C filter [,C order [,P argsIn [,C endpointfunctionname ]]]]])

 

Where:

 

Watch Video - Part 1
Watch Video - Part 2

 

Download files

 

Example:

 

dim cs as c = "::name::AADemo-Northwind"

dim table as c = "customers"

dim fieldlist as c = "country,city,contactname"

dim endpointfield as c = "customerId"

dim filter as c = "country <> ''"

dim order as c = "country"

dim endpointfunctionname as c = "selectCustomer"

dim json as c

json = a5_sqlToJSONExpandingMenu(cs,table,fieldlist,endpointfield,filter,order,null_value(),endpointfunctionname)

'now use this JSON to generate the Javascript to populate an Expanding Menu control on a UX component

 

dim js as c

js = "var data = " + json + ";" + crlf()

js = js + <<%str%

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

obj.data.items = data.items

obj.data.actions = data.actions

obj.refresh()

%str%

 

 

Xbasic - a5wcb_convertFriendlyMenuToExpandingMenuJSONData() Function - A new helper function has been added to generate the JSON needed to populate an Expanding Menu control from a menu definition that uses a CRLF list of menu entries, with tab indentation to indicate menu hierarchy.

The menu definition allows you to assign a optional server-side show/hide expression and/or a set of security groups to any menu branch or leaf item. The JSON that is generated will honor the server-side show/hide expressions and security groups. For example, if a menu branch should only be available to someone who is a member of the Administrators group, the generated JSON will not include that branch if the currently logged in user is not in the Administrators group.

The example below shows a "friendly" menu definition

Alpha

    Alpha1

    Alpha2

        Alpha21

        Alpha22

Beta

    Beta1

Gamma

    Gamma1

Each item in the menu can be followed by an optional JSON definition. This JSON definition can have these properties (all of which are optional)

The above "friendly" menu definition shown using the optional JSON settings string for some of the menu items:

Alpha{serverSideShowHideExpn: 'session.var1 = "alpha"'}

    Alpha1

    Alpha2

        Alpha21{securityGroups: 'Administrator,Sales'}

        Alpha22

Beta

    Beta1

Gamma{icon: 'svgIcon=#alpha-icon-bandAidCrossed:icon,24'}

    Gamma1

 

 

 

Syntax

C json =  a5wcb_convertFriendlyMenuToExpandingMenuJSONData(C menu )
 

Where:

 

TabbedUI Component - Expanding Menus - TabbedUI Component - You can now use Expanding Menus to render Tree Controls in the TabbedUI Menu. This allows for a more modern look for your TabbedUI components.

NOTE Expanding Menus are a standard UX control type. To add an Expanding Menu to a UX component, go to the Data Controls section in the UX toolbox and select [More...].

In the two images below, a TabbedUI is rendered with a Tree Control in the first image and an Expanding Menu in the second image. Notice that when the Expanding Menu is used, various parts of the TabbedUI (e.g. the Menu header, the Tab bar, etc.) inherit the color used for the Expanding Menu.

 

 

 

 

To render a Tree container as an Expanding Menu, check the Display as Expanding Menu property in the Tree Control Begin Properties section.

 

 

 

 

When you render a Tree Control as an Expanding Menu you can set the Menu prefix icon for tree branches. This is an icon that will display to the left of the branch text.

 

 

In the image below a tree branch is shown with an icon prefix.

 

 

When you use Expanding Menus in a TabbedUI you will generally want to set the colors of various TabbedUI parts to match the menu color of the Expanding Menu. This is easily done by clicking on the smart field for the CSS to customize TabbedUI appearance property.

 

 

 

When this dialog opens, click the Set all TabbedUI part background colors to match the Expanding Menu color property. This will match the color in the first Expanding Menu control in the TabbedUI. (A TabbedUI might have multiple Expanding Menu controls, each of which may have a different menu color.)

NOTE: If you do not check the box to set the color of various TabbedUI parts to match the Expanding menu color (or if your TabbedUI does not have any Expanding Menu controls), this dialog also allows you to tweak the appearance of different parts of the TabbedUI by defining a set of custom CSS classes that are applied to different TabbedUI parts.

 

 

TabbedUI Component - Customizing Appearance - By modifying the style sheet used for a TabbedUI you can customize the appearance of the TabbedUI component. However, as an alternative to editing the style sheet, you can define custom CSS classes that get applied to various parts of the TabbedUI.

The parts of the TabbedUI interface that you can modify with your own custom CSS classes are:

To define the CSS classes to modify the appearance of these TabbedUI parts, click the smart field for the CSS to customize TabbedUI appearance property in the CSS/SVG section in the property sheet.

 

 

This will open a dialog where you can specify the CSS classes you want to define to customize the various TabbedUI parts.

NOTE The custom CSS classes you define are applied in addition to the built-in CSS classes for the various TabbedUI parts. For example, if you are using the MobBlue style sheet, the CSS class applied to the Menu Panel Header is MobBlueGridHeader. If you define a custom CSS class (called (say) MenuPanelHeader) the CSS classes applied to the Menu Panel Header will be MobBlueGridHeader  and MenuPanelHeader.

 

TabbedUI - Tab Pane Buttons - You can now customize the appearance of individual tab pane buttons (these are the buttons that appear in the tab band after you open a component by clicking on a button in the TabbedUI menu area).

NOTE Previously, you could only customize the appearance of all of the tab pane buttons, but not individual tab pane buttons. To customize the appearance of all tab pane buttons, set the Tab button off and Tab button on properties in the Class names section of the TabbedUI property sheet.

To customize the appearance of a particular tab pane button, select the TabbedUI button in the property sheet and then set the Tab class name and Tab selected class name properties in the Tab CSS section.

 

 

 

 

UX Component - Methods - .setCSS() method - The {dialog.object}.setCSS() method allows you to dynamically add CSS classes at run-time.

 

Syntax:

id = {dialog.Object}.setCSS(css [,id])

 

Where:

If you do not pass in an id a new DOM 'style' node is created. The method returns the id of the node that was created. You can use this id to update the CSS.

 

Example:

var css = '.css1 {color:red;} .css2 {color:blue;}';

var id = {dialog.object}.setCSS(css)l

//now update the definition<br>
css = '.css1 {color:blue;}';

{dialog.object}.setCSS(css,id);


 

Xbasic - showvarhtml() Function - Display Formatted HTML - The showvarhtml() function can be used to display a string of HTML text. The HTML is formatted for readability before it is displayed.

TIP: Contrast with the a5_show_htmlchrome() function which shows the rendered HTML (as opposed to the HTML source).

 

UX Component - List Control - Columnar Layout - Columns - Sort - Initial Sort Direction - When you define the sort action for a column in a List control you can now set the initial sort direction. If the column is unsorted when the user clicks on the column heading the Initial sort direction is defined by the Initial sort direction property.

NOTE: The Grid component as a similar capability to set the initial sort direction.

To set the initial sort direction, set the Initial sort direction property in the List Builder for the selected column.

 

UX Component - Sample Template - Ad-hoc SQL Query Builder - A new sample template is now available when you build a new UX component. The purpose of the component is to allow a user to perform arbitrary queries against any table in a database and then export the data to Excel.

Watch Video

 

The image below shows the component when it is running. As the image shows the user can

 

Once the user execute the query focus is automatically given to the Results pane (second image) which shows the query results.

The use can choose to

 

In order to save and load queries you must configure a Repository table. This is done by going to the Project Properties dialog when the Web Control Panel has focus and setting properties for Repository Settings.

The list of connection strings that the user can select from is controlled by the choices you define for the ConnectionString dropdown box control on the UX.

 

 

 

 

 

UX Component - Containers - Height - Screen.Height - When setting the height of a container control on a UX you cannot use percentages. For example, you cannot set the height of a container to 100%. (You CAN set the width to 100%). Now you can use a special variable screen.height when setting a container's height property.

NOTE: You cannot use screen.height when defining the in-line style for the container. You can only use screen.height in the Height property.

 

Watch Video

 

You can define arithmetic expressions using screen.height.

For example, to set a container's height to half of the screen height set the Height property to

screen.height/2

 

To set a container's height to 50px less than the screen height:

screen.height - 50

 

NOTE: Numeric constants in an expression are always pixels.

 

NOTE: If you use an Alignment container and you set the Container vertical alignment property to Middle and you do NOT set the container height property, Alpha Anywhere will automatically set the container height property to screen.height.

 

UX Component - List Control - Detail View - Synchronization Log Table - When you edit a List control in the List Control Builder, when you save your edits, if your List is configured with an updateable Detail View and you do not have the 'server-side synchronization log table' feature turned on, a warning dialog is now displayed recommending that you turn this feature on.

If you have not configured the synchronization log table (normally done by opening the Project Properties dialog), the warning dialog will automatically configure the synchronization log table if you turn on the synchronization log feature.

 

UX Component - List Control - Detail View - .saveListEdits() Method - The .saveListEdits() method is used to synchronize edits made to the List. The method can now take additional optional properties to specify:

These additional properties are passed in the optional settings object  that the .saveListEdits() method takes.

 

Syntax:

{dialog.object}.saveListEdits('listName',

{

    rows: 'all' or 'current',

    ajax: {

        timeOut: 15000,

        onAjaxFail: function() { } ,

        onDeviceOffline: function() { }

        }

}

);

 

UX Component - PhoneGap Applications - Downloading Files to a Device - A new action has been added to Action Javascript that makes it easy to download multiple files (including SQLite database files) to a device so that these files can be accessed while the application is offline.

 

To select the action choose PhoneGap - Manifest from the list of available actions.

 

 

 

 

 

 

HTML Reporting - Window Toolbar - Close Button - When you use Action Javascript to define an action that prints a report as HTML you can define buttons that appear in the toolbar of the window in which the report is shown. In some cases, developers will choose to turn off the display of the window title bar in order to create a nicer looking window. However, if you turn off the title bar, there is no way to close the window. There a new option is available to add a close button to the window toolbar.

 

To select this option uncheck the option to show the window title and then set the Has window close button property

 

 

Here is how the window toolbar will appear:

 

Bugs

Application Server for IIS - Under certain conditions the Application Server for IIS would crash.

UX and Grid Component - Date Picker - Two Digit Years - Regardless of the date template that has been defined, when the user enters a date with a two digit year, the year is now correctly interpreted.

UX Component - List Control - Soft Delete - If a List with Detail View was configured to do "soft deletes" and the List was based on a SQL query that joined two or more tables, the soft delete field was not being qualified with a table alias in the SQL statment that retrieved the data for the List.

API Creator - Authorization - Passing Parameters in Request Header - Fixed an issue where argument could not be passed to the authorization method in the request header.

Xbasic - AlphaDAO - toJSON() Method - Fixed a bug that caused an unhandled exception when calling SQL::Query::Resultset.toJSON() if a query included a row with an invalid Geometry Well Known Text value.

UX Component - Hyperlink - Click Event - Disable - If you used client-side enable expressions to disable a hyperlink, the Click event would still fire even though the hyperlink should have been disabled.

UX Component - Textbox Control - Client-side Formatting - If a textbox control had client-side formatting defined, when you tabbed into the control, all of the text in the control was not selected.

UX Component - List Control - Reports - Fixed an issue with the currentListFilter() function.

Geocode_address() Function - Was not passing in the API Key value correctly

UX Component - Web Sockets - Fixed an issue where the WebSockets code was not getting published when a web project that used WebSockets was published. As a result, the components that used Web Sockets would not work. 

SQLite Database - Indexes - When you create a SQLite database, Alpha Anywhere allows you to define indexes for the SQLite database. If a table was based on a custom SQL statement, the Index Builder genie did not show you the fields in the SQL query.

Application Server - Security Framework - Active Directory - IIS - A regression was introduced in the last release build in Application Server for IIS where groups are not found for a user. This leads to users not being authorized to access pages after the user has successfully logged in.

This problem occurs when the users and groups are in separate branches of the Active Directory hierarchy. Given this example Active Directory structure:

Company (OU)
    Employees (OU)
        Location1 (OU)
        Location2 (OU)
            Users (OU)
                User1 (User)
                User2 (User)
                User3 (User)
    Security Groups (OU)
        Applications (OU)
            Manufacturing (OU)
               Administrators (Group)
               Assemblers (Group)
               Foreman (Group)
		

the problem would occur when using the Users OU to authenticate users and the Manufacturing OU for groups. This is now fixed.

 

Action Javascript - Email a Report - Fixed an issue when the Internal option was selected to email the report. (The Mandrill and Sparkpost options did not have any issues).

Web Applications - Security Framework - Active Directory - Fixed an issue where you would occasionally get an error message stating:

 

Cannot access a disposed object.

 

UX Ccomponent - Semi-circular Number Display - Dynamic Color - The dynamic color option was broken as a result of an upgrade to a new version of the RGraph open source Javascript library bundled with Alpha Anywhere

 

Alpha Anywhere V4.5.4.5 - Build 5221-5152 23-JUL-2018

 

 

Features

Web Control Panel - F2 Key - The F2 key now acts as a shortcut for the Rename command, available on the right-click menu.

 

UX Component - Action Javascript - Try/Catch Blocks - You can now wrap individual actions and the entire action in a Javascript try/catch block. To wrap an action in a try/catch block, right-click on the action and select the Wrap action in try/catch block  command. This will open an editor where you can define the code to run in the catch block. If an action is configured to use a try/catch block, the menu item will be checked.

 

 

An action can comprise several individual actions. You can also wrap the entire action in a try/catch block by checking the appropriate checkbox at the bottom of the dialog.

 

Custom APIs - Swagger Test Page - When you create a custom API using Alpha Anywhere's API creation facility, you might want to create an .a5w page where users can explore your API and test it out. In order to create an API testing page, click the New button on the Web Control Panel while the Web Components category has focus.

Then select the Swagger API Test Page option.

When your users visit this page in your published application they will be able to explore the methods exposed by your API.

 

 

 

 

UX Component - Javascript Charts - X-Axis Label Angle - You can now specify the angle for the x-axis labels. In the example below, the xaxisTextAngle property has been set to 45.

TIP When you set the xaxisTextAngle property, you may also need to set the gutterBottom property to ensure that the labels are not clipped.

 

 

 

 

UX Component - Expanding Menu - Above Menu and Below Menu HTML - You can now specify arbitrary HTML to display above and below an Expanding menu control.

 

 

 

UX Component - Summary of all defined event handlers - A new item on the Menu dropdown in the UX builder allows you to get a summary of all of the events that have been defined in the UX. This can be very helpful in a large UX with many controls because it allows you to quickly get a comprehensive view of all of the event handlers that have been defined.

To display the summary, click the Menu button and then select the Show summary of all Javascript code for event handlers menu item.

 

 

 

This will display a windows showing all of the controls on which event handlers have been defined.

 

 

 

UX Component - Action Javascript - Run a Report that is Embedded in a UX Component using a Custom Filter Action - This action now allows you to define a custom sort order in addition to the custom filter.

 

 

 

 

UX Component - PhoneGap - Offline Applications - Loading Files onto a Device - When you design an App for offline use, you may want to install files (including images, videos and SQLite databases) on the device so that these files can be accessed by your App even when there is no connection.

There are already ways in which you can load SQLite databases onto a device (using Action Javascript) and also use the client-side data cache to store data on the device, but now a new method ( {dialog.object}.phoneGapDownloadManifestFiles() ) allows you to define an arbitrary list of files that you want to install on a device.

The  {dialog.object}.phoneGapDownloadManifestFiles() method take a manifest that defines the files you want to install on the device. The manifest can either be a JSON string that specifies an array of objects (described below), or the URL of remote JSON file that specifies the manifest.

Syntax

{dialog.object}.phoneGapDownloadManifestFiles(manifest,folder,cbAllDone,optionsIn,fileSystemPart)

 

Where

Syntax for the optional optionsIn argument
 

{
    showProgress: true,
    progress: {
        color: 'green',
        width: '600px',
        progressElement: '{dialog.componentname}.V.R1.PLACEHOLDER_1'
}

 

Example

 


var cb = function(arr) { alert('File have been installed - ' + arr.length);};
 

 

//the manifest is an array of objects

//each object must have a 'url' - the url of the file

//each object must have a 'type'. types are: 'sqlite', 'folder' or 'file'.

//for 'folder' the entire folder must be zipped into a single zip file. The 'targetFolder' specifies the sub-folder

//within the target folder where the folder (containing all of the unzipped files) will be located

//for 'file', the file must not be zipped.

//for 'sqlite', the file can be zipped, or unzipped. (zipped is recommended)


array  = [
        {
            url: 'http://alphamediacapture.s3.amazonaws.com/transform/SQLiteNorthwind.zip',
            type: 'sqlite',

            version: 1
        },
        {
            url: 'http://alphamediacapture.s3.amazonaws.com/transform/sqlite3.db',
            type: 'sqlite',

            version: 1
        },
        {
            url: 'http://alphamediacapture.s3.amazonaws.com/transform/allimages.zip',
            type: 'folder',
            targetFolder: 'images',

            version: 1


        },

        {
            url: 'http://alphamediacapture.s3.amazonaws.com/transform/customer.zip',
            type: 'file',
            targetFolder: 'files',

            version: 1


        }


    ]
 

var url = 'http://alphamediacapture.s3.amazonaws.com/transform/transformManifest.json';

 

//can either specify a url that points to a manifest or the JSON manifest itself

url = array;
{dialog.object}.phoneGapDownloadManifestFiles(url,'account1',cb,opsIn)

 

 

UX Component - PhoneGap - Unzip Files - A new helper function has been added to the Alpha Anywhere Javascript library that makes it easier to work with the PhoneGap plugin that allows you to unzip files.

The function allows you to specify the file system part and folder where the source zip file located, the file system part where you want the unzipped files to be placed and optionally can call the onSuccess callback function with an array showing the files that were unzipped.

Syntax:

 

{dialog.object}.phoneGapUnzipFiles(explicitFilenameURI,filesystemSource,folderSource,zipFileName,fileSystemTarget, dirStructureTarget,onSuccess,onError,flagListUnzippedFiles)

 

Where

 

 

Web Components - Modal Windows - Tab and Sift Tab Key - You can no longer tab out of a modal window using the Tab or Shift+Tab keys.

 

UX Component - Container - Constrain Tabbing - You can now set a constraint on a container to prevent the user from tabbing out of the container using either the Tab or Shift+Tab keys. You can set the Constrain tab key property to:

 

 

TIP: Using this feature you can constrain controls in a Panel Card by wrapping all of the controls in a container.

 

PhoneGap Builder - 3rd Party Plugins - Cordova Custom URL Scheme Plugin - Added support for the Cordova Custom URL Scheme plugin. This plugin allows you to register a custom URL scheme that can be used as a link to launch your app.

When you select the Cordova Custom URL Scheme Plugin a dialog will appear to allow you to enter your custom URL scheme when you save the PhoneGap project.





The link can be added to an email, a web page or another app. As long as the app is installed on the device and the link is triggered from an email, web page or app that is being viewed or used on the device, then your app will load. You can also pass in parameters that can be used for deep linking, redirecting the app to a specific page within your app. You can also pass Base64 encoded JSON as a parameter for further processing within your app.

The plugin supports an optional handleOpenURL(url) method, that receives the URL and any parameters that were used to launch your app. This allows you to define a custom handler that can act on the path and parameters as required.

See the plugin documentation for further details and examples. cordova-plugin-customurlscheme

 

PhoneGap - Instant Update - Channels - By default, when you publish an Instant Update to your PhoneGap application, all of the users of your app will get the update as soon as they launch the app on their devices (assuming the app was designed with auto update turned on).

However, you may want to push an update to just of few users, perhaps because you are still testing a new feature. This can easily be done by specifying a channel when you publish an Instant Update.

You will need to add a user interface to your app so that a user can select what channel they are on. By default, all users are on the Production channel. But a user may change their channel to (say) the Test channel. The Javascript command that you can use to allow a user to set their channel is:
{dialog.object}.setChannel(channelName)

When you publish an Instant Update, you specify for which channel the update is intended. For example, if you publish an Instant Update to the Test channel then a user who is on the default Production channel will not get an update when they re-launch the app on their device. However, a user who has changed their channel to the Test channel will get updated when they re-launch the app. If that user later changes their channel back to the Production channel, then when that user re-launches the app, they will be automatically switched to the latest Production version.

 

 

 

Template Tester - A completely redesigned version of the Template Tester is now available. The main advantage of this new version is that all of the various editing panels (i.e. JSON data, template, css, javascript) are resizeable and can also be collapsed. Previously, each of these editing panels was on a separate tab. The new tester is more convenient to use. If you prefer the old version of the template tester you can revert to it by going to the View, Settings menu and navigating to the Preferences, TemplateTester section.

 

Bugs

Web Applications - Session Variables - Fixed a regression that was introduced in Version 4.5.4.1 enumerating session variables.

UX Components - Panel Cards - Fixed a regression that was introduced in the previous release.

 

 

 

 

Alpha Anywhere V4.5.4.4 - Build 5159-5132 22-JUN-2018

 

Bugs

 

UX Components - Panel Cards - Fixed a regression that was introduced in the previous release.

Starting Alpha Anywhere with Command Line Arguments - Fixed a regression that was introduced in the previous release.
 

 

Alpha Anywhere V4.5.4.2 - Build 5155-5130 20-JUN-2018

Bugs

Launching Alpha Anwhere from a Shortcut - A regression was introduced i the last release that broke the ability to launch Allpha Anywhere and open a named work space using a shortcut.

Application Server for IIS - Grid Component - Fixed a regression that was introduced in the last update. Grid would fail on any Ajax callback.

PhoneGap - Fixes a problem when generating an app with custom icon and splash screen.

 

Alpha Anywhere V4.5.4.1 - Build 5151-5127 18-JUN-2018

 

Videos

UX Component Cascading DropdownBoxes Using the Client-side Data Cache Cascading dropdown boxes allow you to dynamically change the choices in a child dropdown box based on the selection in the parent dropdownbox. The UX component makes it very easy to define cascading dropdownboxes. However, in applications that are designed to work offline, you cannot use the standard way of creating cascading dropdownboxes because if you are offline you cannot make the Ajax callback to populate the child dropdownboxes when the parent dropdownbox value is changed. However, you can still implement cascading dropdown boxes in offline applications by populating the dropdownboxes from data in the client-side data cache.

In this video we show how data in the client-side data cache is used to create cascading dropdownboxes.

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

Download files

Date added: 2018-04-30
UX Component - Map Control Computing Distance and Travel Time Between Points A common requirement in mapping applications is to compute a route (showing driving directions, distance and travel time) between points.

In this video we show how a route, defined by addresses in a List control is used to compute driving directions, distance and travel times between points on the route. The code is all generated automatically by Action Javascript.


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

Download files

Date added: 2018-04-30
SOAP Services Using the Sample WCF Service You can easily consume SOAP services from your Xbasic code. But it can be difficult to find publicly available SOAP services to test your code with. Using the sample WCF SOAP service that ships with Alpha Anywhere, you can easily create test code that shows how to consume methods in a SOAP service.

In this video we show how the sample WCF service can be used.

Watch Video

Date added: 2018-05-06
UX Component - List Control Running Totals This video shows how you can compute a column of running totals.

Watch Video

Download files

Date added: 2018-05-31
UX Component - ExpandingMenu Control Collapsing Menu When Selecting an Action When you select the action on a leaf node in an Expanding Menu control, you might want to collapse the menu so that some or all of the expanded nodes are collapsed.

In this video we show how an expanded node in an Expanding Menu control can be collapsed.

Watch Video

Download files

Date added: 2018-06-02

 

 


 




 

 

Features

Alpha Launch - New Version -  A new version (version 2.1.1) of Alpha Launch is now available in both the iOS and Android stores. With version 2.1.1, installing apps onto the device is now significantly quicker if the apps are published to Alpha Launch using the singleWithHeader option in the Download type property. With this option, all of the files that need to be installed on the device are combined into a single file which is then downloaded to the device and then unpacked on the device. It is considerably quicker to download a single large file than hundreds of smaller files.

 

Web Applications - Reload Security Information - Reload the security data for the current application - When you change the security information for an application (for example, change whether a page requires login, and if so, what groups are authorized) and you republish the application to a remote server, the new security information is not loaded immediately. It is only loaded when the security information cache is cleared (the duration of this cache is set in the Security Settings for the project). For more information on the security cache click here.

 

The a5ws_ReloadWebSecurity() function will force an immediate reload of the web security settings for the current application on a standard web server, regardless of the security cache timeout setting. The function must be run on a web page or component running on the web server. It does not reload security on an IIS server. This can be used on a maintenance page to force a reload of security after publish

The function will return .T. if successful, and .F. if running on IIS, running in Live Preview, or running in Working Preview

Syntax:

L flag = a5ws_ReloadWebSecurity( )
 

Xbasic - Using the Stripe API From Xbasic - A new genie, accessed from the right-click menu when you are editing Xbasic code, opens a genie that shows sample code for making calls to the Stripe API

 

The image below shows how the Stripe genie is accessed from the Genies... menu on the right click menu.

 

 

When you select the Stripe genie.. command the dialog shown below is shown.  The genie shows sample Xbasic code for the vast majority of the features exposed by the Stripe API.

 

 

 

Web Applications - Publishing Fonts - In some cases the server on which your application is running may not have installed a font used in one of your reports.

You can now click on the More... button on the Web Projects Control Panel and select the Create 'Fonts' folder menu command to create a folder called fonts in your Web Project. Any fonts you place in this folder will be automatically installed on the server when you print a report. This feature is especially useful on Alpha Cloud where you do not have the ability to specify what fonts each server has installed.

 

 

UX Components - Color Palettes - If a UX component uses a version 4 type style (the Alpha style is the only style currently that is a version 4 style), a new property is available in the UX builder to select a color palette.

 

 

 

Selecting a color palette is very similar to using the Customize style colors and fonts property, except that the color palette applies only to the current UX component, whereas if you use the Customize style colors and fonts property, the settings apply to every UX component in the current Web Project that uses the selected style.

 

 

When you click the smart field for the Color palette prompt the dialog that is displayed allows you to select an existing color palette, or create a new, user-defined, color palette.

 

 

When you preview a color palette or create a new color palette you will see a dialog like the one shown in the image below. This dialog allows you to set a color for each of the available color types.

 

 

 

Audit Table Feature - User Defined Field - You can now add a user defined field to the audit table to capture any additional information that you want at the time the audit table is updated. If you set the value in a special session variable called session.__audit_userfield1, the value in this variable will be written to the user defined field when the audit table is updated. If you want to store a significant amount of information in this field, consider creating a string of JSON data. The JSON data can have a large number of properties.

 

Xbasic - ShowDiff() function - The ShowDiff() function shows you a windows with the differences between data in two variables or files.

You can either choose a light theme or a dark theme (second image).

You can use the Previous and Next buttons to move from one difference to the next.

Use the black square icon on the right to change the theme.

Syntax

V =  showdiff(c varOrFile1, c varOrFile2)

 

Where

NOTE: ShowDiff() Function cannot be used in Web Application

 

 

 

Xbasic - geocode_address() Function - Now allows you to pass in an API key. If you are using Google to Geo-code addresses, Google is introducing rate limiting to the geo-coding API. You can now pass in your API key when you call this function. You can also define a project wide API key in Project Properties

 

Xbasic - SQL_Query() Function - Returns JSON data from a SQL Select statement - This function is a convenience function. It is just a wrapper around the low level Xbasic AlphaDAO commands.

 

Syntax

 

p Result = sql_query(a cnIn, c sql [, sql::arguments argsIn [, L flagPortableSQL[, L formatJSON]]]);

 

Where

 

Xbasic - A5_ink_to_png() Function - Background Color - The A5_ink_to_png() function is used to convert the Alpha Anywhere ink format (produced by the UX Ink control) to a .png image. By default, the image created has a transparent background. Now, you can specify an explicit background color.

Syntax:

function a5_ink_to_png as v (c ink ,n heightInPoints,n widthInPoints,c filename [, L flagUseViewBox [,c backgroundcolor ]])
 

 

Where

 

.Net 4.7.2 - Alpha Anywhere now installs Microsoft .Net 4.7.2. The first time you run an installer or path installer for this version there will be a significant delay while .Net 4.7.2 is installed (if it is not already installed on your machine).

 

UX Component - Expanding Menu - Set Background Color Below Menu - You can now easily set the background color of the space below the bottom an expanding menu control. This gives the expanding menu a more pleasing appearance.

 

 

 

 

In the expanding menu builder there is a new property Below menu background color.  By default, this property is set to <Same as Menu Color> which will use the Menu color defined in the previous property.

 

Alpha Launch - Publishing apps to Alpha Launch can be tricky. A new option on the Alpha Launch dialog allows you to check if your publish worked correctly. To test your publish, click the Check if files were published correctly button.

 

IMPORTANT: The publishing profile you define for Alpha Launch publishing should not use used to publish your application using the standard Publish dialog. The Alpha Launch publishing profile is for the exclusive use of Alpha Launch publishing.

 

 

 

Xbasic - Get size of JSON Array - The extension::json::ArraySize() method allows you to get the size of a JSON array, without having to first call the json_parse() function. For large JSON strings, this can result in a significant performance improvement

Syntax

n size = extension::json::ArraySize(c JsonString)

Example:

? extension::json::ArraySize("[10,20,30,40,50,60,70,80,90]")

= 9

 

Xbasic - Chunk JSON Array - The extension::json::ArrayChunked() method takes a large JSON array and breaks it into smaller chuncks

Syntax:

c JSONChuncks = extensioni::json::ArrayChunked(c json, n maximumRows, n maximumBytes, c separator)

Example:

? extension::json::ArrayChunked("[10,20,30,40,50,60,70,80,90]",3,0,crlf()+"--sep--"+crlf())
= [ 10,20,30 ]
--sep--
[ 40,50,60 ]
--sep--
[ 70,80,90 ]

 

Alpha Launch - Faster App Install - When you publish files to Alpha Launch you can now bundle the package of files that get loaded into AlphaLaunch into a single file. This makes installing apps on a device much quicker because a single file is loaded from the Alpha Launch server, rather than a large number of small files. To use this new feature, select the singleWithHeader option in the Alpha Launch Settings dialog.

NOTE: This option will only work if you have installed Alpha Launch V2.1.1 on your device.

 

 

 

JSON Path - JSON Path allows you to extract portions of a JSON string and perform certain types of simple calculations on JSON strings.

When working with XML data, there is a well known standard, called XPath, for extracting parts of the XML data. JSON Path allows for similar functionality when working with JSON data.

Xbasic now includes a new function called json_path() that allows you to perform JSON Path queries on JSON data.

You can also use JSON Path on the client side (in your Javascript code). The Javascript function is also called json_path().

IMPORTANT: The json_path() function is only available in the UX component. In addition, you must explicitly load the jsonpath system library by selecting it at the Optional system libraries property in the UX Builder if you want to use the json_path() function in your code

 

Syntax - Xbasic json_path() Function

c string = json_path(c json, c path)

Syntax - Javascript - json_path() Function

    string = json_path(jsonOrObject, path)

Where

 

 

The following sample JSON string is used in the examples below:


{
  "store": {
    "book": [
      {
        "category": "reference",
        "author": "Nigel Rees",
        "title": "Sayings of the Century",
        "price": 8.95
      },
      {
        "category": "fiction",
        "author": "Evelyn Waugh",
        "title": "Sword of Honour",
        "price": 12.99
      },
      {
        "category": "fiction",
        "author": "Herman Melville",
        "title": "Moby Dick",
        "isbn": "0-553-21311-3",
        "price": 8.99
      },
      {
        "category": "fiction",
        "author": "J. R. R. Tolkien",
        "title": "The Lord of the Rings",
        "isbn": "0-395-19395-8",
        "price": 22.99
      }
    ],
    "bicycle": {
      "color": "red",
      "price": 19.95
    }
  }
}

 

JSON PathSyntax

(NOTE: Examples are from the https://www.npmjs.com/package/JSONPath documentation)

 

$.store.book[*].author The authors of all books in the store
$..author All authors
$.store.* All things in store, which are its books (a book array) and a red bicycle (a bicycle object).
$.store..price The price of everything in the store.
$..book[2] The third book (book object)
$..book[(@.length-1)]
$..book[-1:]
The last book in order.
$..book[0,1]
$..book[:2]
The first two books
$..book[0][category,author] The categories and authors of all books
$..book[?(@.isbn)] Filter all books with an ISBN number
$..book[?(@.price<10)] Filter all books cheaper than 10
$..*[?(@property === 'price' && @ !== 8.95)] Obtain all property values of objects whose property is price and which does not equal 8.95
$ The root of the JSON object (i.e., the whole object itself)
$..* All Elements (and text) beneath root in an XML document. All members of a JSON structure beneath the root.
$.. All Elements in an XML document. All parent components of a JSON structure including root.
$..[?(@.price>19)]^ Parent of those specific items with a price greater than 19 (i.e., the store value as the parent of the bicycle and the book array as parent of an individual book)
$.store.*~ The property names of the store sub-object ("book" and "bicycle"). Useful with wildcard properties.
$.store.book[?(@path !== "$['store']['book'][0]")] All books besides that at the path pointing to the first
$..book[?(@parent.bicycle && @parent.bicycle.color === "red")].category Grabs all categories of books where the parent object of the book has a bicycle child whose color is red (i.e., all the books)
$..book.*[?(@property !== "category")] Grabs all children of "book" except for "category" ones
$..book[?(@property !== 0)] Grabs all books whose property (which, being that we are reaching inside an array, is the numeric index) is not 0
$.store.*[?(@parentProperty !== "book")] Grabs the grandchildren of store whose parent property is not book (i.e., bicycle's children, "color" and "price")
$..book.*[?(@parentProperty !== 0)] Get the property values of all book instances whereby the parent property of these values (i.e., the array index holding the book item parent object) is not 0
$..book..*@number() Get the numeric values within the book array

 

Example

 

Xbasic Example

dim path as c

'get the author for all books in the store

path = "$.store.book[*].author"

dim json as c

json = <<use the sample json string from above>>

dim result as c

result = json_path(json,path)

= [
    "Nigel Rees",
    "Evelyn Waugh",
    "Herman Melville",
    "J. R. R. Tolkien"
]

 

Javascript Example

    var path = '$.store.book[*]';

    var json = {

        //put sample json here

    }

    var result = json_path(json,path)

 

 

CURL Genie - Xbasic Template - extension::curl::RequestTemplate() Method - When you use the XBasic CURL genie (to convert a CURL command into Xbasic) a new, more concise Xbasic syntax can be generated.

The new syntax, shown in the image below in the Xbasic Template tab of the genie, takes a JSON input string to define the request.

The main advantages of the Xbasic Template over the low level Xbasic syntax (shown in the Xbasic tab of the genie) are:

In the example shown in the screenshot below, the JSON definition passed to the command defines:

 

 

 

The Xbasic Template can also be used to post multi-part form data.

 

In the screenshot shown below, the JSON defines a form property which can have form data (name "key1" and value "value1") and form data.

 

 

 

 

 

Special Placeholders

When defining the URI and the headers in the JSON passed to the extension::curl::RequestTemplate() method, there are two special placeholders that you can use:

The values for these placeholders are resolved by the specified Named Provider (see the namedResource variable in the example code below).

 

Sample Xbasic code showing how a REST API call is made to the Salesforce API.

(Assume that the authentication details for the Salesforce account have been saved in a Named Provider called salesforcetoken. )

Notice that the URI specified in the JSON string has an argument name in it (:id)

dim json as c = <<%json%
{
    "uri": "{namedresource.resourceurl}/services/data/v39.0/sobjects/Account/:id",
    "auth": {
        "bearer" : "{namedresource.access_token}"
    }
}
%json%
dim namedResource as c = "salesforcetoken"
 

'define the value of the arguments used in the URI
dim args as sql::arguments
args.add("id","0011N00001EBYRDQA5")
 

'instead of putting the account id in a sql::argument, we could have

'used a variable and referenced the variable in the URI as {accountNumber)

'instead of :id

'for example: /services/data/v39.0/sobjects/Account/{accountNumber}
 

dim vars as p
vars.accountNumber = "0011N00001EBYRDQA5"
 

dim response as extension::CurlResponse
response = extension::curl::RequestTemplate(json,namedResource,vars,args)

if response.content <> "" then

    dim json as c

    json = response.content
else

    'no response
end

 

 

 

UX Component - ViewBox Control - Data Source - REST API - The ViewBox control now has new data source type - REST API. Use this option to make a REST API call to retrieve the JSON data to be rendered in the ViewBox.

 

When you use the REST API option you can specify if the REST call is made from the server or from the client.

When you make the call from the server, the Alpha Anywhere server will make the REST API call and then return the JSON data to the browser. If you later refresh the ViewBox, an Ajax callback is made to the server, the server executes the REST API call and then returns the JSON data to the client.

When you make the call from the client, the REST call is made directly from the client using the Javascript XHR object. The Alpha Anywhere server is not involved at all.

When you make the call from the server, you can specify a URL for the REST API end point that includes placeholders that will get resolved before the call is made. You can use controls on the UX and also arguments as placeholders. For example, say you have a textbox on your UX called customerId. You might specify the URL for the REST API as:

http://www.myapi.com/customers/{customerId}

 

When the API call is made, the placeholders in the URL are resolved. So, for example, if at the time the ViewBox is refreshed, the customerId control has a value of CUST_01, the URL for API call will be:

http://www.myapi.com/customers/CUST_01

 

Argument values are represented in the URL using :argument_name. For example, assume you have an Argument called CUSTOMER_ID. You could specify this URL for the API endpoint:

http://www.myapi.com/customers/:CUSTOMER_ID

 

In some cases, the API endpoint you call will be authenticated. For example, many API endpoints require an oAuth authentication or a "service account" login. You can specify the name of a Named Provider (defined by going to the Tools menu when the Web Control Panel has focus, and selecting Tools, Named Providers, or by opening the Project Properties dialog).

In the case where the call is made from the server,  you can optionally specify an Xbasic function to post-process the JSON data that is returned by the REST API call before the data is returned to the client. In the case where the call is made from the client, you can optionally specify Javascript code to post-process the data before the ViewBox is populated.

In the case where the API call is made from the client, the URL is defined by Javascript code that must return the URL. This allows you to easily construct URLs that are dynamically computed, based on data in the component.

 

 

UX Component - ViewBox Control - Data Source - Custom - The ViewBox control now has a new data source type - Custom. When you select the Custom option you can specify the name of an Xbasic function. This function should return the JSON data that the ViewBox will render.

An example of where the Custom option could be used is if the data that you want to show in your ViewBox is returned from a SOAP service request, or you need to aggregate data from multiple data sources.

 

UX Component - List Control - <listObject>.removeRows() Method - Animation - You can now turn on animation when you remove rows from a List control using the .removeRows() method.

Syntax

<listObject>.removeRows([rowsToDelete [,flagAnimate]])

Where

 

 

UX Component - httpFetch() Method - A new method has been added to the UX component to fetch data from a remote URL.

Syntax:

{dialog.object}.httpFetch(url,onSuccess,onError[,headers])

 

Where headers is an optional array that allows you to set custom headers for the request. The headers array is an array of objects. Each object has a name and value property.

For example:

var headers = [];
headers.push( {

    name: 'Authorization',

    value: 'Bearer my_access_token_value_goes_here'

});

 

The onSuccess callback function get called when the data are available.

Example:

var url = 'http://some_remote_url'
var cb = function(data) { console.log(data)}
var fail = function() { alert('request failed');}
{dialog.object}.httpFetch(url,cb,fail)

 

Template Tester - MDI Window - The Template Tester (accessed from the Tools menu when the Web Control Panel has focus) is now a MDI window rather than a modeless window. This makes it easier to keep the Template Tester window open while you are working on other tasks.

Template Tester - Default Template - The Template Tester now has a new link on the Template pane to generate a default template from the JSON data. In cases where the JSON data is very complex, this can give you a quick start on building a new template. The default template can be generated in one of two ways: compact, or fully expanded.  The 'compact' option will use containers (e.g. {orders}....{/orders}) for arrays, but not objects. The 'fully expanded' option will use containers for both arrays and objects and it results in a larger template.

 

Alpha Anywhere Server for IIS - Performance Improvements - Session State Storage -

All session state providers have a new option to specify storage. A button is available in the new publish profile genie
 




and a new option is available in a publish profile's property sheet "Session State Storage Type" :



Session State Storage Type defines where session files are stored.

There are 2 options:


When "Storage Connection String" is selected there will be an additional prompt for the storage connection string.



When the storage connection string is of type "Disk" there will also be a "Storage Lifetime" and "Storage Scope" prompt.

 

Alpha Anywhere Server for IIS -  Redis Installed as a Service - The Application Server for IIS installer will now install Redis as a Windows service. This service will be installed for Manual start. If an application uses Redis for session state provider, this service can be set to Automatic start up and started up to provide a Redis instance. The redis.config for the service is located in C:\ProgramData\Alpha Software\Redis. See (https://www.alphasoftware.com/documentation/pages/Guides/IIS/ConfigureProviders/ProviderConfiguration.html#section2_configureRedis) for understanding the options in the redis.config file.
 

SQLite Database - A new menu option on the Tools menu (when the Web Control Panel has focus) allows you to create an SQL database and populate the database with data. After the SQLite database has been created, it can optionally be uploaded to Amazon S3. This makes it easy for mobile applications to download the database and store it on a device.

To select the option select Tools, More.., Create SQLite Database

 

Xbasic - High Precision Numeric Calculation - When doing numeric calculations with Xbasic there can sometimes be a loss of precision because internally Xbasic uses floating point numbers. A new class is available in Xbasic for high precision calculations. When using this new class, all input numbers and output results are variables of type character (not number).

For example:


 


? MathUtil::Decimal::Add("1.20","2.30")
= "3.50"
? MathUtil::Decimal::Subtract("1.20","2.30")
= "-1.10"
? MathUtil::Decimal::Multiply("1.20","2.30")
= "2.7600"

? MathUtil::Decimal::Divide("1.20","2.30")
= "0.5217391304347826086956521739"

? MathUtil::Decimal::Compare("1.20","2.30")
= -1


 

Web Applications - Publish - Done Message - After a web project is published, a dialog can now be shown to confirm that publishing was completed. You can toggle whether this dialog should appear or not by opening the Project Properties dialog from the Web Control Panel and selecting the Design-time tab.

NOTE: By default, this dialog is turned off. You must go to Project Properties, Design-time Settings to turn it on.

 

NOTE: Alpha Anywhere also displays a dialog after publishing files as shown below. This dialog can be turned on/off by going to the View, Settings menu and navigating to the Preferences, Web Publishing section. The setting to show or hide this dialog is system wide, while the settings for the new Publish Complete dialog are just for the current Web Project.


 

 

 

UX Component - PhoneGap - Instant Update - First-time Run Message - The first time you load a PhoneGap app (built using the Instant Update feature) on a device the app files must be unzipped and stored in a folder on the device. On most newer devices, this process happens quite quickly. However, on some older Android devices, it can take some time to unzip the files. It can appear to the user that the app is not responding. Therefore, you can now display a message to the user when the app is unzipping files for first time use. The message should tell users that this is a one-time delay and that they must wait until the files have been prepared.

 

 

Xbasic - A5InstanceCount Function - Returns the number of instances of Alpha Anywhere that are running.

 

Syntax:

n count = A5InstanceCount()

 

 

Runtime Applications - Control Panel - In most Runtime Applications, the Control Panel is hidden from the user. However, in some Runtime Applications, the user is allowed (by the designer of the Runtime Application) to get access to the Control Panel. You can now control which panes in the Control Panel should be visible in a Runtime Application

To set the visible panels, select the File, Workspace Properties menu option.

 

 

Documentation - Notable new Articles  - Several new notable articles have been added to the documentation. These articles are highlighted here:

 

 

Consuming SOAP Services - Sample Service - Alpha Anywhere now has a sample WCF service that you can host locally. This makes it very easy to test how to consume a SOAP service from Xbasic.

 

Watch Video
 

You can automatically install and run the sample, locally hosted, service when you create a new Web Reference client at the Web Control Panel, as documented in the steps below:

 

 

1. Click on the New button when the Web Services category is selected.

 

 

2. Click the Create a new definition to consume a SOAP web service button.

 

 

3. Select the Sample WCF Service item from the dropdown when you click on the Insert Sample hyperlink.

 

 

 

 

UX And Grid Components - Friendly Dates - String Customization  - You can now customize the strings used to display 'friendly dates' (e.g. a friendly date might display 'today' by default, but you might want to customize this so that it displays in the user's language of choice).

You can now customize all of the strings used in friendly dates by setting the Friendly dates customization property. You can use language and text dictionary tags in the customized strings.

 

 

 

UX Component - List Control - Fields - Security Groups and Server-side Show/Hide Expressions - When you define a List control, the List Builder allows you to specify security groups and server-side show/hide expressions for any of the fields in your List's data source.

A clarification has been added in the builder explaining that these settings only apply to fields used in a Column List layout. They do not apply in a Freeform layout. Furthermore, these settings only control whether a particular column in the List layout should be shown or not -- they do not affect the data that are sent from the server to the browser. (So, for example, if you have set a security setting on (say) the 'salary' column, the 'salary' column will be hidden in the List, but the List data that is sent from the server to the browser will still include the salary data).

If the List is based on a SQL query, then if you have defined security groups or show/hide expressions for any field in the List data source, when you close the List Builder a new dialog (shown in the image below) will appear asking if you want to copy your security and show/hide settings to the Data Source tab. The advantage of doing this is that the security and show/hide will be applied at the query level (meaning that in the above example, the salary data will not be included in the List data that is sent from the server to the browser).

 

 

 

 

UX Component - PhoneGap - iPhoneX - Sample Template - Styling a PhoneGap application so that it looks good on an iPhoneX can be tricky. A new sample template for UX components is available to help you get you styling right.

When you create a new UX select the PhoneGap - iPhone X Styling template.

 

 

 

PhoneGap  iPhone X - Important information about styling an iPhone X application so that it appears full screen has been added to the documentation. The article can be accessed from this link. If you are building PhoneGap apps for iPhone X, this article is essential reading.

 

PhoneGap Builder - Hot Topics Link - The PhoneGap builder now has a new hyperlink that opens the 'Hot Topics' documentation in the Help System. The PhoneGap ecosystem is in constant flux. As Adobe updates the PhoneGap build service from time time time, things that used to work may not work the same way or plugins that used to work may no longer be working. The Hot Topics document in the Help System helps you stay on top of the changes to PhoneGap and alerts you to things you might need to do in your PhoneGap projects.

 

 

 

 

UX Component - Bind Controls Dialog - The Bind Controls to Fields dialog is now easier to work with (especially for UX components that bind a large number of fields) because the dialog now allows you to filter and sort the data shown in the table.

 

 

 

UX Component - Map Control - Action Javascript - Compute Distance and Travel Time Between Points - A new action type has been added to the Google Maps Methods action. The action is called Get distance and travel time between points. It takes an array of addresses (either strings or longitude/latitude values) and computes the distance and travel time between each set of points in the array.

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

 

 

The builder for the action is shown below. You can either pass in a start and end address or multiple addresses.  In the case where you select MultipleAddresses you must specify the name of a Javascript function that will return an array of addresses. For example, if your function returns an array with these addresses:

 

['address1','address2','address3']

 

the action will compute the distance and travel time between:

The action is asynchronous, so when all values have been computed, a callback function is called. You can specify the Javascript run run in the callback function in the onReady Javascript property.

In your Javascript you can reference an array called data that has an item for each address pair. Each item in the array has these properties:

 

In addition you can reference these variables:

 

 

Control Panel - Contains optimizations to improve the way in which the Control Panel is rendered

 

UX Component - PhoneGap - Instant Update - Quick Build - If your PhoneGap project has turned on the Instant Update feature, a new button appears on the Web Projects Control Panel toolbar that allows you to quickly build an Instant Update without having to bring up the PhoneGap Genie. All modal dialogs normally displayed when an Instant Update is built are suppressed.

 

UX Component - Action Javascript - Map Control - Plot Route - A new action in Action Javascript - Google Map Method makes it easy to plot a route on a map and get directions (either driving, walking or bicycling).

 

 

 

The builder for the new Plot route action is shown below:

 

 

 

The Type property can either be StartAndEndAddress or MultipleAddress. If you select StartAndEndAddress you can either enter address for the start and end (e.g. '36 Bigelow St. Cambridge MA') or latitude/longitude values (comma delimited (e.g. 42.3685632,-71.1045822). You can also specify the name of a Javascript function to return the start and end address. To use a Javascript function, specify the address as:

javascript:name_of_your_function

 

If you select MultipleAddress option, then you must specify the name of a Javascript function. This function must return an array of addresses. Each address in the array can either be an address or a lat/lng value (comma delimited).

 

 

 

Bugs

Reports - PDF - Watermark - Fixed an issue where settings for PDF watermarks were not being honored under certain conditions.

fedex_delivery_status() Function - Fixed this function.

 

Grid Component - Search Part - Checkbox - Fixed a regression where a search using a checkbox control combined selected options using AND rather than OR.

SQL Server Reporting Services Reports - Multi-select Parameters - Numeric Stored Value - If a SSRS report had a multi-select parameter that had a numeric stored value (i.e. the parameter displayed a list of string values, but each string value had a numeric stored value), the report could not be displayed by Alpha Anywhere.

SQL Auditing - The SQL Audit feature was not correctly inserting the name of the Grid that was used to edit a table when the component was run in live mode. In Working Preview, it worked correctly. Also, the audit feature was not inserting the connection string into the Audit Table. You will need to recreate the Audit Table to get the fix for the connection string.

 

 

 

Alpha Anywhere V4.5.4 - Build 5028-5088 19-APR-2018

 

Videos

Auditing Auditing Table Edits In many applications it is desirable to keep track of every edit made to a SQL table so you can know what fields were changed, who made the edit and when the edit was made. This is often achieved by added update, insert and delete triggers to the SQL database. But in cases where it is not possible to modify the database, you can use the built-in auditing feature in Alpha Anywhere.

In this video we show how the auditing feature is set up and used.

Watch Video

In cases where updates to SQL tables are made in your own Xbasic code (as opposed to from UX and Grid components), it is necessary to manually update the audit log. In this video we show how this is done.

Watch Video - Part 1
Watch Video - Part 2


Date added: 2018-15-06

 

 

Features

 

Auditing  - You can now enable an auditing feature to keep track of all edits made to SQL tables in an application. Information about each Insert, Update and Delete is kept in the Audit table. This table keeps track of the type of edit, the user id of the person making the edit, the name of table that was edited, and the old and new value of each field that was edited.

Watch Video

 

To turn on the Auditing feature, go to the Project Properties dialog in your Web Project (click the Project Properties button when the Web Control Panel has focus) and then check the Keep track of edits to tables made through Grid and UX components property.

 

 

Once you do this, you will be able to specify the connection string to the database where the Audit table is stored. You can either map an existing table, or create a new table.

 

 

By default, the User Id of the user who made the edit to a table is obtained from the Alpha Anywhere security framework (by evaluating the context.security.currentUser expression). However, if you are not using the Alpha Anywhere security framework, you can define a custom expression to get the user id of the person who made the edit.

 

In the case where you are making updates to SQL tables in your own Xbasic code, you will need to manually update the audit log table. There are two helper function in Xbasic to make this easy:

 

For example, the following code updates a table and also updates the audit log

dim cn as sql::Connection

cn.open("::Name::Northwind")

dim args as sql::arguments

args.add("primaryKey","ALFKI")

args.add("title","Manager")


dim sql as c
sql = "update Customers set title = :title where CustomerID = :primaryKey"

'capture the BEFORE update values
dim dataJson as c
dataJson = a5Helper_getAuditInfoFromSQLStatement(cn,sql,args.xml)

flag = cn.Execute(sql,args)

'write to the auditing table
a5Helper_writeToAuditingLog(cn,"Update",dataJson,"CustomerID","ALFKI")
 

TIP: The Audit table can grow to be very large in a large application used by many people. You might want to implement a strategy to purge old records from the audit table from time to time.

Alpha Anywhere Server for IIS - Redis is now an option for the Session State Provider in a publish profile.
 




The configuration settings are as follows:
 


JIT session locking can also be set.

The option will only appear on the profile property sheet.

 





It is also only available for the Redis provider.

The SecurityConfiguration object has a new property JitSessionLock that when set to true and the new AddSessionStateProviderRedis() is called, will configure to use the JIT session state wrapper with the Redis session state provider.

 

UX Component - Action Javascript - PhoneGap - TouchID/FaceID Action - A new action in Action Javascript allows you to easily use features in the PhoneGap TouchID plugin.

 

Bugs

UX Component - Reports - CurrentListFilter() - Fixed an issue when using the special CurrentListFilter() function an a report filter if the List was a parent of another List with pre-fetched data.

UX Component - Detail View - PhoneGap - Image Capture for List Detai View - onImageCapture Event - Was not firing if the capture method was set to PhoneGap.

Reports - Report Server - Images - PDF Reports - If you have a report with images in the data, then when printing the report to PDF from a web application, the images did not appear in the PDF. This problem does not happen if you turn off the Report Server (from the Project Properties dialog). The problem also does not affect the IIS server, or Alpha Cloud as neither of these use the Report Server. This issue is now fixed.

Web Applications -- IIS Server - Workspace reports, labels and letters are now all allowed if component security if turned off.

TabbedUI - Running a TabbedUI in build 5007 that had been created in an older build caused a Javascript error in certain cases.

 

 

Alpha Anywhere V4.5.3 - Build 5009-5081 10-APR-2018

Web Applications -- IIS Server - Workspace reports, labels and letters are now all allowed if component security if turned off.

TabbedUI - Running a TabbedUI in build 5007 that had been created in an older build caused a Javascript error in certain cases.

Alpha Anywhere V4.5.3 - Build 5007-5081 09-APR-2018

 

Videos

UX Component - PhoneGap Using the Instant Update Feature in a PhoneGap Application After you have created a PhoneGap application from a UX component, if you subsequently want to update the application you need to go through the entire release cycle again (i.e. submit to PhoneGap Build, then submit to the appropriate App Store). However, if you enable the Instant Update feature when you build your application in the first place, you can make certain types of updates to your application without having to go through the release cycle again.

Instant Update can be used as long as you are not changing the PhoneGap plugins used by your application, or the splash screens, etc. You can perform an Instant Update on an application as long as the changes to the application are limited to changes in the application's UX component.

In this video we show how the Instant Update feature operates.

Watch Video - Part 1
Watch Video - Part 2

Date added: 2017-12-24
Grid Component - Alphabet Button Search Adding Bubble Help with Record Counts to Buttons in Alphabet Button Search Bar The Alphabet Button search bar in a grid is a convenient way for searching for all records where a field starts with a particular letter. It can be useful for the user to know how many records are in each group before they actually press the button to execute the query.

In this video we show how bubble help is added to each button in the Alphabet button search bar. When the user hovers the mouse over the button, the bubble help shows how many records are in the group.

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

Download component

Date added: 2017-12-31
Reports Alternating Background Colors for Records in the Detail Section It is common in reports to print alternating rows in the report's Detail section with different background colors.

This video shows how this is done.

Watch Video

Date added: 2018-02-01
UX and Grid Components Display Date and DateTime Values using Formatted Text Date and datetime values are easier to comprehend when they are formatted in a 'friendly' manner (e.g. today, in 1 hour, tomorrow).

In this video we show how you can display date and datetime values using 'friendly text' in a Grid and UX component.

Watch Video

Date added: 2018-02-04
UX Component ViewBox - Client Side Reporting Using the ViewBox control, it is possible to create highly stylized client-side reports. In this video we build on a previous view in which a sample Invoice report is created. The video shows how you can configure the report to allow the invoice line-items to be collapsed (i.e. hidden) or expanded. The video also shows how you can add a button to the report to generate a PDF file for the report.

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

Date added: 2018-02-10
UX Component Mobile Date Picker In a mobile app, the standard date picker control that the UX uses may be too big for the screen. In this case, it might be desirable to use a date picker that is more tuned to a mobile application, such as a control that uses Spin Lists to select the month, day and year.

In this video we show how to use Spin List controls to edit the value in a date field.

Watch Video

Download component

Date added: 2018-02-23
UX Component - List Control Displaying Friendly Dates in a List Control The data picker control allows you to display dates in a friendly format (i.e. today if the date is today's date).

In this video we show how date values displayed in a List control can be displayed in a friendly format.

Watch Video

Download component

Date added: 2018-02-23
UX Component - ViewBox Control
Using a ViewBox to Create Nice Looking Email Messages The ViewBox component can create beautifully styled HTML by merging data into a template to create a customized, styled HTML document. You might want to email the contents of the ViewBox to someone as an HTML message.

In this video we show how a ViewBox can be used to create some nice looking HTML output (by merging JSON data for a customer's order into an HTML template) and then sending the resulting output as an HTML email.

Watch Video - Part 1
Watch Video - Part 1

Download component

Date added: 2018-03-02
UX Component - ControlBar Control Scrolling disclosure menus A common practice when building ControlBars is to have a button on a ControlBar that displays a menu that slides in from the left or right. The menu can be implemented using a List (which is inherently scrollable), but can also be implemented using a disclosure (which is a much simply solution).

In this video we show how the disclose menu can be made to scroll.

Watch Video

Date added: 2018-03-27
Salesforce Creating a Salesforce Connected Application Before you can work with Salesforce data in an Alpha Anywhere application, you must first define a new Connected Application in your Salesforce account and a Named Resource in your Alpha Anywhere Web Project.

This video walks through the process of creating a Salesforce Connected Application

Watch Video

Date added: 2018-04-06
Salesforce Creating a Named Resource Provider Before you can work with Salesforce data in an Alpha Anywhere application, you must first define a new Connected Application in your Salesforce account and a Named Resource in your Alpha Anywhere Web Project.

This video walks through the process of creating a new Named Resource Provider in your Alpha Anywhere web project.

Watch Video - Part 1
Watch Video - Part 2


Date added: 2018-04-06
Salesforce Making REST API Calls Then SalesforceAPIRequest() function makes it easy to make REST API requests to the Salesforce API. You can either make a request directly against an endpoint documented in the Salesforce API documentation, or you can use the Salesforce SQL like query language, SOQL, to execute queries.

In this video we show both uses of the SaleforceAPIRequest() function.

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

Date added: 2018-04-06
Salesforce Creating a Connection String You can create a Salesforce connection string (just as you create connection strings to point to SQL databases) that then allows you to treat Salesforce as a data source for a component, or a control.

In this video we show how a Salesforce connection string can be defined and then used to create a Grid component.
Watch Video - Part 1
Watch Video - Part 2

Date added: 2018-04-06
Salesforce Building a UX Component That Uses the Salesforce API In this video we show how a UX component can be built to display Salesforce data. The UX component does a query to retrieve the a list of accounts from Salesforce and it displays the result in a List control. When the user clicks on a row in the List, details for the selected account are shown by making another API request to Salesforce.


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

Download component

Date added: 2018-04-06
Creating a REST API Creating a simple REST API You can create REST APIs in Alpha Anywhere to expose functionality defined in an Xbasic class or a Node API.

In this video we show how a simple API is defined.

Watch Video - Part 1
Watch Video - Part 2

Date added: 2018-04-06
Creating a REST API Passing parameters to a method In the previous video we showed how to expose a very simple method in a REST API. The method did not take any arguments. Typically most of the methods you expose in your API will take arguments. These arguments can be supplied to the method being called in various ways (as part of the request URL, in query parameters, in the request header, or in a POST body).

In this video we show how a method that takes a single parameter can be exposed in a REST API.

Watch Video

Date added: 2018-04-06
Creating a REST API Authenticating a method in a REST API When you create a REST API that exposes one or more methods, you might want to require that some (or all) of the methods exposed by the API should require some type of authentication before the call can be made.

In this video we show how to require authentication for certain methods in your API.

Watch Video - Part 1
Watch Video - Part 2

Date added: 2018-04-06
Creating a REST API Auditing an API You can use the audit feature when you create a REST API to keep track information such as how often a particular endpoint is called, how long each method takes to execute. You might want this information so you can implement some type of rate limiting for you API to ensure that it is not being abused.

In this video we show how you can define methods to audit the use of your API.

Watch Video

Date added: 2018-04-06
Creating a REST API Defining the Encoding for the Body Data A common use case for an API is to create a new record in a database or to update an existing record in a database. In these cases, the request will typically be a POST and the data for the new or updated record will be in the request body. The data in the body can either be FORM or JSON encoded.

Watch Video

In this video we will show the difference between FORM and JSON encoding the body data.

Date added: 2018-04-06
Creating a REST API Returning Complex JSON Data In this video we show how to create a REST API that returns complex JSON data for a customer. The API will return data about a particular customer, including all of the orders placed by that customer, and for each order, all of the line items in that order. The data will come from querying the sample Northwind database. The video shows an example of the type of complex data that a REST API is often designed to return.

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

Download files

Date added: 2018-04-06
Creating a REST API Importing a Swagger Definition When you create a REST API you can either start by defining an Xbasic Class that defines the methods you want to expose in your API, or you can start by importing a Swagger definition for the API. Swagger is an open source standard for describing REST APIs. When you import a Swagger API definition, Alpha Anywhere will create a stub Xbasic class that you can then edit.

In this video we show how you can import a Swagger definition.

Watch Video

Date added: 2018-04-06

 

 

Breaking Changes

Web Applications - Active Directory  - As a result of changes in the way Active Directory authentication is now implemented, certain applications may need to be reconfigured. If an application uses Forms Based Active Directory for authentication and authorization (i.e. for users and groups) the Active Directory Configuration in the publish profile may need to be updated if the users are defined in one organizational unit and roles are defined in a different organizational units.

The Active Directory Configuration dialog now has an additional prompt for the organizational unit that specifies the groups used by the application. The input value is the distinguished name of the organizational unit. This prompt can be set to "All Organization Units" if groups are in the same hierarchy as specified in the LDAP connection string.



Given this Active Directory structure:


 

Company Domain (Domain)
    Users (Users)
        User1
        User2
        User3
    Car Division (OU)
        CarUser1 (User)
        CarUser2 (User)
        CarUser3 (User)
    House Division (OU)
    Application Division (OU)
        Group1 (Group)

            User1

            CarUser1
        Group2 (Group)

            CarUser2
        Group3 (Group)

            User1


 

And this LDAP connection string:

LDAP://ad.company.com/CN=Users,DC=ad,DC=company,DC=com

 

And a setting in the Organizational Unit for groups prompt of:

OU=Application Division,DC=ad,DC=company,DC=com

 

Then, anyone in Active Directory can login, but only users in an "Application Division" group (i.e. Group1, Group2, Group3) will have access to protected pages.


Next, assume the following LDAP connection string:


LDAP://ad.company.com/OU=Car Division,DC=ad,DC=company,DC=com

 

And assume that the setting for the Organizational Unit for groups  prompt is:


OU=Application Division,DC=ad,DC=company,DC=com
 

In this case, only users in the Car Division OU will be able to login. Only the users that are assigned to an "Application Division" group will have access to protected pages.

This change affects both the Standard Application Server and the Application Server for IIS.

 

 

Application Server - Cookieless Sessions - Support for cookieless session tracking has been removed from the Classic Application Server. This eliminates the small possibility that previously existed of "session hijacking".  Your application users must now support cookies in order to use sessions with the Classic Application Server.

 

 

Features

REST API - Creating - You can now create and publish REST APIs. Alpha Anywhere has always had the ability to consume REST APIs, but now you can also publish your own REST APIs.

For details on how to create and publish a REST API, click here.

Salesforce - Extensive support for working with Salesforce data has been added to the Alpha Anywhere. For complete details on how you can work with Salesforce data in an Alpha Anywhere application, click here.

 

PhoneGap Build - Instant Update - The Instant Update feature allows you to update a PhoneGap App that has already been installed on a user's device without needing to submit the App to the PhoneGap Build service after you have made changes to the App and without having to re-submit the App to the App stores.

As soon as the user launches the App on their mobile device, the App will be instantly updated to the latest version of the App.

 

Watch Video - Part 1
Watch Video - Part 2
 

The first time you create a PhoneGap App from a UX component, you are creating a Baseline for this application. The Baseline App must be submitted to the PhoneGap Build service, and must then be submitted to the appropriate App Stores.

After you make changes to the App, the PhoneGap genie will prompt if you want to do an Update build, a new BaseLine build, or Roll-back to a previous update.

NOTE: You can only use the Instant Update feature if you do not need to change any of the PhoneGap plugins used in your App. If you need to change PhoneGap plugins, you will need to create a new Baseline application.

If you select to do an Update build, the PhoneGap genie will determine which files in your project have changed (relative to the Baseline build) and will upload a changes file to a server (either an Alpha Software Amazon S3 bucket, or your own Amazon S3 bucket). When a user launches the App on their device, the App will automatically check if a new version is available, and it will instantly update itself to the new version.

If you release an Update to your App, and you find that this new version has introduced a bug, you can roll back to a prior version. When the user launches the App on their device, the App will instantly be downgraded to the specified previously released version.

To turn on the Instant Update feature, set the Enable Instant Update property to Yes.

 

Once you have enabled Instant Update the Instant update settings property is revealed

 

 

 

The options in this dialog are:

                    The current installed version number (shown when the App is launched)

                    App is running latest version message (if no update to the App is found)

                    App was updated message (if an update was found)

                    In Verbose mode, the user-defined After update message will also be shown.

                    Fatal errors are always shown.

 

 

How to Configure A Private S3 Bucket

The S3 bucket you specify must have a CORS policy set. Click the CORS Help hyperlink on the Instant Update Settings dialog for more information on CORS.

You will also need to set a bucket policy to set the objects in the bucket to allow public read. The policy can be set in the Amazon AWS management console and it will look something like this:

{
    "Id": "Policy1513279106848",
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt1513279094040",
            "Action": [
                "s3:GetObject"
            ],
            "Effect": "Allow",
            "Resource": "arn:aws:s3:::your-bucket-name/*",
            "Principal": "*"
        }
    ]
}			
			
			
			

UX Component - PhoneGap Applications - {dialog.object}.instantUpdateCheckForUpdate() Method - This method allows you check if an update is available in a PhoneGap application that was build with the Instant Update feature enabled. Since this is an asynchronous operation, you need to provide the JavaScript success and the error callback functions.

If a result is returned within a 5 second time-frame, the successCallback is called and passed an object with a result property that will be either true or false. If true, an update is available. If a timeout or any other error occurs the error callback is passed an error object or a string, depending on the error.

This method can be useful if you have turned off auto updates and want to programmatically check if an update is available.

Syntax:

{dialog.object}.instantUpdateCheckForUpdate(_successCallbackFunction,_errorCallbackFunction);

 

Where

_successCallbackFunction - function to call if there is an update available

_errorCallbackFunction - function to call if there was an error checking for an update.

 

UX Component - PhoneGap - Instant Update - By default, if you build a PhoneGap App and you turn on the Instant Update feature, every time the App is launched in a device, the App will check if a new version is available. You can turn this default behavior off.

When you define your PhoneGap project, the Instant Update Settings dialog has a property called Automatically check for update when App is started. If you uncheck this property, then when the App is started, it will not automatically check for a new version.

 

 

 

 

Use the {dialog.object}.instantUpdateRefresh() method to force a check for a new version at runtime.

You can toggle this setting on or off at run-time using this method: {dialog.object}.instantUpdateUseAutoUpdate(true/false);
 

 

UX Component - PhoneGap Applications - Instant Update - URL For AJAX Callbacks - When creating an Instant Update to an existing baseline application, you can now change the URL for Ajax callbacks by checking the Change AJAX URL property in the image shown below.

When you press the OK button, the Genie will prompt for a new AJAX callback URL.

 

The AJAX callback URL is set in the PhoneGap builder when you create he baseline version of your application. When you create an update you might want to change this URL so that users who are still running an older version of your APP are still making callbacks to the original location, while users who are running the latest version of your App will make callbacks to a new location.

Another reason why you may want to change the URL for AJAX callbacks is that you simply want to move the location where your App is hosted. For example, you might be migrating from on premises deployment to deploying in the Alpha Cloud.

IMPORTANT: If you change the URL for AJAX callbacks be sure to also publish your App to that location!

 

 

UX Component - PhoneGap Applications - Instant Update - Version Numbers - When you create an Instant Update to a PhoneGap Application, each update is automatically give an internal version number. The internal version number is an integer that automatically increments each time a new Instant Update is created.

Now, you can also define your own version number for each Instant Update. The version number can use any numbering pattern that you want. (The Internal Version Number will also still be generated). In addition you can define a description for the Instant Update.

Your version number and description will make it easier if you need to roll back to a previous version to select the version to which you want to roll back.

 

 

UX Component - PhoneGap Applications - {dialog.object}.instantUpdateRefresh() Method - This method allows you to check for a new Instant Update version of an application without having to exit the App on the device and then re-launch it.

The method is only available in a PhoneGap application that was build with the Instant Update feature enabled.

Normally, after you publish an Instant Update to a PhoneGap application, users will not get the new version until they re-launch the application on their devices.

Using this method, you can get a new version of the application without have to exit and re-launch the application.

Syntax:

{dialog.object}.instantUpdateRefresh()

 

 

Xbasic - JSON_normalize() Function - Takes an array of JSON objects and "normalizes" the data to create an hierarchical JSON object.

For example, consider the following "un-normalized" JSON array:

 

[
{"name" : "john", "state" : "MA", "city" : "boston"},
{"name" : "fred", "state" : "MA", "city" : "boston"},
{"name" : "liz", "state" : "MA", "city" : "springfield"},
{"name" : "jill", "state" : "NY", "city" : "albany"},
{"name" : "sid", "state" : "NY", "city" : "manhatten"},
{"name" : "tammy", "state" : "NY", "city" : "manhatten"},
{"name" : "fran", "state" : "RI", "city" : "providence"},
{"name" : "tess", "state" : "RI", "city" : "providence"}
]

 

Notice that the "state" and "city" properties are duplicated in each array item.

You can use the JSON_normalize() function to produce the following "normalized" JSON:

 

			
[
    {
        "state": "MA",
        "_list_1": [
            {
                "city": "boston",
                "_list_2": [
                    {
                        "name": "john"
                    },
                    {
                        "name": "fred"
                    }
                ]
            },
            {
                "city": "springfield",
                "_list_2": [
                    {
                        "name": "liz"
                    }
                ]
            }
        ]
    },
    {
        "state": "NY",
        "_list_1": [
            {
                "city": "albany",
                "_list_2": [
                    {
                        "name": "jill"
                    }
                ]
            },
            {
                "city": "manhatten",
                "_list_2": [
                    {
                        "name": "sid"
                    },
                    {
                        "name": "tammy"
                    }
                ]
            }
        ]
    },
    {
        "state": "RI",
        "_list_1": [
            {
                "city": "providence",
                "_list_2": [
                    {
                        "name": "fran"
                    },
                    {
                        "name": "tess"
                    }
                ]
            }
        ]
    }
]
			
			

Syntax:

c jsonOut = json_normalize(c jsonIn, c groupingOptions)

 

Where:

In the above example, the command used to produce the normalized JSON is:

json_normalize(jsonin,"state,city")

 

This indicates that the first level of grouping is on the "state" property, and the second level of grouping is on the "city" property.

 

NOTE: The json_normalize() function is the reverse of the json_flatten() function.

 

UX Component - ControlBar - Disclosure Type - Template - A new type of ControlBar disclosure can now be created. The Template type allows you to create arbitrary HTML and inject placeholders for ControlBar items into the HTML.

Watch Video

For example, assume you have defined these ControlBar items: Button1, Button2 and Button3.

You can inject these controls into the HTML for the template using these placeholders: [Button1], [Button2] and [Button3].

The Template type is similar to the HTML disclosure type in that they both take an HTML template. There are however significant differences. The Template type is regenerated every time the disclosure is opened and you can inject ControlBar items into the template. The contents of the disclosure can be scrolled.

The HTML type is rendered once at the time the ControlBar is instantiated and you cannot inject ControlBar items into the HTML. The contents of the disclosure cannot be scrolled.

 

 

 

UX and Grid Components - Action Javascript - Open a Grid and Open a UX Actions - Ajax Failed Message - The actions to open a child UX or Grid have always allows you to specify a value for the Ajax failed message.  This message is displayed in the case of a failed Ajax callback (i.e. the server does not respond). Now you can execute arbitrary Javascript when the Ajax callback fails by specifying the Ajax failed message as

javascript:name_of_your_javascript_function

 

UX Component - Sample Template - MobileApp_HOST_UX_with_multiple_linked_child_UX_components - When you create  new UX Component, a new template is available.

This template shows a possible design solution for the use case where you have a parent table (e.g. customers) and you want to be able to display/edit an arbitrary number of tables related to a particular customer. For example, each customer can have multiple Order, Payments, Credits, Returns, Notes, etc.

The sample UX component shown in this template is analogous in concept to a Grid based on the Customer table with a row expander showing grids for each of the related child tables.

 

 

UX and Grid Component - Auto-suggest - Speed Improvement - By default the auto-suggest used the Upper() function in the SQL select statement to force the query to be case insensitive. However, on extremely large tables this resulted in a significant slow down and furthermore many databases already perform case insensitive queries by default so using the Upper() function was unnecessary.

Now, the Auto-suggest does not use the Upper() function in the generated SQL query, meaning that on those databases that perform case-insensitive queries the auto-suggest is case-insensitive and on those database that perform case sensitive queries, the auto-suggest is case sensitive. The resulting performance improvement on very large tables can be dramatic.

For those situations where you have a database that performs case sensitive queries, but you want the auto-suggest to be case insensitive, a new option in the Auto-suggest builder allows you to explicitly force a case-insensitive query.

 

UX Component - List Control - Detail View - Incremental Refresh - Timestamp Field - Normally, no schema changes are required to the database in order to perform an incremental refresh (i.e. there is no requirement that a timestamp field be added to the table).

An incremental refresh must compute which records on the server were changed since the last time the List was populated. In order to compute which records were changed the checksum (CRC) of the record contents of each record on the server is compared with the checksum of the corresponding record on the device. If the checksum is different, the record was changed and an updated version of the record is sent to the server.

However, a more efficient way of determining if a record was changed is to query for all records modified since the highest timestamp value the last time the List was populated.

Now, if you have a timestamp field in your table, you can direct Alpha Anywhere to use this field for Incremental Updates, rather than the CRC (checksum) method.

To direct the List to use a timestamp field for incremental updates, open the List builder and go to the Detail View pane.

Then check the Use a 'timestamp' field when performing an Incremental Refresh property and then specify the name of the timestamp field.

 

 

UX Component - List Control - Detail View - PhoneGap - Media Files - Ignore Folder - When a List is populated you can specify that all media files (images, videos, audios, etc.) that are referenced in the List should be downloaded to the device so that these media files will be available when the device is offline.

Now you can specify that any referenced media files that are in a folder in the PhoneGap bundle (i.e. in a subfolder inside the www folder of the PhoneGap project) should be ignored when the List computes which files must be downloaded from the server.

The following scenario will make the use case for this option clearer.

 

Assume that your UX contains a List control with this data in two of the rows at the time the PhoneGap project is built:

ID Name Image
1 Alpha myImages/image1.jpg
2 Beta myImages/image2.jpg

 

The myImages folder is part of your Web Project (i.e. it is stored in your Web Project folder) and it contains the files image1.jpg and image2.jpg.

 

When the PhoneGap app is built, the 'myImages' folder is included in the PhoneGap project (the PhoneGap Genie has a property where you can specify Additional Files to be included in the PhoneGap project). You would specify

myImages/*.*

for the additional files.

 

When the PhoneGap app is built, the myImages folder and all of the images in that folder become part of the PhoneGap application (i.e. the myImages folder will be a sub-directory in the www folder on the device) and the images in the List will still display because the Image field is pointing to a local file on the Device.

Now further assume that when you designed the List control you specified that Media files should be downloaded to the device. When you specify this property you specify the folder where the media files should be downloaded. You cannot specify that they should be downloaded to the www/myImages folder on the device as that is a read-only folder.

By default Alpha Anywhere suggests a folder for media file downloads called _AAFiles in a part of the filesystem that you designate.

When you refresh the List, Alpha Anywhere decides if the image must be downloaded by checking for its existence in the target folder (i.e. _AAFiles by default). So when it checks the first record, it will not find an image called myImages/image1.jpg in the target folder, and therefore it will attempt to download this file (even though this file is already in another folder on the device) from the server so it can be stored in the target folder.

Once the download is complete the filename in the Image field will be changed to point to the file in the target folder (i.e. the _AAFile folder).

However, by specifying which folders in the PhoneGap bundle to ignore, you can prevent Alpha Anywhere from downloading any images that are already on the device in the www/myImages folder.

To specify folders in the root www folder to ignore, open the List builder and go to the Detail View pane. Then open the Media files (photos, videos, audio recordings, other) settings dialog.

 

 

In this window, check the Ignore media files in www sub-folder property and then specify the folder name.

 

 

UX Component - List Control - Detail View - .addTableRowsBulk() Method  - Allows you to programmatically add multiple rows of data to a List with a Detail View.

The <listObject>.addTableRowsBulk() method allows you to add an array of new rows to the List.

NOTE: Using the .addTableRowsBulk() method is faster than calling the .addTableRow() method in a loop.

 

Example:

 

var listObj = {dialog.object}.getControl('LIST1');

var dataArray = [

    { FIRSTNAME: 'Cecelia', LASTNAME: 'DeLuca'},

    { FIRSTNAME: 'Cathy', LASTNAME: 'Marsh'}

]

listObj.addTableRowsBulk(dataArray);


 

TransForm - TransForm is a stand-alone service for building mobile, data collection forms (i.e. apps). To use TransForm you do not need an Alpha Anywhere license, but if you also have Alpha Anywhere, there are several features in Alpha Anywhere that make working with TransForm easier. To learn more about TransForm, click here.

To learn more about the TransForm features that are built into Alpha Anywhere, click here.

 

AlphaDAO - Update and Delete Operations - When you execute a SQL UPDATE or DELETE operation, if the WHERE clause does not find any records to operate on the SQL::Connection.execute() method currently returns .F.

However, some developers have requested that the SQL::Connection.execute() method should return .T. and treat the "no records found" condition as a warning and not an error. The SQL::Connection.callResult.rowsAffected property can be checked to see if any work was actually done.

In order to change the default behavior so that the "no records found" condition is a warning you can either manually update the connection string to add this property to the connection string:

A5ReportNotFoundAsWarning=Y

NOTE: This property is not exposed in the connection string builder.

Or alternatively, set a property on the connection object. For example


DIM cn as SQL::Connection
cn.ReportNotFoundAsWarning = .t.

 

 

Web Projects Control Panel - Component Dependencies - You can now right click on a component in the Web Projects Control Panel and select the Show dependencies for this component... menu item to see a list of component that this component calls and a list of components that call this component.

 

 

For example, this dialog shows that the Auto_Customers Grid component is called by the FlyingStartTabbedUI component and that it calls the Auto_Orders component.

UX Component - Builder - Live Preview - The Live Preview pane in the UX builder now lets you select if you want to use Internet Explorer or Chrome for Live Preview. Previously Internet Explorer was used and there was no option to use Chrome instead.

This is now similar to Working Preview which also allows you to select between Internet Explorer and Chrome.

 

UX Component - Arguments - Setting Values on the Client-Side - The value of arguments in a component are typically set on the server-side. Now, a new method - .setArgumentValue() -  allows you to set the argument value on the client-side. After an argument value has been set on the client-side, when the next Ajax callback occurs, the argument will have a new value when the server-side code is executed.

Syntax

{dialog.Object}.setArgumentValue(argName,argValue)

 

Where argName is the name of the argument you want to update. The argName must be uppercase and the argument name in the component definition must also be uppercase.

argValue is the new argument value. It is always a string value. If the argument was defined as being some other type, when the argument value is set on the server-side the value will be converted to the correct type.

UX and Grid Component - serverIsAvailable() Method - Performance - The performance of this method has been substantially improved. If the server is available, the response will be received significantly more quickly. This means that you can use a shorter timeout value in the method.

UX Component - Client-side Templating - Format Directives - New formatting options available for the client-side templates.

In all places where you can edit a client-side template, the Insert format directive hyperlink now shows two new options: 'Friendly' date format and Text format.

 

 

The available text formats are

 

If you select the 'Friendly' date format option a builder is displayed.

You can use click the Edit Date Format button to compose either a relative (e.g. 3 days ago) or calendar (e.g. this month) format.

 

 

The new 'Friendly' date formats are represented in the template as follows:

{date:dateRelative(precision,scope)}

{string:dateStringRelative(formatIn,precision,scope)}

{date:dateCalendar(type,showTime)}

{string:dateStringCalendar(formatIn,type,showTime)}

 

 

Xbasic Genie for SQL Actions - A new genie is available to help developers write Xbasic code that performs CRUD operations against SQL databases.

To access the genie, right click on white space while editing any Xbasic code.

 

 

 

The Xbasic SQL Genie screen is shown where you can select the type of SQL action you want to perform.

 

 

The screen below shows the genie for an UPDATE action.  The bottom half of the window shows the generated code based on the settings made in the top part of the screen.

 

 

Update to Security for HTTP Client Functions - The http_fetch(), http_get(), http_getpost(), and http_post() functions in Alpha Anywhere allow an optional SSL/TLS cipher list to be specified. This allows fine-grained control over TLS connection options when working with remote servers.

Some servers have recently begun rejecting connections from these HTTP functions because of their support for older, less-secure encryption ciphers. To address this, we have updated the default ciphers used when they are not otherwise specified.

These functions now use the cipher list from the httpd_defaultcipherlist() function. This is the cipher list used by the Application Server, and it is also suitable for clients.

 

UX Component - List - Detail View - Customization of Message Box - There are several message boxes that the List with Detail View displays.

The message text, title and icon for these messages can be customized in the Customization section of the Detail View pane in the List builder.

Now you can take complete control over these messages and call your own Javascript functions to display the messages.

 

 

In order to use a custom Javascript function for a message, set the message text to:

javascript:name_of_your_function

 

 

Note: If you write you own Javascript handler for any of these message boxes, you will be responsible for specifyin the Javascript to execute if the user selects the OK button (i.e. confirms, for example, that they want to revert the Detail View).

Web Control Panel - Keyboard Shortcuts - Ctrll+P can now be used to Publish a project and Ctrl+Q can now be used to invoke the Quick Publish command.

Web Applications - Active Directory - Performance of authentication against an Active Directory has been significantly improved.

Alpha Application Server - Self-signed Certificates - The way in which self-signed certificates has been changed. This will allow you to use the Development server with SSL turned on in Google Chrome.

 

Xbasic - handlebars_template_merge() Merge Function - Merges JSON data into a template using Handlebars syntax.

Handlebars is a popular, open source templating library.

This function takes JSON data and a template (that uses Handlebars syntax) and merges the data into the template.

NOTE: This is just a helper function for the low level nodeservices::handlebars.runTemplate() static method.

Example:

 

 

jsondata = <<%str%
{

    firstname:'Fred',

    lastname : 'Smith'

}
%str%

template = <<%str%
Hello {{firstname}} {{lastname}}
%str%

?handlebars_template_merge(template,jsondata)

 

= "Hello Fred Smith"

 

 

Xbasic a5_Create_PDF_From_Template() Function - A helper function for use in a Web Application. The function is used in an Ajax callback. It takes some JSON data, and a template, generates a PDF file from the result of merging the data into the template, and then returns the Javascript code necessary to download the PDF file to the client. The merge syntax can either be Handlebars, or the Alpha Anywhere client-side templating syntax.

Syntax

c JavascriptResult = a5_Create_PDF_From_Template(P e,c template ,c jsondata [,c  syntax = "AlphaAnywhere" [, c javascriptfunctions)


Where

IMPORTANT This function uses the Node PhantomJS module. This module is not installed by default (it is installed on Alpha Cloud so no action is necessary for Alpha Cloud) . You must install it by selecting to the Tools, Packages command then selecting phantomjs from the dialog. This will make PhabtomJS available while you are in development mode. You must also ensure that PhontomJS is available in your published application by going to the Web Project Properties dialog and then clicking on the smart field for Referenced Packages.

 

 

Example

Assume you have a button on a Grid or UX component that makes an Ajax callback. The purpose of the button is to generate a PDF confirmation that the client can download. Assume that the name of the Xbasic function that handles the callback is XBCallback. Here is how this function could be defined:

 

Function XBCallback as c (e as p)

 

dim jsonData as c = <<%txt%

{ Firstname: "John", Lastname: "Harris", amount: 23.45 }

%txt%

 

dim template as c = <<%txt%

<p>Dear {Firstname} {Lastname}</p>

<p>Thank you for your order in the amount of {amount:number('$#,##0.00') }

%txt%

 

dim js as c

js = a5_create_pdf_from_template(e, template, jsondata)

 

XBCallback = js

 

 

end function

 

 

UX Component - ViewBox Control - Partial Templates - A partial template is a template snippet that can be included in another template.  Partial templates are useful if your ViewBox defines multiple Layouts and each of these layouts contain parts that are the same across all of the layouts. The parts that are the same across all layouts would be defined as a partial template and then each layout can include the partial template with this template code

{*partial name_of_partial_template}

 

To define partial templates, select the Partial templates property on the ViewBox Properties tab.

 

 

 

 

Application Server for IIS - License Activation - A change was made in how the IIS Server license activation is performed. This change will improve performance for certain requests under the IIS server.

 

UX Component - HTML Editor - Image and File Upload - Amazon S3 - When you upload an image or a file from the HTML editor, you can now specify a storage connection string as the Upload Folder. If your connection string points to Amazon S3, the file will be uploaded to S3 and a URL pointing to the file on S3 will be injected into the HTML document you are editing.

This new option is especially important when running under the IIS server or on Alpha Cloud, because the option of uploading files to a folder in the webroot is not possible in these environments.

 

PhoneGap App Builder - PhoneGap Version - Added support for PhoneGap 8.0.0 which was recently added to PhoneGap Build. This version updates only the Android platform, although it is a major version update for Cordova Android from 6.3.0 to 7.0.0. The minimum Android API level required for PhoneGap 8.0.0 is 19 (KitKat) and only Gradle builds are supported. These properties will be set automatically within the PhoneGap Builder when you save or save and upload your project to PhoneGap Build when using PhoneGap 8.0.0.

If you have any trouble with plugins, you may need to use an older version of PhoneGap.

 

UX and Grid Component - Date and DateTime Fields - Date Picker - Friendly Value Display - For date and dateTime fields, you can now specify that the value should be displayed using 'friendly' text.

 

Watch Video

 

The 'friendly' text can either display the calendar value in text form (e.g. next Friday at 12:00​am, today, Thursday the 21st of February 2019) or in relative form (in 3 days, in 3 days 2 hours, in 45 seconds).

When you select a relative form the display value will automatically update at an appropriate frequency to make the passage of time. For example, if the initial display for a dateTime value is in 45 seconds, then the display will automatically update to in 44 seconds, in 43 seconds, and so on.

To turn on friendly value display for a date or dateTime field, check the Display value using friendly text? property.

 

 

Once you check this property the Friendly date display settings property will become visible. Click the smart field to open the builder as shown in the image below.

 

 

The builder allows you to make several selections to control how the value will be displayed and at the bottom of the builder you can check to see how various values will be formatted using the settings you have chosen.

 

For the Calendar option, you can specify 3 different formats that control how much detail is used in the display value (Abbreviated, Standard, Extended).

 

For the Relative option you can specify the date parts used in the display (i.e. the Scope) (Years, Months, Weeks, Days, Hours, Minutes, Seconds) and how many of these parts should be used in the display (i.e. the Precision)

 

For example, if you specify the full scope (Years to Seconds) and the full precision (-1) the relative a relative would be be displayed as:

"1 day 8 hours 50 minutes 6 seconds ago"
 

However, if you changed the precision to 2 the same value would be displayed as

"1 day 8 hours ago"

 

Javascript Library - Date Object - Several new methods have been added to the Javascript date object prototype allowing for powerful date formatting and calculations.

 

For full documentation see here.

 

Example:

Consider the following console session for a page that load the Alpha Anywhere Javascript libraries:

var d = new Date();
d.adjust('day',2);
d.toString();
"Sat Feb 03 2018 13:59:42 GMT-0500 (Eastern Standard Time)"
d.toRelative();
"in 1 day"
d.toRelative(2);
"in 1 day 23 hours"

 

Support for 4K Monitors - Improved support for 4K monitors has been added. Previously, some of the lists in various screen in the IDE would appear to be compressed. Now, these lists display normally. However, as a result of these changes, certain screens might not look as "sharp" they did before the 4K support was added.

You can use a new command line argument (-hidpi ) to turn off support for 4K monitors.

For example

alpha5.exe -hidpi

 

 

UX and Grid Component - Lookup Grid - Dynamic Filter - When you define a dynamic filter for a Lookup Grid you can now get the filter value from the result of a Javascript function. Previously you had to get the filter value from a control in the current row of the Grid (if the lookup was for a Grid field), or some control on the UX (if the lookup was for a UX field).

 

 

UX Component - Page Title - You can now set the page title property to a session variable.

 

UX Component - PhoneGap Applications - Changing URL for AJAX Callback at Run-time - When you build a PhoneGap application, the URL for AJAX callbacks is set at the time that you build the application.

You can now change this URL at runtime using the {dialog.object}._updateAjaxURL() method.

 

Syntax:

{dialog.object}._updateAjaxURL(newCallbackURL);
 

Example:

var newCallbackURL = 'https://www.myserver.com/v2';

{dialog.object}._updateAjaxURL(newCallbackURL);
 

   

printQRCode() Function - This function now has a new option to generate the QR code internally, rather than calling the Google API. Generating the QR code internally is substantially faster than using the Google API. The speed difference will be most noticeable in reports that call the prinQRCode() function many times.

Syntax:

 

Syntax

P result =  printQRCode(c value, sizeInPixels = 200, flagURLEncodeValue = .t., flagUseGoogle = .f.)

 

The sizeInPixels and flagURLEncodeValue parameter are ignored if the flagUseGoogle parameter is .f.

 

UX Component - Sample Template - A new sample template UX component is available. This template allows you to create a UX component that allows a site administrator to create new users and set user roles.

When you create a new UX, select this component from the available list of templates:

 

Here is what the component looks like at run-time:

Alpha Anywhere Server - A WARNING message will be written to the Xbasic error log when a query parameter name, etc, has a normalized name that is different from the original name. For example, a variable called 'First-Name' in a Post body gets converted to First_Name because First-Name is not a valid Xbasic variable name.
 

Xbasic - AlphaDAO - MySQL/MariaDB - Geography Queries - Portable SQL now generates the ST_Intersect() function instead of the Intersetct() function for queries that use the portable GeogLocationIsWithinPolygon() or GeogLocationIntersectsLine() functions.

PhoneGap App Builder - PhoneGap Version  - Added support for PhoneGap version cli-7.1.0. PhoneGap Build recently announced support for PhoneGap version cli-7.1.0. This release includes support for iOS 11.2 and includes Cordova iOS 4.5.4, Android 6.3.0 and Windows 5.0.0. This will resolve the plugin dependency issues with the latest plugins that require Android version 6.3.0 or greater. With the release of cli-7.1.0, PhoneGap Build should now support the latest Android plugins.

PhoneGap App Builder - Core Plugin Versions - All of the core PhoneGap plugins now include a version specification that is defined in an external file named phonegap_core_plugins.txt that is included in the PhoneGap folder of the directory that contains the Alpha Anywhere executable file. The versions specified are known to work reliably with PhoneGap cli-7.0.1 and greater. If you would like to load a different version of any core plugin, this file can be edited with any text editor. We suggest you make a backup copy of this file prior to editing.

Application Server - IIS - Crash Dump Files - In the event of a crash of Alpha Anywhere Application Server for IIS, a crash minidump file is written to the log folder. Each minidump file can have a unique name. Due to IIS' ability to recover from a crash, it may not be apparent that a crash has happened which may lead to the crash happening again causing another minidump file to be created. Since minidump files can be quite large, lots of disk space may be consumed. An IIS publish profile now has the ability to limit the amount of spaced used by minidump files and these settings are enabled by default.

 

 

These settings are also available for a published application in IIS Manager under the Logging feature in the Alpha Anywhere Application Server section:

 

 

 

 

Xbasic_execute_Javascript() Function - Execute Javascript code on the server side using the Javascript engine in Node.js

Syntax

p result = Xbasic_execute_Javascript(c jscode)



Where

If you want the Javascript code to return a value, the Javascript code must emit the value by specifying the name of the variable to emit as the last line in the Javascript code. See example below


dim js as c
js = <<%str%
var arr = [];
for(var i = 0; i < 1000; i++) {
    arr.push('String: ' + i );
}
var txt = arr.join('\n');

//we want to return the value of the 'txt' variable, so we emit it by specifying

//the variable name as the list line in the Javascript code
txt;
%str%


pr = xbasic_execute_javascript(js)
 

if pr.error = .f. then

    showvar(pr.result)

else

    showvar(pr.errorText)

end if
 

Alpha Anywhere Development Version - Built-in Version of Chrome - The AlphaAnywhere Development environment has been upgraded to build-in the latest version of Chrome. Previously an older version of Chrome was built-into Alpha Anywhere. As a result of this change certain Chrome features that were not supported in the old version of Chrome will now be available when using Chrome for Working Preview. In addition, Chrome Working Preview will be more responsive and the memory footprint used by the Development Version is reduced.

 

MFC Dependency - Starting with this build, Alpha Anywhere no longer has any dependency on the Microsoft MFC library. While the benefit of this to users may not be apparent, the benefit to Alpha Anywhere is significant and will result in new features that would not previously have been possible.

NOTE: This change should NOT have any effect on the Application Server (both the Classic and IIS servers).

 

UX and Grid Component - Javascript Actions - Duplicate Action - You can now duplicate Javascript actions.

 

 

 

Bugs

UX Component - List Control - Action Javascript - Filter List - When using Action Javascript to filter a List, the builder did not show the correct List of fields on which a search could be defined. The builder showed the fields in the underlying table(s) that the List was based on, rather than the fields in the query that the List was based on.

Grid Component - Alpha Theme - Buttons - Some buttons did not show the hover and pressed state.

Grid and UX components - Dynamic Images - Fixed a regression in dynamic images

Grid Component - Updateable Grid - Display Format and UnFormat Expressions - If an updateable grid had a Display Format expression defined for a column, then when the Grid was updated, the "old" value for that column was not first being "unformatted". As a result, the user would get a write conflict error when trying to update the field.

Grid Component - Export to Excel - Hidden Columns - Column Headings - If you have checked the option to use Grid Column Heading for columns in the Excel file, and you have also checked the option to export hidden columns, the hidden columns will now correctly use the defined Grid Column Headings.

Page Layout Component - Frames - Modern - Modern Frames were not rendering correctly.

IIS Server -- Lockout user until reset by administrator - This option did not work correctly

 

.DBF Tables - Export - SQL Server - Fixed a bug exporting .dbf tables to SQL Server.

UX and Grid Component - Javascript Syntax Checker - No longer reports an error if your Javascript code deletes a variable.

UX Component - Slider - Multi-Valued Sliders - Fixed issue when both min and max buttons were at the max value. User could not drag button to a new value.

Grid and UX Component - SVG Icons - Fixed issue with events and styling on SVG icons.

PhoneGap - InstantUpdate Feature - Fixed an issue where if you installed an app on a device that used the Instant Update feature, and you then created a new baseline app and installed it on the device without first uninstalling the original version of the app, the original version of the app (not the new version), would continue to run.

Grid, TabbedUI and UX Components - SVG Icons - onClick Event - Fixes a bug with the onClick event on an image that uses a SVG icon.

TabbedUI and PageLayout Components - Modern Frame - Show/Hide Button - Fixes a bug that was introduced in the last official update. You will need to edit the component and recalculate the controls.

UX Component - ViewBox refresh - Fixes a bug with the refresh ViewBox data option. This bug was introduced in the previous release.

Alpha Launch - UX Components - Auto-suggest Controls - Fixed an issue where Auto-suggest controls did not work in applications that were running in Alpha Launch.

UX Component - ExpandingMenu Control - Menu Data Genie - Fixed several problems when using the Menu Data Genie to define the choices shown in the ExpandingMenu control.

Tips

UX Component - Drag Scrolling vs. Vertical Scrollbar - Web Applications - In some cases you might have a UX with a Panel Card that contains more content than can be displayed in the Panel Card. Vertical scrolling is required to see the content that is not initially visible. On a mobile device, the user will scroll using drag scrolling.

In a web application, you want the user to see a vertical scroll bar.

However, if you are running the web app on a machine that is touch enabled, then drag scrolling will be enabled, and the vertical scroll bar will not be visible.

Here is how you can force the app to show a vertical scrollbar:

In the client-side onInitializeBegin event: add this code:

if( [condition you want to not drag scroll] ){
    A5.u.drag.useDragScrolling = 'never';
}

 

 

UX Component - List Control - Capture and Restore the List's Scroll Position - In some applications it might be necessary to restore the List's scroll position without actually selecting a row in the List. For example, a List may have been scrolled to a certain position, but no record in the List has been selected. A refresh operation on the List is performed, and now you want to scroll the List back to its previous position.

 

Here is how you can do this (assume that the List ID is 'LIST1'):

 


//capture the scroll position
var eleID = {dialog.object}.getControl('LIST1').contId + '.CONTENTWRAPPER';
var obj = A5.u.element.getScroll(eleID)
{dialog.object}._scroll = obj;


//restore the scroll position
var obj = {dialog.object}._scroll
var eleID = {dialog.object}.getControl('LIST1').contId + '.CONTENTWRAPPER';
A5.u.element.setScroll(eleID,obj.left,obj.top);

 

 

 

 

Xbasic - Working with .Net Arrays


Zero-based versus One-Based Indexing
By default, XBasic arrays are indexed using one-based indexing. This means that the items in the array are referenced using indexes beginning with one (1) for the first entry and continuing on with 2, 3, 4 and so on.

Other environments, including .Net arrays and collections, use zero-based indexing. This means that the first item in the array is referenced with an index value of zero (0) and continues on with 1,2,3 and so on.

When accessing an array or collection in .Net from XBasic, Alpha Anywhere automatically maps one-based indexes in XBasic array references (square brackets – “[]”) to zero-based indexes. This removes the need to remember whether an array reference is for an XBasic array or a .Net array or collection.
 

XBasic Square Bracket References


XBasic Function Calls

 


Example Usage

The interactive wndow session below now shows accessing the System::Data::DataSet Tables collection using the Item property with a numeric or string index:

 

dim ds as system::data::dataset
t1 = ds.Tables.Add("Fred1")
?t1.TableName
= "Fred1"
t2 = ds.Tables.Add("Fred2")
?t2.TableName
= "Fred2"
Tables = ds.Tables.Count
for i = 1 to Tables ; ? ds.Tables.Item[i].TableName + crlf(); next
Fred1
Fred2
?ds.Tables.Item["Fred1"].TableName
= "Fred1"
?ds.Tables.Item["Fred2"].TableName
= "Fred2"

 

 

 

Alpha Anywhere V4.5.2 - Build 4770-5018 14-DEC-2017

NOTE: This build has introduced a bug in the Javascript Action to refresh the data in a UX Component ViewBox control. After you install this update you can install a hotfix for the bug by downloading this file. Click here for instructions on how to install a htofix.

 



 

Videos

UX Component - Tree Control Populating a Tree Control using a SQL Query and Defining a Javascript Event for Each Tree Leaf Node The Tree control can be automatically populated with data derived from a SQL query. When doing this it is common to want to execute some Javascript code when the user selects a leaf node in the tree.

In this video we show how this is done.


Watch Video

Download component

Date added: 2017-11-02
UX Component Selecting Multiple Values in an Auto-suggest or Edit Combo Control The Auto-suggest and Edit Combo controls have always allowed you to set a mode where multiple selections can be made. However, each time you make a selection the pick list is closed and you must reopen the pick list before you can make your next selection.

Now, a new property in these controls allows you to specify that the pick list should stay open after each selection, allowing you to make multiple selections more easily.


Watch Video


Date added: 2017-11-15
UX Component - ControlBars Using the Built-in ControlBar Templates The ControlBar is highly configurable. This allows you to create solutions for many different use cases. There are several common patterns that developers use and for many of these patterns you can get a quick start by selecting one of the pre-defined ControlBar templates. For example, common patterns addressed by the pre-defined templates are:ControlBar with a menu button that animates in a menu from the left or right side of the Panel, ControlBar with buttons that reveal animated drop-down menus, ControlBar with buttons that allow you to create a tabbed user interface.

In this video we show how you can create a new ControlBar from a template and then continue to modify the resulting ControlBar.

Watch Video

Date added: 2017-11-28
UX Component Sample UX Component - Amazon Mobile Shopping Look Alike Example The Amazon mobile shopping App is one of the most recognizable mobile Apps. In this video we show how the look and feel of this App can be recreated using the UX component.

Open the App in a Browser

Watch Video - Overview

How the Products List is Populated
Watch Video
How the Back Button in the ControlBar is Implemented
Watch Video
How the Badge on the Shopping Cart Icon is Implemented
Watch Video
How the Search Box is Implemented
Watch Video
How the Product List Layout is Implemented
Watch Video 1
Watch Video 2
How the Detail View is Implemented using a ViewBox Control
Watch Video 1
Watch Video 2
Watch Video 3

Date added: 2017-12-13
     

 

 

 

Features

Application Server for IIS - Unlicensed Mode - The Alpha Anywhere Application Server for IIS is will now run in unlicensed mode. Five users can be active on an unlicensed server allowing development and testing to be done without needing a license. If more users are needed or the server is running in production a license is required.

This change brings the Application Server for IIS in line with the Standard Application Server for use in development and testing.

You can download the installer for the Application Server for IIS here.

 

Application Server For IIS - Installer - Pending Reboots - When you run the installer for the Application Server for IIS the installer will now warn you if your machine has any pending reboots mandated by previously installed Windows, or other, updates.

UX Component - {dialog.object}.refreshExpandingMenuData() Method - This method makes an Ajax callback to refresh the data in an Expanding Menu. This method is useful if the Expanding Menu control has assigned security or server-side show/hide expressions to any of the branches or nodes in the data for the expanding menu.

For example, after a user has logged into an application, you might want to use this method to refresh the choices shown in the expanding menu so that only choices for the user's role are shown.

Syntax:

{dialog.object}.refreshExpandingMenuData(expandingMenuIds);

 

Where:

 

UX Component - {dialog.object}.{dialog.object}.populateExpandingMenuControl() Method - This method will repopulate the data shown in an Expanding Menu control.

Syntax:

{dialog.object}.populateExpandingMenuControl(id,data)


Where:

 

Example:

				

var obj = {dialog.object}.getControl('EXPANDINGMENU1');
var data = {
	items:[
		{
			html: 'Category 1', 
			value: 'category1',
			icon: 'svgIcon=#alpha-icon-addCircleBorder:icon,24',
			action: '',
			children: [
				{
					html: 'Action 1', 
					value: 'action1',
					action: 'action:1',
					icon: 'svgIcon=#alpha-icon-bandAidCrossed:icon,24'
				},
				{
					html: 'Action 2', 
					value: 'action2',
					action: 'action:2',
					icon: 'svgIcon=#alpha-icon-bellRing:icon,24'
				}
			]
		},
		{
			html: 'Category 2',
			value: 'category2',
			action: '',
			icon: 'svgIcon=#alpha-icon-heartSolid:icon,24',
			children: [
				{
					html: 'Action 4', 
					value: 'action4',
					action: '',
					icon: 'svgIcon=#alpha-icon-map:icon,24',
					children: [
						{
							html: 'Action 4a', 
							value: 'action4a',
							action: 'action:4a',
							icon: 'svgIcon=#alpha-icon-trendingDown:icon,24'
						},
						{
							html: 'Action 4b', 
							value: 'action4b',
							action: 'action:4b',
							icon: 'svgIcon=#alpha-icon-trendingDown:icon,24'
						}
					]
				},
				{
					html: 'Action 5', 
					value: 'action5',
					action: 'action:5',
					icon: 'svgIcon=#alpha-icon-trendingDown:icon,24'
				}
			]
		},
		{
			html: 'Category 3', 
			value: 'category3',
			action: '',
			icon: 'svgIcon=#alpha-icon-shield:icon,24',
			children: [
				{
					html: 'Action 7', 
					value: 'action7',
					action: 'action:7',
					icon: 'svgIcon=#alpha-icon-shuffle:icon,24'
				}
			]
		}	],
	actions: {
		action: function(arg){
			alert('Action' + arg);
		}
	}
}
{dialog.object}.populateExpandingMenuControl('EXPANDINGMENU1',data);
					
		

sql_upsert() Function - The sql_upsert() function is a high level Xbasic function that complements the sql_update() and sql_insert() functions. The sql_upsert() function will update a record if the record exists in the database. Otherwise it will insert a new record into the database.

Syntax

    p result = sql_upsert(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_upsert(cn,tablename,fieldsValuePairs,primaryKey,primaryKeyvalue)

 

Amazon Look Alike Sample Mobile Application - A new sample template is available. The Amazon look-alike sample mobile application is a sample Alpha Anywhere application designed to show how a familiar mobile app could be built using a UX component.

You can load the sample app in your web browser, or on your mobile device from this url:

http://alphamediacapture.s3.amazonaws.com/sampleamazonlookalikeapp/index.html

 

You can watch a video showing a quick overview of the application by clicking here.

 

NOTE: When you create a new UX Component, you can select this sample application from the list of template applications.

 

The images below show screenshots from various parts of the application:

 

 

 

Main App screen. This screen shows a List control listing the various products that can be purchased. Each row in the List is rendered using a freeform layout template that uses Alpha Anywhere's client-side templating feature to create a highly customized layout.

 

 

Navigation menu. The navigation menu is shown when the user taps on the menu icon in page header. The menu it rendered using the Expanding Menu control.

 

 

This is the Detail View for a particular product. This Panel is shown when the user taps on a row in the List. The ViewBox control is used to render the Detail View and the template that is used in the ViewBox control to render the Detail View makes extensive use of client-side templating features.

 

 

This is the scrolled view of the Detail View for a particular product.

 

 

This is the shopping cart showing a list of products that have been added to the cart. This Panel also uses a List control with a freeform Layout to display each row in the shopping cart.

Notice that the shopping cart icon in the header has a badge indicating how many products are in the cart.

 

 

This screen shows the page that is displayed when the user taps on the Quantity button on the product detail page.

 

After the user selects a quantity, the Quantity button on the product detail page is updated to show the selected quantity.

 

Understanding How the App Was Built

The entire App was built using a single UX component as shown in the image below.

 

 

The key building blocks of the app are:

 

The app structure is shown below:

 

 

Each 'page' in the App is contained in a Panel Card and the Panel Cards are contained in a Panel Navigator. The Panel Navigator has been configured as "Programmatic" - meaning that the user cannot swipe left-to-right, or right-to-left on a Panel to navigate to the next Panel. Instead Javascript code is used to control which Panel is shown in the Panel Navigator.

The Panels in the App are:

 

NOTE: This demo app is not a complete application.  It is only meant as a teaching tool to show how a compelling mobile user interface can be created using the UX components. For example, the navigation menu displays, but when you make a selection from the menu, the product list is not updated.

 

Videos Explaining How Various Features Are Implemented

 

How the Products List is Populated

    Watch Video

How the Back Button in the ControlBar is Implemented

    Watch Video

How the Badge on the Shopping Cart Icon is Implemented

    Watch Video

How the Search Box is Implemented

    Watch Video

How the Product List Layout is Implemented

   Watch Video 1

   Watch Video 2

How the Detail View is Implemented using a ViewBox Control

   Watch Video 1

   Watch Video 2

   Watch Video 3

 

JSON_shred() Function - This function has been enhanced. The input schema that describes how the JSON should be shredded is now optional. Also, the function can automatically inject linking values into the JSON if the JSON does not already have appropriate linking values. If the input schema is not specified then linking values are automatically injected.

The purpose of the JSON_shred() function is to take a complex JSON document (with one or more nested arrays) and decompose the JSON into multiple flat arrays, none of which have nested arrays.

The new syntax for the function is:

 C result =  JSON_shred(C json [,C schema [,C topArrayName [,L flagAddSurrogatePrimaryKey [,C surrogateKeyName ]]]])

 

Where:

 

Example:

dim json as c 
json  = <<%str%
[
    {"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}
        ]
    }
]
?json_shred(json)

{
    "__top": [
        {
            "__surrogatePrimaryKey": "475750b196554658b2518fde4bfaec6e",
            "Firstname": "John",
            "Lastname": "Smith",
            "City": "Boston",
            "State": "MA"
        },
        {
            "__surrogatePrimaryKey": "c970381d48aa4abfa92d0f46d02ead27",
            "Firstname": "Henry",
            "Lastname": "Rhodes",
            "City": "New York",
            "State": "NY"
        }
    ],
    "Children": [
        {
            "ParentLinkingValue": "475750b196554658b2518fde4bfaec6e",
            "LinkFieldName": "__surrogatePrimaryKey",
            "__surrogatePrimaryKey": "16963be3261c4d82a50152dfb18f9ff0",
            "Name": "Callie",
            "Age": 5
        },
        {
            "ParentLinkingValue": "475750b196554658b2518fde4bfaec6e",
            "LinkFieldName": "__surrogatePrimaryKey",
            "__surrogatePrimaryKey": "556ed6b0264544bd93ebe1382578347a",
            "Name": "Griffin",
            "Age": 3
        },
        {
            "ParentLinkingValue": "475750b196554658b2518fde4bfaec6e",
            "LinkFieldName": "__surrogatePrimaryKey",
            "__surrogatePrimaryKey": "32558171e17c41f88dffc6594b4f73c3",
            "Name": "Luke",
            "Age": 1
        },
        {
            "ParentLinkingValue": "c970381d48aa4abfa92d0f46d02ead27",
            "LinkFieldName": "__surrogatePrimaryKey",
            "__surrogatePrimaryKey": "7ea305b5205844c5abde8728b68f08ae",
            "Name": "Howard",
            "Age": 15
        },
        {
            "ParentLinkingValue": "c970381d48aa4abfa92d0f46d02ead27",
            "LinkFieldName": "__surrogatePrimaryKey",
            "__surrogatePrimaryKey": "98ff8b3ccc1b4fa1a79bdee2620daee2",
            "Name": "Robert",
            "Age": 11
        }
    ]
}

%str%

 

Dynamic Storage Connection Strings - Storage - SQL Server Reporting Services (SSRS) - Alpha Anywhere has had the concept of dynamic connection strings for AlphaDAO connection strings for some time now. But dynamic connection strings for storage and SSRS did not exist. A dynamic connection string is particularly useful in multi-tenant SaaS applications. Now, you can define dynamic storage connection strings for both storage and SSRS.

A dynamic connection string will resolve differently based on a the value of a session variable.

To define a dynamic storage connection string, your named connection string must start with DynamicConnection_. For example: DynamicConnection_myS3Storage.

You must also have a session variable named

__protected__<name>

where <name> is the text to the right of DynamicConnection_ in the named connection string.

 

So for example, if your named connection string is:

DynamicConnection_myS3Storage

You would need a session variable called:

__protected__myS3Storage

 

When the named connection string is resolved, it will resolve to the value of the __protected__myS3Storage session variable.

 

Xbasic csv_to_json() Function - Escaping Doublequotes - This function now supports two different methods for escaping double quotes.

 

The default is use use two double quote characters. .e.g

"fred","smith","the ""computer"" store","boston"

 

But you can also use Javascript style escapement. e.g.

"fred","smith","the \"computer\" store","boston"

 

Syntax:

c json = csv_to_json(c csvtxt, c escapeMethodForQuotes)

 

Where:

 

 

UX Component - Frame Container - Modern Frames - If a modern frame container is configured to have a show/hide button, you can specify that if the current frame is opened and another frame is subsequently opened, the current frame will be closed.

 

 

UX Component - Mobile Applications - Panel Card - Drag Scrolling - Previously if you dragged on an input control in a Panel Card, the Panel did not scroll. Now, as long as you have not actually given focus to the input control (i.e. the keyboard has not come up) then the panel will still scroll.

 

 

UX Component - ControlBar Builder - User-Defined Templates - You can now save a ControlBar that you have designed as a template. Your user-defined templates will be listed when you click the Load Sample ControlBar hyperlink on the Home pane of the ControlBar builder.

 

 

To save the toolbar that you are currently editing in the ControlBar builder as a template, click the Save ControlBar as a Template hyperlink on Home pane of the ControlBar builder.

 

The dialog shown below will be displayed where you can give the template a name and a description. The description can use HTML markup.

 

 

After you have saved the template, you can save an image of how the ControlBar looks. The image filename that you must use is shown in the next dialog.

When you use the Load Sample ControlBar command the image you have saved will be shown in the list of available templates, making it easier to choose the template you wish to use.

 

 

 

Application Server - Publishing - The publish genie now has an option on the 'Clear Publishing History' button to clear the publish history for just the currently selected publish profile. The ability to clear all history is still available as an option.
 

UX Component - New Starter Template for Mobile App - A new starter UX template is available. The template, called MobileAppFramework_FlyInMenu_to_select_Active_Panel ) is a Panel Navigator, with multiple Panel Cards, and a Control Bar with a menu button that displays an expanding menu that flies in from the left.

 

 

 

Xbasic - Arrays - Change_type() Method - Changes the data type of an Xbasic array.

When you create an Xbasic array by parsing some JSON text, the array's type is set to 'A'. This is because a JSON array can contain items that are of different type.

For example, consider the following code

 

dim json as c

json = <<%txt%

[

    {name: "fred"},

    3

]

%txt%

 

dim p as p

p = json_parse(json)

 

If you were to check the type of p[1], (using typeof(p[1]) ), it would return 'P'.

However, if you were to check the type of p[2], it would return 'N'.

So the array elements in the array can be of any type. You can also dim an array where the items can be of any type like as follows:

dim array1[10] as A

 

Now consider a JSON string that defines an array in which all items are of the same type:

 

dim json as c

json = <<%txt%

[

    {name: "fred"},

    {name: "john}

]

%txt%

 

dim p as p

p = json_parse(json)

 

In this case all of the elements in the array are of type 'P'.

However, if you insert or append elements to the array, the new elements will be of type 'N' and not 'P' as you might have expected. This is because the internal type of the array is 'A' (as is always the case when an array is created by parsing a JSON string).

In some cases you will want to change the type of the array to a specific type so that items inserted into the array, or appended to the array are also of the same type as the other items in the array.

For example:

 

dim json as c

json = <<%txt%

[

    {name: "fred"},

    {name: "john}

]

%txt%

 

dim p as p

p = json_parse(json)

dim result as c

result = p.change_type("P")

if result <> "" then

    ui_msg_box("Error","Could not change array type: " + result)

end if

p.insert(1,1)

?typeof(p[1])

= "P"   '<<----- would have been 'N' had the .change_type() method not been called!

 

UX Component - ControlBar - ControlBar Builder - Pre-defined Templates - New pre-defined templates are available when you create a new ControlBar from a template and the template picker has been enhanced to show a preview of each template.

Watch Video

 

When you create a  new ControlBar, you can set all of the properties in the ControlBar by selecting a template (i.e. sample ControlBar). To select a template, click the Load Sample ControlBar hyperlink on the ControlBar builder Home pane.

 

 

When you click the hyperlink a window showing the templates is shown:

 

 

 

 

UX Component - ControlBar - DisclosureButtons - Disclosure Position - Three new disclosure positions are now available: flyout, flyout-element and flyout-element-cover. Using these positioning directives, it is possible to create controlbars with dropdown menus. See example below.

 

 

 

 

In the image below, the button on the toolbar opens another disclosure positioned using the flyout-element position.

 

 

 

NOTE Sample ControlBars that use the new flyout-element position directive can be seen by selecting the Load Sample ControlBar hyperlink on the ControlBar builder Home tab.

 

sql_import() function - Upsert - The SQL_Import() function is a helper function that imports new records into a SQL table. It is called a 'helper' function because it is an alternative to writing the low level Xbasic AlphaDAO commands to import data. This function now supports both 'insert' and 'upsert'. An 'upsert' performs an update on existing records and an insert if there is no existing record.

The syntax for the function is now:

p result = sql_import(connectionString as c, tableName as c , tableOwner as c, csv_or_json_data as c , replicateIdentity = .f., inputfield_to_sql_table_column_map = "", action="insert", primaryKey = "")

 

Where:

 

 

Example

p = sql_import("::name::myconnstring","table1","","c:\data\datatoimport.xlsx",.f.,"","upsert","id")


 

UX Component - List Control - Freeform Layout - List Item Footer - Freeform layouts now support the List-item Footer property. The state of the list item footer can be toggled on each row from open to closed, or vice versa using the <listObject>.toggleRowExpander() method.

 

UX Component - Multi-select Token Control - Keep List Open - A new option has been added to the Multi-select Token Control to keep the pick list of choices open after the user makes a selection.

 

UX and Grid Components - Arguments - Upper Case Names - When you add a new argument or rename an existing argument, the argument name is now converted to uppercase. By using the convention that argument names are always uppercase, a class of bugs that can result when the same argument name is used in multiple linked components is used and in each of these components, the argument name is defined using a different case.

UX Component - List Control - Detail View - onStateChanged Event - A new event has been added to the List control. The onStateChanged event fires when the Detail View goes from clean to dirty, or vice versa.

UX Component - Auto-Suggest and Edit-Combo Control - Multiple Selections - Keep List Open - The Auto-suggest and Edit Combo controls have always allowed you to set a mode where multiple selections can be made. However, each time you make a selection the pick list is closed and you must reopen the pick list before you can make your next selection.
 
 Now, a new property in these controls allows you to specify that the pick list should stay open after each selection, allowing you to make multiple selections more easily.

 

 

If you have turned on multiple selections, you can delete previously made selections by either backspacing to delete one character at a time, or use Shift+Cntrl+Backspace to delete complete selections.

If you have turned on multiple selections, you can prevent the user from selecting the same value more than once by setting the Allow duplicate selections property.

 

PhoneGap App Builder - Core Plugins And Some Key 3rd Party Plugins - Added a version specification to all core and some essential 3rd Party Plugins plugins to resolve problems with updated plugins and Android on PhoneGap Build.

Many of the core plugins were updated recently and specified a requirement for a minimum PhoneGap version of Android 6.3.0. PhoneGap Build cli-7.0.1 (the latest release supported by PhoneGap Build) includes Android PhoneGap Version 6.2.3 so the changes to the plugins configuration files causes the build to fail on the current release on PhoneGap Build. This change ensures that PhoneGap Build will work with the specified plugins.

PhoneGap App Builder - 3rd Party Plugins - Added support for the PDF417-Phonegap plugin. This plugin is a small but powerful scanner that handles bar code and PDF417 scanning.

 

Alpha Style Sheet - SVG Icons - Several new SVG icons have been added to the Alpha stylesheet. These are:

 

 

 

UX Component - List Control - List Virtualization - onNavigate Event - The onNavigate event's behavior is different depending on whether the list is virtualized or not. If the List is not virtualized, the onNavigate event fires when the List is scrolled. If it is, then the onNavigate event fires when the user navigates to a new page of records.

In order to allow the behavior of this event to be consistent regardless of the virtualization option, a new property has been added to the list. The onNavigate event behavior property can be set to Navigate, Scroll or Both. When set to Scroll, the behavior is the same as a non-virtualized list.

 

 

Application Server - OpenSSL - Updated to build 1.0.2m of OpenSSL.

Web Security - Utility for SQL tables in Standard Server - A revised utility has been added to the 'Utilities' option in the Web Security menu when using SQL based tables on the standard server. The new utility will still verify if the defined security tables can be found, but has additional options.

If the security system connects to the SQL tables with Active Link tables, the utility has an option to 'Validate Field Maps'. The action will verify if the field map saved in the Active Link tables map to the correct field names in the SQL table.

The option will only check a single table if one is selected. If a table is selected, the option 'Clear Selected' will remove the selection and allow checking all tables.

The option 'Show Connection String' will show the actual connection string used by a table if the table is selected. The normal configuration would have the same connection for all tables.

Errors cannot be corrected if using Active Link tables, but the utility will show a message on close if any errors were found

Changes can be made and saved if the security system is using a 'DataLink' file in place of Active Link tables. The option to 'Show Connection String' is still shown, but the option to 'Validate Field Maps' will open a genie to remap the fields if any errors were found in the existing map. The genie will only allow selecting fields that are of the correct data type and length.

A new option is shown to 'Change Connection String'. This shows a list of available connections and can change the connection for all tables. The utility will check if the current tables exist in the new connection and will run the validation option is tables with the same names are found.


Another new option is 'Select New Table'. This will show a list of tabled found in the SQL database that uses the connection. When a table is selected, the field map validation will run to allow remapping the field as needed. This option can also create a new table in the target database, but will not populate the new table with any data.

Changes can be saved by the 'Save Changes' button which is activated if any changes were made.

 

PhoneGap App Builder - iOS Launch Images - Added static (legacy) image generation support for iPhone X and the 10.5 inch iPad Pro launch images. If you are planning to support the new iPhone X and/or the 10.5 inch iPad Pro, you previously had to use storyboard images for your app launch image. This is no longer the case. If you choose to use static (legacy) launch images, then the appropriate size is automaticaly generated for the iPhone X and the 10.5 inch iPad Pro. Remember to center weight your image (look at Twitter's launch image) and verify that each generated image looks correct. The iOS launch images can be found in the PhoneGapProjects\ProjectName\www\res\screen\ios folder.

PhoneGap App Builder - PhoneGap Project Template The PhoneGap new project template was modified to support better code formatting for legacy (static), iOS Storyboard and Android 9-Patch launch images. These sections are dynamically replaced within the PhoneGap config.xml file when the launch and storyboard images are generated by the PhoneGap App Builder genie.

UX Component - List Control - No Records in List HTML - Specify Message Using Javascript - The List Builder allows you to specify a message to show in the List if there are no records in the List.

Previously, you could only define some static HTML to display. Now you can specify some Javascript code to return the message to be shown. To specify that the message is returned by some Javascript code, prefix the message with javascript:

For example, assume that you had defined a local function called norecordsmessage in the List Builder  (Turn on the optional Javascript tab in the List Builder and define a function at the This object level).

You would set the No Records HTML to:

javascript:this.norecordsmessage()

 

You can also include a5-item attributes in the message text. For example, assume you wanted to display a message if the user tapped on the no records message. Assume also that the message was to be returned by a local function called norecordsmessage(). Here is how this could be done:

First, define an item in the List Builder's Items tab (by turning on the optional Template Items tab - check the box at the bottom of the List Builder window. For example, you could define an item called 'norecords' that displayed a message when clicked.

Then define the norecordsmessage function as follows:

 

return '<span a5-item="norecords">List has no records</span>'

 

 

Xbasic Functions - convert_ts_to_js() - Converts TypeScript files (with .ts extension) to Javascript files (with same name, but .js extension)

 

Syntax

result = convert_ts_to_js(files)

 

Where

 

UX Component - Client-side Event - OnBeforeCreate - Fires before any code to render the UX is executed. Allows you to change settings in the Alpha Anywhere Javascript library that affect how the UX is rendered. For example you could override the definition of the A5.listBox.prototype.populate() method in this code.

NOTE: The {dialog.object} object cannot be referenced in the code for this event handler as it has not yet been instantiated.

Xbasic - a5_XbasicTreeToJSONTree() Function - This function, which takes a CRLF delimited string, and converts it into a complex JSON structure that can be used to populate a Tree or Menu control, has been enhanced and now allows you to define the Javascript code to execute when the user clicks on a tree leaf.

 

Consider the following example, which produces a tree showing Countries, Cities, then ContactName. ContactName is the tree leaf. When the user clicks on a leaf, you want to call a Javascript function. The data for the tree should come from a SQL query.

Here is how this is achieved:

 

dim cn as sql::Connection
cn.open("::Name::northwind")
cn.PortableSQLEnabled = .t.
dim sql as c
dim flag as l

'define the sql query that will return the data in the correct format
sql = <<%str%
select country, city, concatenate(contactname,'```onclick:findCustomer(','''',customerId,''')') from customers where not (country = '') order by country, city, contactname
%str%

flag = cn.Execute(sql)
dim txt as c
txt = cn.ResultSet.tostring(-1,-1,.t.,"|")
'this will generate a crlf delimited string like this
'France|Nantes|Carine Schmitt```onclick:findCustomer('FRANR')
'France|Nantes|Janine Labrune```onclick:findCustomer('DUMON')
'France|Paris|Dominique Perrier```onclick:findCustomer('SPECD')
'France|Paris|Marie Bertrand```onclick:findCustomer('PARIS')
'France|Reims|Paul Henriot```onclick:findCustomer('VINET')'

'notice that the tree branches are separated by a | character.
'the leaf nodes specify an onclick event.
'the syntax for the onclick event is ```onclick:javascript to execute

'notice that we pass the primary key to the leaf as the argument to the function

txt = a5_XbasicTreeToJSONTree(txt,"|","html")

 

 

The resulting JSON string is:

 

[
  {
    "html": "Argentina",
    "children": [
	          {
		    "html": "Buenos Aires",
		    "children": [
			          {
				    "html": "Patricio Simpson",
				    "onClick": function() { findCustomer('CACTU')}
				   },
				   {
				     "html": "Sergio Gutiérrez",
				     "onClick": function() { findCustomer('RANCH')}
				   },
				   {
				     "html": "Yvonne Moncada",
				     "onClick": function() { findCustomer('OCEAN')}
				   }				
		]
           }
   }......
]
			

UX Component - Spreadsheet Input Control - Get and Set Column State - Two new methods have been added to the control

 

Example

 

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

var json = obj.getColumnState()

//store the column state in local storage

localStorage.setItem('columnstate',json);

 

 

 

//restore the column state

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

var json = localStorage.getItem('columnstate');

obj.setColumnState(json);

UX Component - List Control - Media Files - Events - In a disconnected application you can configure the media files in the List to download to the mobile device and be stored in the filesystem on the device. The UX component will fire the beforeMediaFiles download and afterMediaFilesDownload events. Previously, even if there were no media files to download, these events would fire. Now, if there are no media files to download a new event, onNoMediaFilestoFetch will be fired.

 

UX and Grid Components - Reports - Send via Email - A new option in the Action Javascript command to display a report, now allows you to email the report rather than displaying it.

 

 

When you check the Email report property the Email settings property is shown when you can configure the email that will be sent with the report as an attachment.

The Email Settings dialog is shown below.

 

 

UX Component - Frame Control - Modern Frame - Set Open/Close State Programmatically - A new method allows you to set a modern frame to be open. closed, or to toggle its state.

The method, {dialog.object}.frameOpenStateChange(frameId, state) takes two arguments:

Bugs

Alpha Style - IE 11 - Browser Hang - Under some circumstances it was possible to hang IE 11 when using a Grid or UX component that used the Alpha style. The Alpha style uses SVG icons for all icons shown in the components. If a button had an SVG icon and you clicked directly on the icon, and as a result of the click, the icon was replaced (perhaps with a disabled version of the icon), IE11 would occasionally hang.

 

UX Component - SpreadsheetInput Control - Column Width - The column width property was not being honored when the control was rendered.

Alpha Anywhere Server for IIS - Install Error - An install error introduced in approximately build 4710 has been corrected.

bus_days_between() Function - Fixed a bug in this function when using a .dbf table for the list of holidays. The bug did not exist when using a SQL table for the holiday list.

AlphaCloud - All Components - Local CSS - SASS - If any local CSS defined in a component used SASS syntax, the definition was not properly converted to CSS. This bug was a recent regression.

SASS Processing - This build now includes a new version of the SASS processor that converts SASS to CSS. This new SASS processor can report errors in the input SASS file.

UX and Grid Components - Client-side Watch Expressions - Stack depth exceeded Error - Certain types of client-side watch expression (for example myFunction('{grid.componentName}'), would cause a 'stack depth exceeded' error message when the component was saved.

Page Layout Component - Fixed an issue when a Page Layout component contained a Grid component.

Tips

UX Component - Edit-Combo Control - Automatically Displaying the List of Choices - In some situations you might want the pick list for an edit-combo box to be displayed automatically as soon as the user gives focus to the control.

This is easily done by getting a pointer to the button that opens the pick list and then calling the object's .click() method.

For example, assume that the variable name for your edit-combo control was MYEDITCOMBO. You could add this code to the control's onFocus event:

 

ele = $('DLG1.V.R1.MYEDITCOMBO.BUTTON');
ele.click()

 

However, on a mobile device this will not work because the events are all abstracted on a mobile device. To get the above code to work on a both a standard desktop browser and a mobile device change the code to use the $e.execute() method, which allows you to execute abstract events.

 

ele = $('DLG1.V.R1.MYEDITCOMBO.BUTTON');
$e.execute(ele,A5.d.evnts.click);

 

 

 

 

Alpha Anywhere V4.5.1 - Build 4642_4981 12-Oct-2017

Videos

UX Component - List Control Reorder List Rows by Dragging Row to a new Group when Client-side Grouping is Enabled When client-side grouping is enabled in a List, the order of the rows in the List is determined by the sort expression that is applied to the data so that the List data can be grouped correctly. That means that if you drag a row to a new position, and then drop, the row will immediately snap back to its original position (because the client-side sort will be re-applied to the List data).

However, you might want to use drag reorder to move a row from one group to another. This is done by changing data in the row that is moved so that in the onMoveEnd event, the data in the row is updated and then, when the client-side sort is applied to the List data, the row will continue to appear in the target group.

In this video we show how a list of customers, grouped by Country, can be re-arranged by dragging a customer from one country to another.

Watch Video

Download component

Date added: 2017-09-14
UX Component - Spreadsheet Input Control Using the Spreadsheet Input Control In certain applications where a user needs to input data quickly, a spreadsheet style data entry control can be very efficient.

In this video we show how you can add a Spreadsheet Input control to a UX component.

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

Download component

Date added: 2017-10-02
     

Features

{dialog.Object}.frameOpenStateChange(frameId,state)"
a2[..].description = <<%html%
Sets the open/closed state of a Frame control. Frame control must be configured as a 'Modern' frame and must have
the 'Has show/hide buttons' property checked. Where: <br>
 

 

 

 

 

PhoneGap App Builder - Added PhoneGap CLI Support for Cordova Version 7.0.1  - Added support within the PhoneGap CLI builder for Cordova Version 7.0.1, Android Studio 2.3.3 and XCode Version 9.0.

Handling of Launch Images, Splashscreens and Icons was modified and tested with the latest releases of PhoneGap, Android Studio and Xcode.

Note: The script for Android Studio 2.3.3 was modified to kill all aapt.exe (Android Asset Packaging Tool) instances that remain open after a successful Android Cordova Build. This appears to be a bug in the Windows Android SDK or Cordova 7.0.1.

 

Xbasic - JSON - extension::json::ForEachString() Method - This method is similar to the Xbasic *for_each() function, except that it is designed to operate on property values in a JSON string.

 

For example:


dim json as c = <<%str%
{
    "name" : "name Smith " ,
    "alias" : [ "jj " , "name " ] ,
    "id"     : {
        "name" : "name_01 "
    }
}
%str%
 

Notice that the string 'name' appears in the above JSON as both a property name and also in a property value.

We want to change 'name' to 'John', without changing the names of any of the property values. Also, note that each property value has trailing spaces.
 

'change 'name' to 'John'

json = extension::json::ForEachString(json,"strtran(value,'name','John')")
 

'trim trailing spaces from each property value
json = extension::json::ForEachString(json,"trim(value)")
 

Result:


{
    "name" : "John Smith" ,
    "alias" : [ "jj" , "John" ] ,
    "id" : {
        "name" : "John_01"
    }
}
 

Notice that none of the property names were changed.

 

UX Component - SpreadsheetInput Control - A new control type is now available in the UX component. The SpreadsheetInput Control allows you to display a spreadsheet style grid of cells in which the user can enter/edit data. The spreadsheet columns can be resized and also reordered.

For example, in the image below, a SpreadsheetInput Control has been defined with 3 columns and 5 rows. The user can use keyboard navigation (tab, shift-tab, up and down ) to move between the cells in the control.

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

Download component

When the UX is submitted, the data in the control is submitted as a JSON string.

 

For example, if the control had been filled in as shown below:

 

then, when the UX was submitted, the data submitted for the SpreadsheetInput control would be as string with this value:

 

"[{"field1":"alpha","field2":"beta","field3":""},{"field1":"","field2":"","field3":"gamma"}]"

 

 

To, add a SpreadsheetInput control to a UX, select the [More..] control from the Data Controls section of the UX toolbox.

 

 

 

Then select the SpreadsheetInput control from the list.

 

 

To configure the control, click the smart field for the Control properties.

 

 

 

This will open the genie where you can configure the control.

 

 

The most important property to configure is the Column definitions property. This property allows you to define the columns shown in the SpreadsheetInput control.

Click the smart field to open the editor, as shown in the image below.

 

 

You can add columns one at a time by clicking the Add Column button. You can click the Quick Select using Genie hyperlink to add columns to match the fields in a SQL table.

 

The onNavigate property allows you to specify Javascript code to execute when a cell in the control gets focus.

 

Defining Row Prefixes and Suffixes

You can define row prefixes (i.e. row labels) and row suffixes so that the control looks even more like a spreadsheet. The prefix displays at the left side of each row and the suffix displays at the right edge of each row. For example, in the image below a prefix has been defined to show the row number.

 

Here is how the control is configured to show the prefix:

The Has row prefix (label) property is checked.

The Row prefix HTML is a defined using Javascript code that can reference row - the zero based row number and data - the array of data with which the control is populated. To show the row number as the row prefix, the Javascript for the Row prefix HTML is set to:

return (row + 1);

 

The Width property is set to 50px to set the width of the prefix column.

The Style property is set to font-size: 75%; text-align: right; to make the font slightly smaller than the text in the input control and also to right align the text in the row labels.

 

 

 

Methods

 

Since the SpreadsheetInput control is a standard UX Data Control, you can use the {dialog.object}.setValue() method to populate the cells in the control with data and the {dialog.object}.getValue() method to get the data in the control. When you use these methods, the value is a JSON string.

For example, if the SpreadsheetInput  control has 3 columns (field1, field2 and field3), you could use the following Javascript to populate the control:

var _data = [

    {field1: 'alpha', field2: 'beta'},

    {field2: 'gamma', field3: 'delta'},

    {field3: 'epsilon'}

];

var _string = JSON.stringify(_data);

{dialog.object}.setValue('mySpreadsheetControl',_string);

 

.setColumnAndPopulate() Method

You can also dynamically change the columns shown in the control to match the columns in some data with which you want to populate the control. For example, say that the SpreadsheetInput control was initially configured to show a single column (say 'Field1') and you wanted to populate it with the the following data:

 

[

    {firstname: 'John', lastname: 'Smith', city: 'London'},

    {firstname: 'Harry', lastname: 'Jones', city: 'Boston'},

    {firstname: 'Winston', lastname: 'Flowers', city: 'Harare'}

]

 

You can call the control's .setColumnsAndPopulate() method.

For example:

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

var _data = [

    {firstname: 'John', lastname: 'Smith', city: 'London'},

    {firstname: 'Harry', lastname: 'Jones', city: 'Boston'},

    {firstname: 'Winston', lastname: 'Flowers', city: 'Harare'}

]

obj.setColumnsAndPopulate(_data);

 

 

The columns shown in the control will now be 'firstname', 'lastname' and 'city'.

 

.getColumnState() and .setColumnState() Methods

Since the columns in the Spreadsheet input control are resizeable and reorderable, you might want to capture the state of the Spreadsheet input control's column layout so that you can restore it the next time the user runs the component.

 

For example

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

'get the spreadhseet control state as a JSON string

var json = obj.getColumnState();

 

'store in local storage

localStorage.setItem('spreasheet_01_State',json);

 

Then, to restore the state

var json = localStorage.getItem('spreasheet_01_State');

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

obj.setColumnState(json)

 

 

 

UX Component - Client-side Events - onWatchEvent - A new client-side event has been added. The onWatchEvent fires when any of the client-side watch events (show/hide, enable, readOnly) fires. For example, when a client-side show/hide expression on a control is executed the event is fired. The type of event, the name of the control on which the expression is being evaluated and the result of the expression are passed into the event handler.

Possible values for the type parameter passed to the event handler are

 

 

UX Component - Set Tab Order - By default, the tab order in a UX component is the same as the order in which the controls were defined. However, you can now define a custom tab order without having to reorder the controls in the builder.

 

To open Tab Order dialog, select the Set tab order... menu item in the dropdown Menu

 

 

 

 

In the dialog, select the tab order that you want.

 

 

 

UX Component - List Control - Event - onBeforeListClear - Fires before the list data is cleared.

 

UX Component - Client-side Events - canAjaxCallback and onAjaxCallbackComplete - callbackId Parameter - A new parameter is available in the e object passed to these events. The e.callbackId property is a GUID that identifies the callback and allows you to match the onAjaxCallbackComplete event with a particular AjaxCallback.

UX Component - List Control - .setDisplay() Method - This method has been enhanced and can now be used to operate on List columns.

For example, the following method will hide columns 0, 1 and 2 in a columnar List layout:

 

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

lObj.setDisplay('column',{column: [0,1,2], display: [false,false,false]})

 

 

Documentation - List Control - The documentation system now contains in-depth description of the List object. Note that in the documentation the List is referenced as ListBox, its official internal name.

NOTE: The documentation referenced here does not include the List control methods that are only available when the List has a Detail View. These methods are currently documented here.

 

PhoneGap Builder : Added support for PhoneGap Build Version cli-7.0.1

PhoneGap Build recently added support for PhoneGap 7.0.1 which aside from security and performance enhancements includes some important changes behind the scenes in the build infrastructure. There are now two distinct builders that can be used by PhoneGap Build, the original and the new and this option is exposed in the Alpha PhoneGap App Builder as the PhoneGap Builder Version property, values 1 and 2. By default this value is set to 1 which will use the original builder which will most likely be deprecated at some point in the future. If you set this option to 2, then the new builder will be used by the PhoneGap Build Service.




If you plan to support the new iPhone X, you will need to use storyboard launch images (now supported, see below) and you must use cli-7.0.1 and PhoneGap Builder Version 2.

Please see the PhoneGap Build Blog PhoneGap 7.0.1 Release Notes for all of the details on the cli-7.0.1 release.

PhoneGap Builder: Added support for iOS Storyboards and Android 9 Patch images

With the release of PhoneGap Build cli-7.0.1, support for iOS Launch Storyboards is now inherently supported within the new builder. If you plan to support the new iPhone X or the iPad Pro 12.9’s native resolution or split screen/slide-over multitasking, you’ll need to use iOS storyboard launch images.

Launch storyboard images are sized based on scale, idiom, and size classes. They supports all devices, and can be used with split-screen/slide-over multitasking.




Apple is moving away from legacy launch images. There is no official support for providing a native-resolution launch image for the iPad Pro 12.9 or for providing launch images that work with split-screen multitasking or slide-over. If your app doesn't need to support these contexts, then you can continue to use legacy launch images for as long as you like.

The preferred method of providing launch images is to use a launch storyboard.

These are similar to the legacy launch images, but there are crucial differences:



Designing launch storyboard images (Applies to Android 9-patch images as well)

The key to designing a launch storyboard image is understanding that the edges of the image will almost certainly be cropped. Therefore, one should not place any important information near the edges of any images provided to the launch storyboard. Only the center is a safe area, and this all but guarantees that following Apple's advice of presenting an unpopulated user interface will not work well.

Instead, the following tips should enable you to create a launch image that works across a multitude of form factors, viewports, and orientations:



Of the images supplied to the launch storyboard, iOS will choose the image that best matches the device and viewport and render that image.

The Alpha PhoneGap Builder will generate all of the rerquired storyboard images from a single user supplied square 2732px x 2732px (min) png file. The iOS storyboard file is generated from the image specified for the Portrait splash screen.

Changes to the PhoneGap Build config.xml file

The Alpha Anywhere PhoneGap App Builder will automatically remove and replace certain sections of the config xml file that reference legacy splashscreens, storyboards or Android 9-patch images, based on the properties set within the builder. All of the sections are marked with XML comments and those comments need to remain in place. If legacy splashscreens are specified then the sections for the storyboard and Android 9-patch images are removed, but the comment tags are left intact. If storyboards and Android 9-patch images are specified, then the legacy sections are removed.

If you are modifying an older PhoneGap project with a legacy config.xml file (the comment tags we added around April of 2017), these sections will be added to the older config.xml file and a message will be displayed, indicating that an older config.xml file was modified. In this case, you should edit the config.xml file to remove the older legacy splashscreen section, prior to submission to PhoneGap Build.

 

Grid Component - Arguments - Session Variables - Arguments that are bound to session variables are now updated on every Ajax callback. Previously, the argument values were only set when the Grid was initially run.

Xbasic - email_send_sparkpost() Function - SparkPost Options - SparkPost allows you to specify options, such as open_tracking and click_tracking (see SparkPost API documentation).

You can now pass in these options to the email_send_sparkpost() function as shown below:

 

dim ms as p

'xbasic commands to set required properties of mp not shown

ms.options.open_tracking = .f.
ms.options.click_tracking = .f.
dim key as c = "your sparkpostkey"

dim pp as p
pp = email_send_sparkpost(key,ms)

 

UX Component - DropdownBox Controls - Client-side Data Cache - DropdownBox Box controls can now be populated with data that is stored in the Client-side Data Cache.

This is particularly useful in the case of mobile applications that are deployed as PhoneGap applications, or in static HTML applications that use the Application Cache, because in these applications the DropdownBox controls are populated with data at the time the application in built. When the applications are run, the DropdownBox controls will still continue to show the data that they were populated with at build-time.

In many cases it will be desirable to update the choices shown in a DropdownBox with up-to-date data and to continue to use the most up-to-date data available when the App is launched, even if there is no connection available at that time.
To solve this problem, you can populate DropdownBox controls with data from the Client-side Data Cache.

In order to indicate that data from the Client-side Data Cache should be used, set the first line of the static choices to this:


client-side-data-cache:cacheItemName(displayDataColumn,storedValueColumn)


When the App is launched, if a connection is available, the Client-side Data Cache will be refreshed and the DropdownBox will be populated with fresh data. If no connection is available the first time the App is launched the choices you specify in the second and subsequent lines of the defined Static choices will be used.

For example, assume you had a Client-side Data Cache item called Products and that this item had two columns, Description and Code. In order to populate the DropdownBox to use the Description field as the display value and the Code field as the stored value, you would use this directive in the first line of the Static Choices:


client-side-data-cache:Products(Description,Code)


If you want the display value and stored value to be the same, then just specify the name of the display value column for the stored value.

 

client-side-data-cache:itemName(displayColumn,storedValueColumn)

 

The image below shows how the choices in a DropdownBox control would be defined to read the data from a Client-side Data Cache item called weekdays.

The choices shown starting on line two are the fallback choices that will be used if there is no connection available the first time the App is launched (which means that the Client-side Data cache cannot be populated).

 

 

 

Xdialog - Dynamic Titles - It is now easier to dynamically change the title on an Xdialog. The {title} directive can now display the value of a variable. When the value in the variable changes, the Xdialog title is also changed.

To specify that the {title} directive should use a variable, use this syntax:

{title=@variable_name}

 

 

Example:

 

dim dyn_title as c = "The Title"
ui_dlg_box("dynamicTitleExample",<<%dlg%
{title=@dyn_title};
Title [.80dyn_title!change];
{line=1};
{justify=right}<&Ok>
%dlg%,<<%code%
if a_dlg_button = "change" then
    a_dlg_button = ""
end if
%code%)

 

Clone Workspace - You can now clone a Workspace. The Clone Workspace command is on the File menu when the Web Control Panel or the standard Control Panel have focus.

 

 

UX Component - Slider Controls - Client-side Data Cache - You can now set the data in a slider control based on data in a Client-side Data Cache item.

 

UX Component - Client-side Events - afterControlBasedOnClientSideDataCacheRefreshed Event - Several control types (e.g. SpinList, ButtonList, Slider) can be populated from data in a Client-side Data cache. This event fires after a control that is populated from a client-side data cache item has been populated.

 

UX Component - Expanding Menu Control - Define Menu Choices Using JSON - You can now define the menu choices in an expanding menu control by defining a JSON object.

 

 

Xbasic - Handlebars.js Templating Library - You can now use the popular Handlebars.JS templating library in Xbasic code.

 

NOTE: The Alpha Anywhere templating library is also available to Xbasic code through the a5_merge_JSON_into_template() Function.

 

Example:

dim hb as nodeservices::handlebars

dim source as c = <<%str%
<p>Hello, my name is {{name}}. I am from {{hometown}}. I have
{{kids.length}} kids:</p>
<ul>

{{#kids}}

    <li>{{name}} is {{age}}</li>

{{/kids}}

</ul>
%str%
 

dim json as c = <<%str%
{
    "name": "Alan",
    "hometown": "Somewhere, TX",
    "kids": [

        { "name": "Jimmy", "age": "12" },

        { "name": "Sally", "age": "4" }

    ]   
}
%str%

html = hb.RunTemplate(source,json)

 

Resulting text:

 

<p>Hello, my name is Alan. I am from Somewhere, TX. I have
2 kids:</p>
<ul>

    <li>Jimmy is 12</li>

    <li>Sally is 4</li>

</ul>
 

 

 

UX Component - SpinList and ButtonList Controls - Client-side Data Cache - You can now specify that the data source for a SpinList or ButtonList control is a Client-side Data Cache item. This is particularly useful in PhoneGap applications that are designed to work offline. Here is why:

Say you build a UX component that has a SpinList control and you specify that the control should be populated with data from a Data Series. At the time your PhoneGap application is built, the SpinList with be populated with the data in the Data Series.

Once the PhoneGap app is installed on a device, the SpinList will continue to have the data that was in the Data Series at the time the PhoneGap app was built. If you refresh the Data Series the SpinList will now have up to date data, but this data has not been persisted on the device. So, this means that if you exit the App and re-launch it you are back to having stale data in the SpinList. If you do not have a connection you would not be able to make a callback to the server to refresh the data in the SpinList.

However, if you specify that the SpinList is populated from data in a Client-side Data Cache, the Client-side Data cache will be refreshed automatically when the App is launched and then the SpinList will be populated with the up-to-date data. The data that was retrieved from the server will be persisted on the device (assuming the Client-side Data Cache item was configured to persist data on the device). This means that if you exit the App and then re-launch it (while no connection is available), the SpinList will be populated with the data that was fetched from the server the previous time the App was launched (presuming that at that time a connection to the server was available).

 

UX Component - List Control - Search Part - Server-side After Search Expression Computed Event - New server-side event when performing a search on a List using the List's Search Part.

 

The Grid component exposes a server side event, onSearchPartFilterCompute, that allows developers to override the filter that was computed from the submitted search data. This event fires before the actual search query is executed.

 

Analogous behavior can now be added to searches performed from the Search Part of a List control.

The Javascript method to invoke a search is as follows:

{dialog.object}.getControl('name_of_your_list').searchList( searchOptions)

 

where searchOptions is a JSON object with these properties:

 

For example:

{dialog.object}.getControl('LIST1').searchList({searchMode : 'auto', xbasicAfterFilterCompute : 'xbmodifysearch'});

 

 

 

The Xbasic function takes e as an input parameter.

The e object contains:

e.searchDefinition contains these properties

 searchValue|||field type|argument name

For example:

%UK%|||C|search_country_country1

 

For example:

(Country LIKE :SEARCH_Country_Country1)
 

 

Your Xbasic function can modify any of the properties in the e.searchDefinition object.

 

Bugs

UX Components - Alignment Containers - Client-side Show/Hide Expressions - Were not working on alignment containers.

UX Component - List Control - Star Rating and Switch Control - Client-side Sorting - When you set the control type for a column in a List to either a Star Rating or Switch control and the List had a client-side sort applied to the data, the controls did not behave correctly.

UX Component - Javascript Injection Attack - In some cases, the UX was incorrectly reporting that a Javascript Injection Attack had been detected.

 

Alpha Anywhere V4.5.0 - Build 4584_4961 13-Sep-2017

Bugs

UX Component - List Control - Deleting Records - Under some circumstances a Javascript error was thrown when deleting a List row.

Application Server - IIS - Built-in icons were not displaying a disabled when they should have been.

Alpha Anywhere V4.5.0 - Build 4582_4960 12-Sep-2017

 

 

Videos

UX Component Multi-Lingual PhoneGap Applications Normally, UX components can be localized by wrapping the strings you want to translate in either language tags (<a5:r>...</a5:r>) or text dictionary tags (<a5:t>...</a5:t>). The string translation takes place on the server when the component is rendered. But in a PhoneGap application, the component is loaded from the file system on the device and so you can't use language or text dictionary tags. Instead, you must use a client-side approach (using Javascript) to translate the strings into the selected language.

In this video we show how you can implement client-side language translation.

Watch Video - Part 1
Watch Video - Part 2

Download component

Date added: 2017-08-04
UX Component - FormView Control Client-side Show/Hide and Enable Expressions that Reference External Data Typically, the client-side show/hide and enable expressions in a FormView layout reference field values that are in the data being displayed in the Form. For example, the Form might have a field called Country and you might want to show a container only when the Country field has a certain value.

However, there are also use cases where you want to reference external data (i.e. the value in some other control on the UX) in a client-side expression. This video shows how this is done using FormView state variables.

Watch Video - Part 1
Watch Video - Part 2

Download component

Date added: 2017-08-14
UX Component - ViewBox Control Client-side Show/Hide Expressions that Reference External Data When you define the layout for a ViewBox control, the template can use the {*if} directive to conditionally show/hide content in the ViewBox. Typically the expression in the {*if} directive will reference data in the ViewBox data. But in some cases you might want to reference data that is external to the ViewBox (for example, your UX might have a control whose value you want to reference in the {*if} directive's conditional expression). In order to do this, you must create a ViewBox state variable that is set to the value of the external data.

In this video we show how external data is used in a ViewBox conditional expression.

Watch Video

Download component

Date added: 2017-08-15
UX Component - List Control Displaying Data in a List using a StarRating Control Many applications allow you to rate something by tapping on a star in a StarRating control. The UX component has a stand-alone StarRating control (accessed by selecting [More...] in the UX Builder Controls toolbox), but in some cases you might want to display data in a List control using a StarRating control.

In this video we show how this is easily done.

Watch Video

Download component

Date added: 2017-08-18
UX Component - List Control Row Drag Actions A common user interface pattern seen in mobile apps that use a List is to allow the user to drag on a row in the List to invoke some type of action. For example in the iOS Email app a user can drag on a row to archive the row, mark is as unread/read, or move the row to another folder.

In this video we show how you can implementing row drag behavior an a List control.

Watch Video - Part 1
Watch Video - Part 2

Download component

Date added: 2017-08-25
UX Component - List Control Reorder List Rows by Dragging Row to New Position In certain applications where a List control is used, it is necessary to allow the user to reorder the rows in the List. A common user interface pattern used to reorder List rows is to allow the user to drag a row to its new position in the List.

In this video we show how you can add 'drag to move row' behavior to a List control.

Watch Video - Part 1
Watch Video - Part 2

Download component

Date added: 2017-08-28
UX Component - List Control Displaying Summary Values in Column Footers In some applications you might want to compute summary values (e.g. count, total, average, etc.) for data in a List column and then display that data below the last row of data in that column.

In this video we show how this is done.

Watch Video

Download component

Date added: 2017-09-02
UX Component Adding Keyboard Shortcuts to a Component In this video we show how you can add support for keyboard shortcuts to a UX component. Keyboard shortcuts can speed up a user's interaction with a component. For example, you could configure the Ctrl-S key as a shortcut for saving the data in the a UX.

Watch Video

Download component

Date added: 2017-09-02
UX Component Using the Enter key as a Keyboard Shortcut to Navigate to Next Control For users filling in a UX with many controls, pressing the Enter key to navigate from field to field, can be a useful productivity boost.

In this video we show how the Keyboard Shortcuts feature in the UX component can be used to map the Enter key to navigate between input controls.

Watch Video

Download component

Date added: 2017-09-02
UX Component - List Control Displaying Data in a List using Switch, Radio Button, Checkbox, Integer Increment and Map Controls The UX offers several different control types that can be used to display data in the List.

In this video we demonstrate several of the control types that can be used in a List.

Watch Video

Download component

Date added: 2017-09-02
     

 

 

 

Features

UX Component - Client-side Data Cache - A new option to automatically refresh the Client-side Data Cache before reading it has been added to the following actions in the Client-side Data Cache action in Action Javascript:

When you read the value in a client-side data cache item that has been persisted to storage on a device (either local storage or the file system if in a PhoneGap application), the existing value in the cache will be returned. If you wanted to ensure that you were getting 'fresh' data you would need to first execute an action to refresh the Data Cache. Now you can combine the refresh and read actions into a single step. Both the 'Read Data' and 'Read Multiple Data Items' actions now have a new property - Refresh cache items (if on-line) before read.  When you read an item, the cache will first be updated (if the device is on-line and the Alpha Anywhere server is available) and then the refreshed cache will be read. If the device is not on-line, or the Alpha Anywhere server is not available), then the existing data in the cache is read and returned.

 

 

 

 

UX Component - Client-side Data Cache - Client-Side Data Cache Action in Action Javascript - The Refresh Data Item(s) action now allows you to specify Javascript to handle these situations:

 

 

 

 

Web Control Panel - Bulk Operations UX Components - The bulk operations 'Recalculate UX components' and 'Turn Pre-render option on for UX Components' have been replaced with a new single genie for updating UX components. It is listed in the Web Control Panel menu option Edit -> Bulk Operation as 'Update UX components'

This new genie has options to filter the list of components by filtering by the 'pre-render' property, the file save type (binary or JSON), and if the component was last saved in an older build. This can make selecting the components to update easier. The update options include the original recalculate option and a new option to recalculate all controls as part of the update. Selected components can be changed to pre-render or have the pre-render option removed. The component save format (binary or JSON) can be changed at the same time. The genie includes help to explain the various options.

Some update options will automatically change the filters to show appropriate components. For example, if you select to change components to 'pre-render', only components that are not already pre-rendered will be shown.

Web Security - Using SQL Data - Use DataLink File - A new option has been added to the web security settings when using SQL based tables. A special encrypted single DataLink file is used to store all of the connection data needed to connect to the defined back-end SQL security tables. This file is named 'DataLink.SecuritySettings' and will always be included in every publish with other security settings files. Active Link tables for security are not used with this option and will be removed from the web project when the 'Use DataLink File' option is selected. If the DataLink option is not selected or removed, the original Active Link tables will be recreated as required.

When a DataLink file has been published, the original security Active Link files named 'websecurity_*.*' will not be used and can can be deleted from the published web project. A published application will always use the DataLink.SecuritySettings file if it exists.

 

UX Component - List Control - New Control Types - Several new control types are now available for displaying data in a List. These are:

The images below show the various control types.

 

Watch Video

Download component

 

To select any of the above List Column control types, go to the Fields tab in the List builder and click the smart field for the Control type property.

 

 

 

 

UX Component - Keyboard Shortcuts - You can now define keyboard shortcuts for a UX component.  The shortcuts can run Javascript Actions, click a button, or execute arbitrary Javascript code.

 

Watch Video
Download component
 

To define Keyboard shortcuts, click the smart field for the Keyboard shortcuts property in the UX builder.

 

 

This will open up the genie where you can define key combinations and the corresponding action for the key combination.

 

 

 

 

UX Component List Control - Columnar Layouts - Column Footer - You can now define footers for columns in a List control.

 

 

 

 

 

The ability to define column footers is particularly useful when you want to display summary data (such as totals, averages, etc.) at the bottom of a column of data.

For example, in the image below the total for the Quantity column is shown in column footer for the Quantity column.

 

Watch Video

Download component
 

 

In the above example, the total was added to the column footer for the Quantity column as follows:

 

1. On the Fields tab of the List builder, the Compute summary values option for the Quantity field was checked. This option computes the summary values on the client-side (after the List has been rendered)

 

 

 

2. The following HTML markup was added to the Column Footer Template for the Quantity column:

 

<div>
Total: <span id="{dialog.componentName}.{dialog.listid}.QTY.TOTAL"></span>
</div>

 

3. The following code was added to the afterClientSideSummaryCompute event. The code writes the value for the Quantity total to the element with the id of {dialog.componentName}.{dialog.listid}.QTY.TOTAL. This element was placed in the footer template for the Quantity column. By using the placeholders, {dialog.componentName} and {dialog.listid} in the id, we ensure that the Id is unique.

 

 

UX Component - List Control - Template Commands - New directives are available for use in the List template. These are:

 

 

 

 

Request Enhancements - A new option on the Help menu allows you send enhancement requests to the Alpha Anywhere development team.

 

 

UX Component - List Control - Reorder Rows by Dragging on Row - You can now easily implement a pattern where the user drags a row in a List to a new position.

 

Watch Video - Part 1
Watch Video - Part 2

Download component

 

 

 

To turn on drag-reorder behavior, open the list builder and check the Has row drag reorder behavior property in the List builder on the List Properties pane.

 

 

Then open the settings builder.

 

 

The builder allows you to specify two different modes of operation, DownHold and Handle.

In the DownHold mode, the user presses and holds on the row to be moved. The List then switches to reorder mode and the user can drag the row to its new location.

In Handle mode, the user simply drags on a portion of the row that has been designated as the drag handle to drag a row to its new location. Dragging on any other portion of the row simply scrolls the List. Typically a icon is used to designate the drag handle, and the icon is hidden until the user puts the List in reorder mode (using some Javascript).

When you click the smart field for the Mode option, a dialog is displayed explaining the modes.

Notice when you select the Handle option, a hyperlink is displayed that will show sample HTML, CSS and Javascript to hide the drag handle until the user explicitly puts the List into reorder mode.

 

 

UX Component - List Template Items - You can now display a tab in the List Builder for List template items. Previously you had to open a modal dialog window when you wanted to define or edit List template items.

NOTE: List template items are inserted into a List template using the a5-item attribute in the HTML markup for the List.

 

 

 

You can control the visibility of the Template Items, CSS and Javascript tabs by checking the appropriate checkboxes at the bottom of the List builder screen. If your List definition contains control CSS , items, or user-defined List methods (Javascript), the appropriate tabs are automatically displayed when the List builder is first opened.

 

 

UX Component - List Control - CSS - Control Level CSS - You can now define CSS for a List control. This CSS is scoped to the List.

This means that if you have two List controls on a UX and in the first List control you define a CSS selector called .myclass1 as color:red; and in the second List control you define a CSS selector also called .myclass1 as color:blue; the CSS selector defined in the second List will not override the selector defined in the first List.

The List builder now has a new pane where you can define this control level CSS.

NOTE:  The advantage of CSS defined at the Control level (besides the fact that it is in its own namespace) is that the List is fully defined in the List definition. It does not rely on any CSS classes that are in linked CSS stylesheets or in local (to the UX component) CSS definitions. If you copy the List from one component to another, it will still render correctly.

You can use SASS syntax when defining the control CSS.

 

 

UX Component - List Control - Drag on Row - You can now add support for drag actions on a row in a List. You can define actions for both left-to-right and right-to-left drag actions. For each drag action you can define one or more buttons that are revealed as the user begins dragging on a row.

 

Watch Video - Part 1
Watch Video - Part 2

Download component

 

 

 

The sequence of images shown below shows a List with both left-to-right and right-to-left drag actions defined in its different states.

 

This image shows the list with the first row selected and before user has dragged in either direction on the row.

 

This image shows the List after user begins dragging from left-to-right. Notice that the action button is partially revealed because the user has not dragged sufficiently far to the right.

 

The user has now dragged sufficiently far to the right and has released her finger from the screen. The action button is now locked in place. User can invoke the action by tapping on the button.

 

The user can continue dragging to the right past the specified threshold distance. The action button keeps on expanding in size. If the user removes her finger from the row the action will automatically be selected. User does not have to tap on the button to select the action.

 

 

In this image the user has previously selected the Unread action to mark the status on the row to read. Now the user has dragged again all the way to the right and the label on the action button has changed from Unread to Read. Releasing on the row will invoke the action and mark the row as read. If, instead of releasing, the user drags back in the opposite direction (toward the left), the action button will gradually be hidden and the action will not be invoked

 

This List is shown in its normal state after the user has selected the Unread action. Notice that the icon on the row has changed to indicate that the row has been read.

 

 

The user now starts dragging from right-to-left. Three action buttons have been defined for this action. The action buttons are only partially shown because the user has not dragged sufficiently far. If the user were to release now, the action buttons would be hidden and no action would be invoked.

 

The user has now dragged sufficiently far to the right to fully reveal the three action buttons. If the user releases now the action buttons remain visible in the row. Tapping on one of the buttons will invoke the action. Tapping in the area to the right of the buttons will not invoke any action and the List row will be returned to is normal state.

 

If the user continues dragging on the row (past the threshold distance) after all of the action buttons are fully revealed, the outermost action button (Archive) is auto selected and it begins to fill the row. If the user releases now the Archive action will automatically be invoked.

 

To define row drag settings open the List builder and check the Has custom row drag behavior property on the List Properties pane.

 

 

Then open the genie by clicking on the smart field for the Row drag settings property.

 

TiP: You can get to the Row drag settings genie more quickly by clicking the Quick Access... button at the bottom of the List builder and then selecting Row drag settings from the menu.

 

The List Row Action Builder genie is shown below. The builder has two panes. The Action Buttons pane is where you define the action buttons for the drag actions. The Actions pane is where you define the Javascript code to execute when each action button is selected.

 

 

NOTE: When you drag on a row and select an action, the row you dragged on does not automatically become the selected row in the List. If a previous row was selected, this row remains selected. If you want the row you drag on to automatically be selected, add this code to the Javascript for the Action:

this.setValue(index);

 

 

UX Component - List Control - Lazy Image Loading - Virtualized List - The code that the genie generates has been changed so that if your list is virtualized and you scroll back to a page of List records that have previously loaded images, the spinner will not be shown for the previously fetched images.

 

UX Component - List Control - Star Rating - You can now display data in a List column using a StarRating control. Tapping on one of the stars in the control will update the value in the List.

 

Watch Video
Download component

 

For example, in the image below, the selected row in the List (which has an associated Detail View) was edited by tapping on a star and the List row is shown as dirty.

 

 

To display data in a List column using a Star control, set the Control type for that field to StarRating in the List builder Fields tab (as shown below).

 

 

 

UX Component - Color Picker - A new color picker is now being used in selected parts of the UX builder.

The color picker has several modes that make selecting colors easier and faster.

The color picker also has support for semi transparent colors (when set into either 'rgba', 'hsla' mode).

In the image below, the 'Fan Decks' (like paint swatch sheets that you get from a paint store) allows you to select from a series of predefined colors.

On the left you can select any color and transparency that you want by dragging the sliders.

The selected color is shown in the rectangle at the top left.

In the top right corner of this rectangle a much smaller square is shown. This is the color that was originally selected when the color picker was first opened. It allows you to quickly switch back to the initial color by clicking on the color square.

 

 

In the Palettes mode (shown below) you can select from a palette of pre-defined colors that you define.

 

You can easily add a new color to the palette by selecting a color in the left hand pane and then clicking the + icon in the Palettes pane.

Another way to add a color to the palette (when the Palettes mode is not selected) is by clicking on the

button in the left hand pane.

You can manage your palettes by clicking the down arrow icon in the Palettes mode

 

 

 

In the Image mode (shown below) you can load an image into the image picker and then select colors by pointing to different parts of the image.

 

 

You can set the mode in which the color picker works by clicking on the button (shown as HEX in the above image)

This brings up a menu showing the mode.

 

 

UX Component - Star Rating Control - Color of Un-selected Stars - You can now set the color of un-selected stars as show in the images below. The top image shows the current default color and in the second image both the selected and un-selected colors have been changed.

TIP: The Star Rating Control is selected by selecting the [More...] item in the UX toolbox (in the Data Controls section).

 

 

Application Server for IIS - Publishing  - IIS publish now supports optimized publishing (like all other publishing types when using the standard server). Previously, when you published to IIS all of the files in your project were automatically published. It was not possible to publish a single file, of a selected subset of files, as is possible when publishing to the Alpha Anywhere server.

When you publish to IIS, a staging folder named __staging.staging is now located in the web project folder. This folder will contain the published application in a form ready to be deployed to an IIS server.
 

Application Server for IIS - Page Security - Deny by Default -  Authorization is now denied by default under IIS. The authorization rules for accessing files under IIS were previously set on files only known at publish time. This meant that files could be added to the web root of a published application and access would be allowed to any of these files. This changes means that a file needs to have a rule set to expressly allow or allow by group name in order for it to be accessible in an application.
 

Grid Component - Detailed Javascript Error Reporting - In V4.5 detailed Javascript error reporting was added to the Grid. This was done by defining a handler for the window.onerror event. This has caused error alerts to be displayed even when the Javascript errors are benign and caused no problem with the Grids that were run in prior versions. Now, detailed Javascript error reporting is off by default, but you can turn it on using this property:

 

UX Component - PhoneGap - Action Javascript - Open File with Native Application -- SQL Server Reporting Services - This action can now work with SSRS reports.

 

 

UX Component - Data Driven Forms Sample Template - The sample template showing how to create a data-driven form (first released in v4.5) has been updated to include a star-rating control.

 

 

 

UX Copmponet - FormView Control - Action Javascript - The Action Javascript action for FormView actions now has two additional actions:

 

State variables can be referenced in the FormView layout templates (and therefore in client-side show/hide and enable expressions) using this syntax

[temp].state.your_variable_name

 

Say you had a container in a FormView layout that contained several controls. You wanted to show this container if a session variable (called say myVar1) was equal to 'alpha'.

MOTE: You would, of course, need to publish the value of this session variable to the client-side by setting the Published session variables property.

 

Here is how you would do this:

Set the show/hide expression for the container to

[temp].state.myVar1 == 'alpha'

 

In the client-side onRenderComplete event, execute this code to set the FormView control's myVar1 state variable to the value of the session variable.

 

var myVar1 = {dialog.Object}.getSessionVariable('MYVAR1');

{dialog.object}.formViewSetStateVariables('FORMVIEW_1',{myVar1: myVar1});

 

 

Watch Video - Part 1
Watch Video - Part 2

Download component

 

UX Component - Audio Player/Recorder Control - New Events - Two new events have been added to the Audio Player/Recorder

 

 

 

 

UX Component - window.onerror Event Handler - In V4.5, the UX component generates a widow.onerror event handler to report Javascript errors. This event handler displays an alert with a full stack. In some cases, where you are loading 3rd party Javascript libraries, that might throw benign errors on loading, you might want to suppress this error reporting.

The Capture detailed Javascript error information property allows you to turn off detailed Javascript error reporting.
 

 

 

UX Component - Templates - Localize PhoneGap Application - A new template is available showing how you can localize a PhoneGap application at run-time, allowing the user to select the language used for the app. The template is called MobileAppFramework_Client-side-Language_Translation.
 

Watch Video - Part 1
Watch Video - Part 2

Download component

 

UX Component - Templates - SecurityFramework-LoginComponentMobileApp-Persistent Login - The template showing how to build a mobile app that has a persistent login has been updated. The template now applies security settings when the component is reloaded and a persistent login token is found.

Alpha Anywhere Application Server for IIS - Publish - Delete Files - Publish to IIS no longer deletes files and folders that are not part of the web project. This applies to existing publish profiles and new publish profiles. Previously, any files in the target webroot folder that were not part of the web project were deleted when a project was published.

In the event a you want the old delete behavior, the Delete existing files option can be checked in the publish profile:

 

or the Delete existing files option can be checked in the Advanced Settings section when creating a new publish profile:

 

 

 

UX Component - Pre-Defined Date Range Selector Control - The Date Range selector control is useful if your UX component has controls where the user must enter a start date and an end date.

In the image below, the Date Range Selector (a dropdown box) shows the list of date ranges. The user has selected the 'This Year-to-date' range and the two input controls (one for date start, the other for date end) have been filled in.

 

 

To add a Date Range Selector control to your UX, select the control from the Defined Controls section of the UX toolbox.

 

 

Once you have added the control, you must edit the Javascript in the control's onChange event to define the Ids of the start and end date controls.

 

The Choices property for the Date Range Selector shows these choices. These are the built in options. You can add text or language tags to the display value if you want to show the choices in a different language.

 

|
Today|today
Yesterday|yesterday
This Week|thisweek
This Week-to-date|thisweektodate
This Month|thismonth
This Month-to-date|thismonthtodate
Last Week|lastweek
Last Month|lastmonth
Next Month|nextmonth
This Year|thisyear
This Year-to-date|thisyeartodate
This Quarter|thisquarter
This Quarter-to-date|thisquartertodate
Last Quarter|lastquarter
Next Quarter|nextquarter

 

You can also add your own custom choices to this List. When you define a custom choice you use this syntax

Display value|javascript:javascript code to compute start and end date

 

The Javascript code that you write must follow these rules:

For example, here is how a customer item called 'Tomorrow' could be added to the choices in the Date Range Selector Control:

 

(Code shown on multiple lines for clarity. Must all be on a single line)


Tomorrow|javascript:/*custom date range. code must not contain any commas*/var d1 = new Date(); var d2 = new Date(); d1.setDate(d1.getDate() + 1); d2.setDate(d2.getDate() + 1); var obj = {}; obj.startDate = d1; obj.endDate = d2; return obj;

 

 

Xdialog - Overlays - You can now design Xdialogs with floating 'overlay' windows. The overlays are similar to bubble-help that you can define for toolbar buttons, Xdialog buttons, etc. except that the overlay content can be any HTML text and the overlay can be applied to any part of the Xdialog.

 

In the images below an overlay is shown when the mouse if over the combo box and another overlay is shown when the mouse is over the button.

 

 

The Xdialog {overlay=variableName} directive is used to define an overlay.

 

Here is the code to produce the above Xdialog.

 

dim overlay1.html as c = <<%html%
<div style="margin: 0px; padding: 5px; border: 1px blue solid; border-radius:10px;">
This <b>combo</b> lets you pick a number on entries<br>
Your choices are one, two, three or four.
</div>
%html%

dim overlay2.html as c = <<%html%
This is the button that performs the action
%html%

dim item as c = "one"

ui_dlg_box("with_help",<<%dlg%
A Combo;
List {overlay=overlay1}[.60item^={one,two,three,four}];
{line=1};
{overlay=overlay2}
<&Do It...>
%dlg%)

 

UX Control - Multi-select Tokens Control - Text Highlighting - When you start typing into a multi-select tokens control, the list of choices that is displayed, which is filtered, by the text you have typed, now shows the matches in the choice list with the text you have typed in bold.

 

For example, in the image below, the user has typed an 'a' and the choice list shows all of the items that contain an 'a'. Notice that in the choice list all of the 'a' characters are bolded.

 

If you have an existing multi-select token control you will need to edit and resave to get this feature.

ViewBox and FormView Control - Post-process event - You can now specify post process Javascript for each Layout. The post process Javascript runs after the HTML for the layout has been rendered. You can use the Post-process event to modify the HTML that is shown in the layout. A common use of this event is using the A5.u.html.highlight() function to highlight some text in the Layout html.

Javascript Library - A5.u.html.highlight() Function - Can be used to add markup to an HTML string to highlight portions of the text in the HTML. Any text in HTML elements or attributes is ignored.

Syntax:

A5.u.html.highlight(html, searchString [, prefix [,suffix]])

Where

 

Example

var html = '<div>this is some text</div>';
var html2 = A5.u.html.highlight(html,'ome')
 

The resulting html2 string will be:


<div>this is s<b>ome</b> text</div>

 

Example using a function for the prefix argument:

 

count = 0;

var html = '<span>this text is inside a span. But only a single span</span>'

A5.u.html.highlight(html,'span',function(search,match,offset,html){
    count++;
    return '<i id="match.'+count+'">'+match+'</i>';
    }

)

Result

<span>this text is inside a <i id="match.1">span</i>. But only a single <i id="match.2">span</i></span>
 

 

Grid Component - Pre-defined Date Ranges - When you define the Search Part for a Grid, you can specify that any of the search fields are 'range' searches. If you turn on the range search feature, the Search Part will display two search fields for the start date and the end data.

You can now also display an optional pick list to select common date ranges, as shown in the image below. If you select one of the pre-defined date ranges, the dates in the From and To input controls will be filled in.

 

 

 

To turn on the pre-defined data range feature, check the Pre-defined date range selector property.

 

 

You can then click the smart field for the Pre-defined date range selector settings control to configure the selector.

The settings dialog allows you to set:

 

By default a standard set of pre-defined date ranges are shown. These are:

 

If you want to translate these names into different languages you can customize the list of choices and add language or text dictionary tags to each label.

You can augment this list with your own data ranges, or you can replace the built-in list with your own date ranges.

To define your own entry to appear in the list of choices, add a choices to the choice list that is defined as follows:

display name in the selector|value|javascript

 

where value is a unique name for the selection. The value must not contain any special characters or spaces. Javascript is some code that returns an object with two properties: startDate and endDate.

 

For example:

 

a5_ink_to_png() Function - This function now has a new parameter that lets you control how the image is created from the ink. Previously, the image was bound to the size of the ink with a 20px border. Now you can size the image to the entire ink page, not just the bounds of the ink text.

The new optional parameter is flagUseViewBox. This defaults to .f. (size the image to the bound of the ink). Set to .t. to size the image to the entire ink page.

Syntax:

a5_ink_to_png(c ink ,n heightInPoints,n widthInPoints,c filename ,l   flagUseViewBox)
 

Bugs

Code editor - Code Library - The code Library got broken in a recent release. This is now fixed.

Javascript Errors - The previous build was too aggressive in reporting Javascript errors. Benign Javascript errors are no longer reported.

PhoneGap - SQLite - MySQL - Bit(1) Columns - A bug in creating a SQLite database from a MySQL database when a table in the MySQL database has bit(1) columns has been fixed. Alpha Anywhere treats bit(1) columns as Logical columns. So a value of 3 or 4 (for example), are both interpreted as True by Alpha Anywhere.

Tips

UX Component - HTML Editor - Display as Pop-up - Double-click - If you configure an HTML editor to act as a pop-up and you specify that the control has a 'click to edit' button, then you can open the HTML editor by clicking the button. However, double clicking on the HTML control will also open the editor. If you want to disable the double click, so that the HTML editor can only be opened by clicking the button, add this code to the UX onRenderComplete client-side event:

 

var obj = {dialog.object}.getControl('name_of_html_control')
obj.dblClickEdit = false;

 

 

 

Alpha Anywhere V4.4.5 - Build 4491_4932 30-July-2017

 

Videos

UX Component - List Control Lazy Image Loading A common use case for Lazy Image Loading is when you have a List that displays images that are sourced from a server. If the List has a large number of rows, fetching all of the images from the server will slow down the initial render of the List. However, by implementing Lazy Image Loading, only the images for the rows that are currently scrolled into view will be fetched.

You can set a wait time that the List will wait after a row comes into view before the images for the visible rows will be fetched. This prevents fetching images for rows that you scroll past without stopping on. When a row that displays an image that has not yet been fetched is displayed, a 'waiting' image will be displayed. Once the image has been fetched, the 'waiting' image will be replaced with the real image.

In this video we show how to configure a List control to use Lazy Image Loading.


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

Download Component

Date added: 2017-05-25
UX Component - ControlBar Control Dynamically Styling Items on a ControlBar A common requirement when using ControlBars is to dynamically style the items on a ControlBar. For example, you might want some text to be red under one condition and green under another condition.

In this video we show how client side templating directives (e.g. {*if} ...{*endif} can be used to define dynamic styles and classes.

Watch Video

Download Component

Date added: 2017-06-09
UX Component - ControlBar Control Showing a List Control in a ControlBar Disclosure A powerful feature of the ControlBar is its ability to display 'disclosures' (i.e. windows). These disclosures can be animated into view from various positions on the screen. A common requirement is to show a List control in a disclosure.

This video shows how this can be done.

Watch Video - Part 1
Watch Video - Part 2

Download Component

Date added: 2017-06-18
UX Component - FormView Control Review of Different Field Editors Fields in the FormView control are edited using Field Editors. You can build your own Field Editors, or chose from the collection of built-in Field Editors.

In this video we review the different built-in Field Editors that are available as of Build 4192.

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

Download Component

Date added: 2017-06-25
UX Component - FormView Control Displaying Data from Hierarchical Lists in a FormView Control (This video is aimed at advanced users of the FormView control).
The FormView control can display data from multiple Lists that are linked in an hierarchical relationship. E.g. A Customer List with a child Orders List. By default, when the FormView displays data for a selected row in the parent (i.e. Customer) List, it will display ALL of the data from the children of the selected row. In other words, the FormView control will display data for the selected customer in the Customer List and it will show ALL of the orders for the selected Customer.

However, in some applications, you might want to display only the data for the selected Order in the Orders List. In other words, the FormView control should use BOTH the parent (i.e. Customer) List and the child (i.e. Orders) List as selectors for the data that should be shown in the FormView control.

In this video we show how the FormView control is configured to show just the data from the selected row in the child (i.e. Orders) List.

Note: Another way to achieve this result would have been to use two separate FormView controls - one for the Customer List and one for the Orders List.


Watch Video - Part 1
Watch Video - Part 2


Download Component

Date added: 2017-06-26
UX Component Introduction to Style 'Tweaks' In order to change the appearance of a UX component you can either edit the stylesheet or you can 'tweak' the style.

In this video we show how you can tweak the style to change the colors in the stylesheet and also how you can add a new button sub-theme.

Watch Video

Date added: 2017-07-05
UX Component - FormView Control Displaying Editors in a Pop-up Window The typical pattern in a mobile UX component that uses the FormView control is to place the editors in their own PanelCard that is animated into view when the user taps on a field in the form to edit its value.

However if you are using a FormView control in a web application, you might prefer the editors to be shown in a pop-up window next to the field you are editing.

In this video we show how the editors used in a FormView control can be opened in a drop-down window relative to the form field you are editing.

Watch Video

Download Component

Date added: 2017-07-05
UX Component - List Control Injecting Arbitrary Headers and Footers into List Data You can inject arbitrary HTML into the List. This can be used to add headers and footers into the List as shown in this video.

Watch Video
Download Component
Download Component - collapsible headers

Date added: 2017-07-12
UX Component - Multi-select Tokens Control Adding a Multi-select Tokens Control to a UX Component The Multi-select Tokens control operates much like the Gmail app when you address an e-mail to multiple recipients. You can type values into a control, or make selections from a drop-down choice list. Each selection is shown in the control as a 'token'. Tokens can be removed from the list of selections by either hitting the backspace key while focus is in the control, or by clicking on the 'delete' icon in the token.

A common use case for the Multi-select Tokens control is to define selection criteria for a List control. In this video we show how a Multi-select Tokens control is used to select a list of countries. The List control is then filtered to show the countries that match the selected tokens. For example, if tokens for 'USA' and 'UK' are selected, the List is filtered to show customers in either 'USA' or 'UK'

Watch Video - Part 1
Watch Video - Part 2

Download Component

Date added: 2017-07-23
UX Component Data-driven Forms A data-driven form is a form whose fields are determined at run-time (typically by querying a database) to get a list of the fields to display in the form.

In this video we show how a ViewBox control and an Editor Set with multiple Editors can be used to implement a data driven form.

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

Download component

Date added: 2017-07-26
     

 

 

Security

 

 

Alpha Anywhere Server for IIS - A potential security issue under IIS has been fixed. A UX AJAX request could be crafted to return the content of a file that should not be visible outside of the server. This fix closes this vulnerability.

Features

email_send_sparkPost() Function - Reply To - Support has been added for the 'Reply to' parameter.

 

Example:

dim ms as p
ms.send_to = "Fred@acme.com"
ms.reply_to = "Harry@acme.com"
ms.from_email = "admin@acme.com"
ms.from_alias = "admin@acme.com"
ms.from_name = "Admin" 
ms.subject = "Reply To Now Supported"
ms.message_html = "Message goes here"
dim key as c = "Your api key"
pp = email_send_SparkPost(key,ms)
 

 

Grid Component - Column Sorting - Initial Sort Direction - When the user first clicks on a column to sort the Grid on that column an ascending sort is performed. Now you can specify that the initial sort should be descending.

 

 

UX Component - Minimum Build Number - You can now specify a minimum build number for a UX component. If a developer tries to edit the component using a build that is older than the specified minimum build, a warning will be displayed. The user will not, however, be prevented from editing the component.

 

 

 

 

UX Component - Data Driven Forms Sample Template - A new sample template has been adding showing a technique for implementing data driven forms. A data driven form is a form where the fields in the form are determined at run-time, rather than at design-time.


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

Download component

Typically, the form is generated by first querying a database to determine what fields the form should display. Then, some Xbasic code is executed to generate a dynamic form definition.

In the example template the form is implemented using a ViewBox control, an Editor Set and numerous Editors for editing the field values shown in the form.

The image below shows how the sample component renders a particular data-driven form. The actual fields shown in the form are easily controlled by editing a JSON object that defines the fields, the field types and the editor to be used to edit the field value.

 

 

 

 

UX Component - Multi-select Token Control - A new control type is available for the UX component. The Multi-select Token control is similar to the Edit-combo control and the Auto-suggest control. However, the selected values are displayed as 'tokens' (as shown in the image below where 'Belgium', 'Brazil' and 'Canada' are selected).

 

Watch Video - Part 1
Watch Video - Part 2

Download Component

 

 

The user can select values from a pick list as shown in the image below. The pick-list can be automatically displayed when the user starts typing in the input control, or can be displayed when the user clicks on the down array (which is optionally displayed). The user can also select tokens by typing the value into the control and then pressing the Enter key.

To delete a previously selected token, click on the X icon in the token, or click to the right of the last selected token and press the Backspace key.

 

 

The choices for the pick-list can be statically defined, can be derived from querying a SQL database, or can be computed by an Xbasic function.

 

How to Add a Multi-select Token Control to a UX Component

 

To add a Multi-select Token control to your UX component, select the [More...] item in the Data Controls section of the UX toolbox.

 

The Multi-select Token control is a Data Control. This means it has a .getValue() and a .setValue() method, just like other Data Controls. When the UX is submitted, the data in the Multi-select Token control are submitted as a comma delimited list of token values.

For example, if there are three tokens selected with values of 'USA', 'UK' and 'Canada', the value submitted is 'USA,UK,Canada'

To set the value in a Multi-select Token control you must specify an array of values. For example

{dialog.object}.setValue('MY_MULTISELECT_TOKEN_CONTROL',['USA','UK','Canada']);

 

To set a default value for the control in the Default value property in the property sheet you can use this syntax

array(USA,UK,Canada)

 

Setting the Multi-Select Token Control Properties

To set the properties of a Multi-select Token control, click the smart field for the Control properties property in the Property sheet.

The configuration genie window is displayed, as shown below:

 

 

Dynamically Populating Choices at Runtime

You can dynamically populate the choices in the Multi-select Token control at runtime by calling the control's .populate() method. For example, assume you have a Multi-select Token control called 'MST1'. You can use the following Javascript  to populate the control's choices:

 

var _d = {
    "data":[
        {"value" : "Argentina", "display" : "Argentina"},
        {"value" : "Austria", "display" : "Austria"},
        {"value" : "Belgium", "display" : "Belgium"},
        {"value" : "Brazil", "display" : "Brazil"},
        {"value" : "Canada", "display" : "Canada"},
        {"value" : "Denmark", "display" : "Denmark"},
        {"value" : "Finland", "display" : "Finland"},
        {"value" : "France", "display" : "France"},
        {"value" : "Germany", "display" : "Germany"},
        {"value" : "Ireland", "display" : "Ireland"},
        {"value" : "Italy", "display" : "Italy"},
        {"value" : "Mexico", "display" : "Mexico"},
        {"value" : "Norway", "display" : "Norway"},
        {"value" : "Poland", "display" : "Poland"},
        {"value" : "Portugal", "display" : "Portugal"},
        {"value" : "Spain", "display" : "Spain"},
        {"value" : "Sweden", "display" : "Sweden"},
        {"value" : "Switzerland", "display" : "Switzerland"},
        {"value" : "UK", "display" : "UK"},
        {"value" : "USA", "display" : "USA"},
        {"value" : "Venezuela", "display" : "Venezuela"}
    ]
};

var obj = {dialog.object}.getControl('MST1');
obj.populate(_d);

 

Grid Component - Summary Fields - Headers - You can now specify that column headers should be repeated before the summary values are shown (as shown in the image below). This is useful when you have a Grid with a lot of rows and the page must be scrolled to get to see the summary values.

 

To turn on this feature, check the Repeat column headings above summary values property.

 

 

Web Security - Get User Values When Using Active Directory - a5ws_GetUserValuesActiveDirectory()  - A function named a5ws_GetUserValuesActiveDirectory() has been added to Alpha Anywhere.  It can be used in code running on a web server to get user values when using Active Directory for security authentication.  This function works in the Classic Alpha Anywhere server and IIS and retrieves a number of default values from Active Directory.  Help about this function is found in the documentation at 

https://www.alphasoftware.com/documentation/index?search=api%20a5ws%20getuservaluesactivedirectory%20function

 

Xbasic - Arrays - .push() method - A new .push() method has been added for Xbasic arrays. To push onto a property array use JSON syntax to define the object you want to push onto the array. See examples.

 

Examples:

 

dim arr[0] as c
arr.push("hello")
arr.push("world")
? arr
= [1] = "hello"
[2] = "world"
 

'using a property array
dim arrp[0] as p
 

'push object defined using JSON syntax onto the array
arrp.push({"text":"hello"})
arrp.push({"text":"world"})
? arrp.size()
= 2
? arrp[1].text
= "hello"
? arrp[2].text
= "world"

 

 

UX Component - List Control - Inject Arbitrary Headers and Footers into List Data - You can now inject arbitrary headers and footers into List data using the onBeforeListDraw event. For example, in the image below a header is inserted for each group of 3 rows of data. A footer is also inserted. Both the header and footer can contain arbitrary HTML. As shown in the image, the footer text contains some bold text as well as a SVG icon.

Watch Video
Download Component

Using items (i.e. the a5-item attribute), you can add event handlers to the header and footer text (see video).

The onBeforeListDraw event allows you to return a new array containing the data to be rendered in the List.

 

 

In the above example, the following Javascript is defined in the onBeforeListDraw  event to add the headers and footers to the List.

 

var ta = [];
var group = 1;
for(var i = 0; i < data.length; i++) {
    //add a user defined title into the data before every 3rd row
    if( (i % 3 ) == 0) {
        if(i != 0) {

            //add the footer html
            ta.push({'*static': '<div a5-item="item1:'+(group-1)+'" style="padding: 10px; border: solid 1px gray; border-radius: 10px;">

                    <img src="svgIcon=#alpha-icon-basketFull:26{ fill: #2730d1; stroke: #f52d2d;}" />This is some static <b>HTML</b>.

                    It shows how you can add arbitrary HTML into the List</div>'});
        }

        //add the header html
        ta.push({'*title': 'Group ' + group});
        group++
    }
    ta.push(data[i]);

}
//return a new array of data to be used to draw the list
return ta;

 

To inject a header into the List, add an object into the data array that has a '*title' property name. To add arbitrary HTML (e.g. a footer), add an object into the data array that has a '*static' property name.

Notice that in the above Javascript code, the data array is passed in. But the contents of this array are not modified. Instead a new array (called ta) is created and the Javascript returns this array. The List is then rendered using this new array of data.

 

Collapsible Headers

The image below shows a slightly more complex example. In this example, each header is made collapsible. For example, Group1 through Group4 have been collapsed. Tapping anywhere on the header will toggle the collapsed state of the group.

 

Download Component - collapsible headers

 

 

 

The Javascript in the onBeforeListDraw event to accomplish this is shown below:

 

var ta = [];
var group = 1;
var to = this._to;
if(typeof to == 'undefined') to = {};
var flag;
var iconOpen = A5.u.icon.html('svgIcon=#alpha-icon-addCircleBorder:icon,24');
var iconClose = A5.u.icon.html('svgIcon=#alpha-icon-removeCircleBorder:icon,24');;
var icon;
for(var i = 0; i < data.length; i++) {
//add a user defined title into the data before every 3rd row
    if( (i % 3 ) == 0) {
        if(i != 0) {
            if(flag == 'opened') {
                ta.push({'*static': '<div a5-item="item1:'+(group-1)+'" style="padding: 10px; border: solid 1px gray; border-radius: 10px;"><img src="svgIcon=#alpha-icon-basketFull:26{ fill: #2730d1; stroke: #f52d2d;}" />This is some static <b>HTML</b>. It shows how you can add arbitrary HTML into the List</div>'});
            }
        }

        flag = to['Group:' + (group)];
        if(typeof flag == 'undefined') flag = 'opened';
        if(flag == 'opened') icon = iconClose;
        else icon = iconOpen;
        ta.push({'*title': '<div a5-item="toggle:' + group + '" style="line-height: 26px;"><div style="float:right;">'+icon+'</div>Group'     +   group + '</div>' });
        group++
    }

    if(flag == 'opened') {
        ta.push(data[i]);
    }
}
return ta;

 

Notice that the header is wrapped in a div that has an a5-item attribute called toggle. Notice also that the list contains a variable called _to that contains an object with the open/closed state of each group. If a group is closed then the code that pushed the list data onto the new array (ta.push(data[i]) is skipped over, thus omitting these rows from the rendered List.

When a user taps on a header, the onClick event in the toggle item is fired. This event will then add the group's open/closed state to the List object's _to variable. The Javascript code in toggle item's onClick event is shown below:

 

var to = lObj._to;
if(typeof to == 'undefined') to = {};
var flag = to['Group:' + ia];
if(typeof flag == 'undefined') {
    to['Group:' + ia] = 'closed'
} else {
    if(to['Group:' + ia] == 'closed') to['Group:' + ia] = 'opened';
    else to['Group:' + ia] = 'closed';
}
lObj._to = to;
lObj.refresh();

 

UX and Grid Components - Amazon S3 - V4 Signing - Ohio Region - Amazon has changed the way that URLs must be signed for their newer regions. For example, support for the Ohio region was recently added to the Storage Connection String builder. But in order to upload or download files to/from the Ohio region, URLs must be signed using Amazon's V4 signing scheme. Support has been added for V4 signing, so now uploads and downloads to the Ohio region will work correctly.

 

 

UX Component - ExpandingMenu Control - A new control type is available in the UX Component. The Expanding Menu control displays a list of menu choices, some of which may have sub-choices (indicated by an icon at the right edge of the item). When a menu item is clicked, it can invoke Javascript code. If the menu has a sub-menu, the sub-menu is shown using animation.

In the image below the ExpandingMenu is shown in its full collapsed state and it a partially expanded state.

 

 

 

 

To add an ExpandingMenu control to your UX component, select the [More...] item in the Data Controls category.

NOTE The ExpandingMenu is in the Data Controls section, because, like all Data Controls, it has a {dialog.object}.setValue() and a {dialog.object}.getValue() method. The 'value' of the current selection in the Expanding menu is defined by the 'value' property for each node in the tree (see below).

 

 

 

 

Then select the ExpandingMenu option from the dialog.

 

To configure the ExpandingMenu control, click the smart field for the Control properties property.

 

 

 

This will bring up a genie where you can define the choices shown in the ExpandingMenu and also set other properties.

 

 

To define the choices and sub-choices shown in the menu click on the smart field for the Menu data genie property.

This will bring up a dialog where you can type in your menu choices, using tab indents to indicate which menu choices are sub-choices.

For example, in the image below, the top level menu choices are:

item1

item2

item3

item4

 

Item1 and item2 hav3 sub-choices.

 

 

When you close the Add Item dialog, the Tree Data Genie is shown (see image below). This dialog allows you to set properties for each menu item in menu tree.

 

 

Properties that you can set include:

 

Grid Component - Delete Checkbox - Delete All - A new option has been added to the Grid component to allow you to check/uncheck the Delete checkbox in all rows on the current Grid page at once.

To turn on this feature, check the Allow 'delete-all' checkbox property.

Update Settings

 

The Grid will be rendered as shown below. The Delete column title will have a checkbox in it. Checking this box will check the delete checkbox in all Grid rows on the current Grid page.

 

 

UX and Grid Components - Javascript Errors - Error Reporting - Error reporting when a Javascript error occurs has been improved. The error message will now include a stack dump.

 

UX Component - ViewBox Control - Sample ViewBox - When you create a new ViewBox a new sample ViewBox is is now available when you click on the Load Sample ViewBox hyperlink.

 

 

 

 

The Menu tree option displays an hierarchical menu as sown in the image.

 

 

 

UX Component - Sample Templates - MobileAppFramework_with_SplitView_ExpandingTreeMenu - A new sample template for mobile apps is available. This template is similar to the the MobileAppFremework_SplitView_Hierarchical_Menu template, except that the menu is rendered using a ViewBox control, not a List control.

The ViewBox menu can contain nested menus. When a menu item that has children is expanded, the ViewBox is animated, creating a very appealing visual effect.

 

To use the template, chose the template from the list of available templates when you create a new UX component.

 

 

 

On a Phone, the UX will render as shown below.

 

 

Tapping on the 'hamburger' menu icon will show the menu in its collapsed state:

 

 

You can expand various branches of the menu. When you tap on a menu item that is an endpoint, the associated action for that menu item is executed.

 

 

On a tablet, the menu is always shown on the left of the screen.

 

 

To edit the list of choices shown in the menu, edit the ViewBox Control. In the ViewBox control, edit the Data Source. The menu structure and the associated menu actions are defined in the Javascript object for the ViewBox data source.

 

The background color of the menu is set in the CSS tab in the ViewBox builder. To change the menu color, edit the ViewBox and in the CSS tab, edit this value:

 

$color: #221f22; //this sets the color of the menu tree.
 

 

 

Xdialog - Simple List View Control - The simple list view control has been enhanced to allow sortable columns and different views of the data.

 

In the image below, the List has been sorted on the Firstname column and a small icon in the column title indicates the sort direct.

This is the 'report' view of the data.

 

 

In the image below, the 'list' view of the data is shown.

 

 

In the image below, the 'SmallIcon' view of the data is shown.

 

 

To indicate that a column is sortable, add a caret to the column definition. For example:

[%M;K;%.100,20id^"Firstname:30^|Lastname:50^"list!idchange];
 

In the above example, we have defined both the Firstname and Lastname columns to be sortable.

You can specify if the sort should treat the data as numeric or data/time values by adding a suffix of N or T after the ^. For example

[%M;K;%.100,20id^"Lastname:30^|DateOfBirth:50^T"list!idchange];
 

 

To change the view of the List, send a command to the list using the ui_dlg_ctl_command() function, as shown in the example below. The second parameter in the function is any string in the control definition that uniquely identifies it. In the example below, the text string 'idchange' is used to identify the control.

 

You can also sort the List on multiple columns using the ui_dlg_ctl_command() function. For example to sort on Lastname (column 2) and then Firstname (column 1), you this command:

 

 ui_dlg_ctl_command(dlg_title,"idchange","sort:2,1")

 

Full example:

 

dim list as c
list = <<%txt%
{image=$$generic.orb.green}Erica|Jones
{image=$$generic.orb.blue}Tom|Snider
{image=$$generic.orb.yellow}Molly|Maloney
%txt%
list = replicate(list,30)
list = *for_each(x,"{data=" + *index() + "}" + x, list)


dim dlg_title as c = "Quick ListView - Sortable"
ui_dlg_box(dlg_title,<<%dlg%
{wrap=100}
This dialog shows a simple ListView using the new ^" Xdialog syntax.;
Using this technique, it is possible to create a simple ListView with substantialy less Xbasic than the {{Listview} Xdialog command.;
The ^ in the control definition makes the column sortable.;
 

[%M;K;%.100,20id^"Firstname:30^|Lastname:50^"list!idchange];
{lf};
Click button to change List layout;
<List><Report><SmallIcon>
%dlg%,<<%code%
if a_dlg_button = "List" then
    a_dlg_button = ""
    ui_dlg_ctl_command(dlg_title,"idchange","list")
else if a_dlg_button = "report" then
    a_dlg_button = ""
    ui_dlg_ctl_command(dlg_title,"idchange","report")
else if a_dlg_button = "smallicon" then
    a_dlg_button = ""
    ui_dlg_ctl_command(dlg_title,"idchange","SmallIcon")
else if a_dlg_button = "idchange" then
    a_dlg_button = ""
    ui_msg_box("Note","User clicked on : " + id )
end if
%code%)

 

 

 

 

UX Component - FormView Control - Pre-defined Editors - AlphaNumeric KeyPad Editor - A new pre-defined editor for editing character and numeric values in a FormView control (without using the Native keyboard on a mobile device) has been added.

The editor, as shown in the two images below, display the AlphaNumeric KeyPad editor in its two possible configurations. In the first image, the KeyPad is shown as it would be displayed on a Phone.

In the second image, the KeyPad is shown as it would be displayed on a Tablet.

 

 

 

 

 

 

 

To add the editor to a UX component, select the [Editor-AlphaNumericKeyPad] from the Defined Controls section of the toolbox.

 

 

To configure the keypad settings, click the smart field for the Editor configuration genie property in the FormView builder.

 

 

 

The genie allows you to configure various aspects of the keypad.

 

 

UX Component - FormView Control - Pre-defined Editors - Time Value Editor - A new pre-defined editor for editing time values in a FormView control has been added.

The editor, as shown below, displays SpinList controls for the hour, minutes and AM/PM values.

The editor also displays a button to set the selection in the SpinList controls to the current time.

You can configure the editor to hide the 'Now' button.

 

To add the TimeSpinLists editor to a UX component, select the [Editor-TimeSpinLists] item in the Defined Controls section of the UX toolbox.

 

 

To configure the Time value editor, click the smart field for the Editor configuration genie property in the FormView builder on the Fields tab.

The configuration genie allows you to specify if the 'Now' button should be shown.

 

 

 

 

UX Component - FormView Control - Pre-defined Editors - Date/Time Value Editor - A new pre-defined editor for editing date/time values in a FormView control has been added.

The editor, as shown below, displays SpinList controls for the month, day, year, hour, minutes and AM/PM values.

The editor also displays a button to set the selection in the SpinList controls to the current date and time.

You can configure the editor to hide the 'Now' button and to show a 'Clear' button which 'un-sets' the date/time value.

 

To add the DateTimeSpinLists editor to a UX component, select the [Editor-DateTimeSpinLists] item in the Defined Controls section of the UX toolbox.

 

 

To configure the Time value editor, click the smart field for the Editor configuration genie property in the FormView builder on the Fields tab.

The configuration genie allows you to specify if the 'Now' button should be shown.

 

UX Component - FormView Control - Pre-defined Editors - Numeric Keypad Editor - A new pre-defined editor for editing numeric values in a FormView control has been added.

The editor, as shown below, displays a keypad that allows the user to enter numbers. When editing a value using the numeric keypad, the native keyboard on a mobile device is not used.

A configuration genie allows you to specify various settings for the keypad.

 

 

To add the Numeric KeyPad editor to a UX component, select the [Editor-NumericKeypad] item in the Defined Controls section of the UX toolbox.

 

 

 

 

To configure the Numeric KeyPad  editor, click the smart field for the Editor configuration genie property in the FormView builder on the Fields tab.

 

 

The configuration genie (shown below) allows you to configure various settings for the keypad.

 

The Custom formatting Javascript allows you to define code that formats the number when it is displayed in the Keypad number display area.

For example, in the image below, the number is formatted to display a $ sign and two decimal places.

 

 

To achieve this, the Custom formatting Javascript property was defined as:

 

return Number(val).toFormat('$#,##0.00;$ (#,##0.00);------');

 

UX Component - ControlBar Control - Disclosures - Injectible Content - When you create a Disclosure in a ControlBar you can now set the Disclosure type to Injectible Container.

Previously, you could add a special Injectible Content placeholder in the HTML that you defined for the Disclosure. Setting the Disclosure type to Injectible Container is easier than using Injectible Content placeholders in the HTML and it has another advantage -- it makes it very easy to display List controls in the disclosures displayed by the Control Bar.

 

Watch Video - Part 1
Watch Video - Part 2

Download Component

 

 

CSS - Shared Styles - You can now define CSS styles that are shared across all stylesheets. Shared styles can be defined at the system level or at the project level.

The shared styles are stored in the following locations:

The shared styles are defined in a file called style.sass in the _sharedStyles folder. The shared styles can include SASS definitions.

For example, if you define a CSS selector called .style1 in the [Project Folder]\css\_sharedStyles\style.sass file, this selector will be available in all components, regardless of what stylesheet the component uses.

 

 

UX Components - ControlBar Control - Disclosure Buttons - Margins -  You can now specify margins for the content that is displayed in a ControlBar disclosure.

 

 

For example, in the image below, the List in Window disclosure button in the ControlBar in the UX footer displays a disclosure and sets the top, bottom, left and right margins to constrain the size of the disclosure content, giving the impression that the List is displayed in a window.

 

 

 

AlphaLaunch - AEX Files -  When you register a UX component as an AlphaLaunch App you can now specify that .aex files for this App should be compiled and published.

 

Xdialog -WaitDialog - You can now set the width of the Xdialog Waitdialog.

 

 

 

Example:

 

dim p3 as waitdialog
p3.create(3,"bounce",500) 'set with width to 500
p3.set_color("dark green")
p3.Set_Bottom_Message("This is the bottom row message - line1." + crlf() + "Line2")
p3.Set_Message("This is the top row message.")

 

'to close the waitdialog

p3.close()

 

 

 

UX Component - List Control - Allow Any Value - The List control now has a new property, Allow any value, that allows you to set the List value to a value not in the List data. If this property is not checked (the default), you cannot set the List value to a value that is not in the List data.

 

UX Component - Defined Control - Time Editor for FormView Control - A new pre-defined editor for a time value in a FormView control is available.

To select the time value editor, select [Editor-TimeSpinLists] from the list of controls in the Defined Controls section.

 

 

The image below shows a form control on the left with a time value and a time value editor on the right. The time value editor is implemented using three spin lists - one for hours, one for minutes and one for AM/PM.

You can modify the values in the hours spin list if you want to user to select minutes in multiples of 5, 10, 15 minutes, etc.

 

 

AlphaLaunch - Download Applications from S3 - By default, when you publish an App to AlphaLaunch, the AlphaLaunch client (i.e. the App running on the mobile device) will download the App from the same folder to which the App was published. The App will be published to a folder in the webroot of the standard Alpha Anywhere server, the Alpha Anywhere IIS server, or AlphaCloud.

However, you can also publish the app to a S3 bucket and when the AlphaLaunch user tries to install a new App, the App files will be downloaded from S3, rather than from your Alpha Anywhere server. Of course, once the user actually starts using the App on their device, Ajax callbacks will be handled by your Alpha Anywhere server.

The benefit of downloading Apps from S3 is that you offload work from your Alpha Anywhere server to S3. Also, in certain cases, when using an Android device and downloading an App from an Alpha Anywhere standard server, the install might fail because the App has too many files. By using S3 as the download location, you can circumvent this problem.

 

If you want to publish the App to S3, check the Use Amazon S3 as download site for AlphaLaunch Apps checkbox on the Publish to AlphaLaunch dialog.

 

 

You will need to specify:

 

Xbasic - SQL Server Reporting Services - a5w_report_saveAs() Function - You can now use the a5w_report_saveAs() function to print SSRS reports.

 

Syntax

c filenameOut = a5w_report_saveAs(c reportname, c type, c filter, c order, c filename,P globalVariables , P printOptions, sql::arguments Args)

 

Where

 

Example:

 

dim reportName as c
reportName = "customersbystate.ssrs.a5rpt"


dim args as sql::Arguments
args.add("whatcountry","UK")
 

dim filename as c

filename = a5w_report_saveAs(reportname,"pdf","","","c:\pdf\report1.pdf",null_value(),null_value(),args)
sys_open( filename)

 

 

UX Component - List Control - Detail View - Incremental Refresh After List Populate - A pattern that some mobile App developers use when building offline applications is to automatically do an incremental List refresh when the App is first loaded. This ensures that the user has up to date data on their device. An incremental List refresh (rather than a full refresh) is done so that any unsynchronized edits are not lost. There was no obvious event in which the incremental refresh could be triggered, especially if the List had been configured to download media files to the filesystem.

Therefore, to make this pattern easy to set up, a new property has been added to the List. The Do incremental refresh after List is populated property will allow you to kick off an incremental refresh of the List after the List has been populated.

 

 

UX Component - Action Javascript - File Upload Action - S3 Timeout - When you upload to S3, you can now specify a timeout setting. If you are uploading a large number of files, you might need to increase this setting otherwise, you might get 'permission expired' errors from S3 indicating that the time window in which uploads are permitted has expired.

 

 

 

 

PhoneGap Applications - Usage Descriptions for Plugins -  PhoneGap Build now allows the addition of a <config-file> element into the config.xml file.

http://docs.phonegap.com/phonegap-build/configuring/config-file-element/

This lets you add xml directly to the iOS Info.plist file and Android AndroidManifest.xml file.

This solves an error that you might get when submitting an app to the Apple App Store. The error complains about certain UsageDescription strings not being set in PhoneGap Build Plugins.

E.g.


Camera Plugin : NSCameraUsageDescription

Calendar Plugin : NSCalendarsUsageDescription
 

The entry into the config.xml file to set the UsageDescription strings is:


<config-file platform="ios" parent="NSCalendarsUsageDescription" mode="replace">
    <string>This app will use the Calendar</string>
</config-file>
 


 

 

UX Component - Client-Side Events - onConnectionChange Event - The onConnectionChange event when the device either gets a connection, or looses its connections. The event has a parameter that tells you whether the device has or does not have a connection. Previously, this parameter was not always accurate. Now, it can be relied on.

A common use case for this event is to only show a 'sync' button on a mobile device when a connection is available. In addition, before executing an Ajax callback you might want to first check that the Alpha Anywhere server is responding (it is possible for the Alpha server to be offline even though the device has a connection).

In summary, here are the events and methods that you can use in a Mobile app.

 

Example use of .serverIsAvailable() method

 

var _ok = function() {
    alert('server responded');
};

var _err = function() {
    alert('server did not respond');
};
 

//wait up to 500 milliseconds before calling either the _ok or _err callback function
{dialog.Object}.serverIsAvailable(500,_ok,_err);

 

 

UX Component - List Control - <listObject>.setValue() Method - Several new options have been added to the .setValue() method.

NOTE: These new options only apply if the List is set to allow multi-selection.

 

 

Examples:

//adds values to the current selection
listObj.setValue({select: 'add', value : ['Smith','Jones']});

//remove values from the currently selected value
listObj.setValue({select: 'remove', value: ['Smith','Jones']});

//toggles the selected state of the items in the value array
listObj.setValue({select: 'toggle', value: ['Smith','Jones']});

//select rows in a list programmatically. If function returns true, row is selected.
listObj.setValue({select: 'match', match: function(value,data) {
        //value and data for the current row
        if(data.Country == 'USA') return true;
        else return false;

    }
   }

);

//select rows in a list programmatically. Optionally add to the existing selection
listObj.setValue({select: 'match', additive: true, match: function(value,data) {
    //value and data for the current row
        if(data.Country == 'UK') return true;
        else return false
    }
  }

);
 

UX Component - Alignment Container - Centering Content - The Alignment container allows you to easily center align content. If you have multiple controls in an Alignment container, each control is horizontally centered on its own line.

 

 

However, if you wanted (say) Control 1 and Control 2 to both be on the same line, and center align the combined width of the two controls, you can now wrap Control 1 and Control 2 in a container within the Alignment container.

UX Component - List Control - Lazy Image Loading - A new genie is available to set up a List to use Lazy Image Loading.

A common use case for Lazy Image Loading is when you have a List that displays images that are sourced from a server. If the List has a large number of rows, fetching all of the images from the server will slow down the initial render of the List. However, by implementing Lazy Image Loading, only the images for the rows that are currently scrolled into view will be fetched.

 

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

You can set a wait time that the List will wait after a row comes into view before the images for the visible rows will be fetched. This prevents fetching images for rows that you scroll past without stopping on. When a row that displays an image that has not yet been fetched is displayed, a 'waiting' image will be displayed. Once the image has been fetched, the 'waiting' image will be replaced with the real image.

To access the Quick Setup Genie, open the List control builder. Click on the Quick access... button at the bottom of the window and then select the List Quick Setup Genie menu item.

 

 

Once the Quick Setup Genie opens, select the Lazy Image Loading option.

 

 

The genie allows you to configure a number of options, such as the name of field in your List data that contains the image URL for the image to display in each row. You can also set the URL of the wait image (the image to display before the real image has been fetched).

When you exit the genie, the genie will automatically set several properties in the List, such as the onListDraw and onScroll event, the List template, etc.

 

AlphaDAO - oData - Authentication Options - You can now specify an Authentication option when building an oData connection string.

 

 

The options are:

 

 

UX Component - List Control - DetailView - addTableRow() Method - The addTableRow() method allows you to programmatically add new rows to a List with a Detail View.

If you are using this method in a loop, then you can add many new rows to a List quite quickly. Under certain circumstances, this might cause a problem.

The circumstances under which this could cause a problem are:

  1. The List is set to persist to storage (so that the application can function offline)
  2. The List storage is set to FileSystem
  3. The App is running in Phonegap.

 

The reason that there is a potential problem under the above scenario is that writing to the FileSystem in PhoneGap is an asynchronous operation. Each time the List is updated, the edits to the List are saved in files written to the FileSystem. But since these write operations are asynchronous, it is possible (actually likely), that the write operation for the next record added to the List will be initiated before the write operation for the current record added to the List has completed, and so on. These overlapping write operations to the FileSystem could corrupt the files used to store the List edits.

The solution to this potential problem is to temporarily suspend persisting the List while the .addTableRow() method is being called in a loop and then once the loop has completed, turn the suspension off and persist the List to storage.

To suspend persisting to the List, you set the List's .suspendPersist property to true.

To turn persisting back on, you set the List's .suspendPersist to false

To manually persist the List after you have turned suspend persist off use the List's .persistToStorage() method. You must pass in an empty object when calling this method.

 

For example:

       


//persist multiple rows in a loop

var listObj = {dialog.object}.getControl('list1');

//suspend list persisting
listObj.suspendPersist = true;

//execute the .addTableRow() method in a loop

//turn list persisting back on
listObj.suspendPersist = false;

//persist the list (passing in an empty object to the .persitToStorage() method.
listObj.persistToStorage({});
 

 

 

UX Component - Panel Navigator - Carousel Mode - If you are swiping to the left or the right to navigate from one Panel Card to another, if the Panel Card you are navigating from allows for vertical scrolling, you could easily start scrolling the Panel Card vertically while you were also swiping left or right. This creates an undesirable visual effect. Now, once you start moving the Panel Card to the left or right (to transition from one Panel Card to another), vertical scrolling the Panel Card is disabled.
 

AlphaDAO - SQLite - AlphaDAO now has built-in support for SQLite. Previously, you could connect to a SQLite database by installing an ODBC driver. However, since there was no syntax handler for SQLite, there was no support for Portable SQL or the Portable SQL functions that AlphaDAO exposes. As a result, certain operations would fail.

Now, with built-in support for SQLite, there is no longer any need to install an ODBC driver and all Portable SQL functions (with the exception of Geography functions, which SQLite does not support) are supported.

Full details on SQLite support are in the documentation.

 

UX Components - Checkbox and Radiobutton Controls - Render as ButtonList - Icon Alignment - A new property has been added to the builder allowing you to better control the placement of the icon relative to the text.

The Button style property has these options:

 

 

Bugs

Application Server - Stripe - The Stripe methods (built into Alpha Anywhere using Action Javascript) did not work when using the Application Server. This was because the Stripe methods use a Node.js module and the Node modules were not getting installed when the Application Server was installed.

UX Components - List Control - Detail View - Persist to FileSystem - Various improvements have been made to the way the List control persists offline data to the file system.

Application Server - Alternate Login - Facebook - As a result of a change Facebook made to the data returned on a successful login, the Facebook Alternate Login was throwing an error. This is now fixed.

 

UX Component - Apply Security Client-side - If you checked the option to apply security client-side, but did not also check the option to pre-render the component at design-time, the security settings were not applied on the client-side.

 

UX Component - Image Controls - Touch Events - Mobile Devices - 300ms Delay - If you defined a touch event for an image control, on a mobile device, the browser would add a 300ms delay before firing the event. This is now fixed.

 

UX Component - List Control With Detail View - CRUD Operations - Regional Settings - If the regional settings on the server specified a comma as the decimal characters, and the UX was configured to show decimals with a period and to require decimal numbers to be entered with a period, update and insert operations would fail.

SSRS Reports - Internal Parameters - When defining a SSRS report you can specify that certain parameters are 'internal' Previously, when printing a report that has internal parameters, the UI would prompt for values for internal parameters. Internal parameters should not have been exposed in the user interface.

AlphaLaunch - Embedded UX Components - The URL for Ajax Callbacks was not getting set correctly for child UX components loaded by the master UX component if the child UX components were set be 'precomputed' (rather than loaded by making an Ajax Callback0.

UX Component - Absolute Container - Bulk Operations - Recalculate UX Components - If you performed a bulk recalculate of UX components, the settings in an Absolute Container were lost.

UX Component - List Control - Detail View - Persist List Data to Storage - FileSystem - Incremental Refresh - In build 4.4.4, the ability to persist the List data to the filesystem, rather than localStorage, was introduced. This provided for a large increase in the amount of data that could be used in offline mobile apps.  A bug was fixed when doing an incremental refresh on the List when the List data was being persisted to the filesystem.

UX Component - List Control - Order - Multi-level sort definitions did not work correctly.

UX Component - List Control - Detail View - Client-side Grouping - New Records - If a List had client-side group breaks, then after a new record was added and the List was synced, focus did not remain on the new record.

Reports - Report Server - Storage Connection Strings - If a report had a reference to an Amazon S3 image that used JSON syntax for the image name, the storage connection string could not be resolved if the report was printed using the Report Server.

Tips

Sample Mobile Application - Export to Excel - This sample application shows how you can create a mobile application that has a button that makes an Ajax callback to the server. The Xbasic function that handles the callback creates an Excel file and then the mobile device downloads the excel file and opens it using the native Excel viewer on the device.

Download example

 

 

UX Component - PhoneGap - iOS Keyboard - Next / Previous Keyboard Buttons - When you run a UX component on a native iOS device, the native iOS keyboard has next/prev buttons to navigate to the next and previous input control on the screen. If you have a UX component with multiple panels and focus is on the last input control on the currently visible Panel, if you tap the next button, focus will go to the next input control, which may be a Panel Card that is not currently visible. Clearly, this is undesirable.

The solution is to disable input controls that are not currently on a visible PanelCard.

Assume you have a PanelNavigator (called 'PANELNAVIGATOR_1') with child PanelCards.

 

You could add the following expression the the client-side enable expression for each of the input controls.

 

enableControl('PANELCARD_1')

 

where 'PANELCARD_1' was the name of the Panel Card in which the input control had been placed.

 

The enableControl() function would be defined as follows:

 

function enableControl(txt) {
var p = {dialog.object}.panelGet('PANELNAVIGATOR_1');
var ps = p.state;
if( p.state.activePanel == txt) return true;
return false;
}

 

This function will return true if the active PanelCard name matches the passed in PanelCard name.

 

So, only input controls on the currently active PanelCard will be enabled and the iOS keyboard next/previous buttons will only cycle through the controls on the current PanelCard.

 

 

 

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 - P