Don't panic!

Before you read the manual, check out the Don't panic! slides.

Make love, not code! (M13E) definition file

Table of Contents

Definition file format
Default number, date, and time formats
Text Constants and Style Sheet
Descriptions of the individual XML elements
definition
table
column of table
global (Server-Side)
functions (Server-Side)
checkPermission
log
executeBeforeInsert
executeBeforeUpdate
executeBeforeDelete
executeAfterInsert
executeAfterUpdate
executeAfterDelete
getSelectWhereClause
getDisabledActions
executeBeforeFileUpload
executeBeforeFileDelete
executeAfterFileUpload
executeAfterFileDelete
jsFunctions (Client-Side)
onApplicationStart
onBeforeHttpRequest
onAfterTabChange
onMessage
onOptionsLoad
onRecordsLoad
onRecordsRefresh
onBeforeSave
onAfterSave
onBeforeDelete
onAfterDelete
onBeforeNew
onAfterNew
onBeforeCancel
onAfterCancel
onBeforeExport
onAfterExport
onSelectedRecordChange
onBeforeConstruction
onAfterConstruction
onBeforeDetailWindowClose
onAfterDetailWindowClose
onBeforeFileUpload
onAfterFileUpload
onBeforeFileDelete
onAfterFileDelete
options
option
tab
header
footer
control
validator
dataGrid
column of dataGrid
checkList
button
Extra features
Selecting a record and a tab on load
I'm a hardcore developer! Show me more!
Licenses

Definition file format

The definition file is an UTF-8 encoded XML file.

Default number, date, and time formats

Number: Decimal Separator: . (dot)
Thousands Separator: no separator (empty string "")
For example:
123456.12
Date: YYYY-MM-DD (Y: year, M: month, D: day)
For example:
2019-04-21
Time: HH:MM:SS (H: hour, M: minute, S: second)
For example:
23:43:13
Date+Time: YYYY-MM-DD HH:MM:SS
For example:
2019-04-21 23:43:13

Text Constants and Style Sheet

Text constants (i18n) and custom style sheet are currently not supported. (Development in progress.)

Descriptions of the individual XML elements

definition

Description:

The root element. It contains the table, zero or more options elements, zero or one functions element, zero or more tab elements and the dataGrid element. If the XML only contains table element with column elements, the app generator completes the XML definition after pressing the Generate my app button, but before processing the XML data: a tab element is added with input fields for every column, where the label of the input field is the name of corresponding column (column of the table), the type of the input field is textInput, and a dataGrid also added with dataGrid column for all columns.

Attributes:

Attribute Description
windowTitle Label of the maintenance window.
colonUsedAtItemLabels Is there a colon at the end of the individual form item labels?
Possible values: true or false
Default value: true
heartbeatPeriod Session heartbeat interval in seconds.
Default value: 300
databaseType The database type.
Possible values: mysql, postgresql
Default value: mysql in myDbDiffo, postgresql in pgDbDiffo
maxWidth Maximum width of the window, in pixels. If not specified or empty string, the window is full width.
maxHeight Maximum height of the window, in pixels. If not specified or empty string, the window is full height.
layout Layout of the main component (dataGrid or checkList) and the form.
Possible values: split, popup, oneToMany, manyToMany, form
Default value: split
split: The main component and the form are displayed in one, vertically split window.
popup: The main component is displayed in the main window, with the form in a pop-up window.
oneToMany: A layout used to display and modify records related to records displayed in a given a window with split or popup layout (one-to-many relationship). Cannot be a standalone layout. It is displayed in the iframe control.
manyToMany: A layout used to display and modify records related to records displayed in a given a window with split or popup layout (many-to-many relationship). Cannot be a standalone layout. It is displayed in the iframe control.
form: It does not have a main component. (A split layout without a dataGrid.) Only the form is displayed, so remove the dataGrid element from your XML code. (M13E automatically generates an XML code with a dataGrid.) It can be used for displaying a record in a popup or in a new blank window. You must provide the value of the key column of the record in the URL as a parameter. The name of the parameter is selectedrecord. E.g. https://example.com/myapp/users.php?selectedrecord=18
popupWindowTitle The label of the pop-up window (see popup layout).
You can use a template or a constant text. Evaluated expressions are delimited with { and } characters.
When another record is selected in the dataGrid with a double click or click, the value of the popupWindowTitle is reevaluated before the pop-up window appears.
To refer to a certain field of the current selected record in the template use the name of the column in the expression. The most simple form:
{column_name}
If a column refers to another table (e.g. master data) you can define options element for that table and you can use the name of the options element as a function in the expressions. This function has only one parameter, the identifier value (see options value attribute), and returns the option object identified by the parameter value. This option object and its properties can be used in the expression, too.
For example:
You want to display the id of an order item with the product name. The orderitems table refers to the products table (orderitems.prod_id -> products.prod_id). You define an options for the products with the name products, so you can use it in templates.
...
<options name="products" value="prod_id" label="prod_name" 
	sourceURL="products.php?action=SELECT" 
	maintenanceURL="products.php" 
	orderBy="prod_name" />
...
popupWindowTitle="#{ord_item_id} {products(prod_id).prod_name}"
Result: #2 DELL XPS
where ord_item_id is a column of the orderitems table for which this app is generated, products is a function/options (in this example the products table has a data maintenance app generated with M13E, too), and option objects of the options have prod_id and prod_name fields (products table has the following columns: prod_id, prod_name, net_price, etc.).
maxPopupWidth Maximum width of the pop-up window, in pixels. If not specified or empty string, the pop-up window is full width.
maxPopupHeight Maximum height of the pop-up window, in pixels. If not specified or empty string, the pop-up window is full height.
allOptionsRefreshed If any options records were modified by the user through the dropdown list’s modify function, a true value means that all options records are updated to reflect changes.
Possible values: true or false
Default value: true
frameworkEmbedded If true, the Haxentric framework’s JavaScript code is also embedded into the generated code. If false, the framework can be downloaded as a standalone JavaScript file, and the generated code links to it as an external file.
Possible values: true or false
Default value: true
language A two-character ISO language code. (E.g. en, hu)
Together with the country attribute, determines the language and locale settings of the generated data maintenance application.
country A two-character ISO country code. (E.g. US, HU)
Together with the language attribute, determines the language and locale settings of the generated data maintenance application.
localeOverridable If true, the locale settings (language and country) can be overridden with a PHP m13e_locale session variable ($_SESSION["m13e_locale"], e.g. $_SESSION["m13e_locale"] = "en_US";). If false, the application always uses the language and country values set in the language and country attributes.
Possible values: true or false
Default value: true
popupCloseOnSave If true, when the user presses the Save button, the program closes the pop-up window. If false, the pop-up window remains open. (see popup layout)
Possible values: true or false
Default value: true
recordRefreshedOnOpen If true, when the user selects a record with a double click, the program refreshes the record from the database before it opens the pop-up window. If false, the selected record is not refreshed. (see popup layout)
Possible values: true or false
Default value: false

Example #1:

<definition windowTitle="Persons">
	<table name="...">
	...
	</table>
	<tab label="Data">
	...
	</tab>
	<tab label="Data 2.">
	...
	</tab>
	...
	<dataGrid>
	...
	</dataGrid>
</definition>

table

Description:

Descriptor element of the database table. Only one exists. Contains one or more column elements.

Attributes:

Attribute Description
name Name of the database table. Required!
orderBy Defines the server side ordering of records displayed in the table. (List of columns, SELECT statement’s ORDER BY part.)
E.g. name, age desc

Example #1:

<table name="persons">

</table>

column element of table element

Description:

Descriptor element of the column of the database table. One or more may exist. Empty element, cannot contain other elements.

Attributes:

Attribute Description
name Name of the column of the database table. Required!
key Indicates whether the column is a primary key. Composite primary keys are not supported, thus it can only have the true value in one column (with an integer data type).
Possible values: true or false
Default value: false
type Type of the column. (Not case-sensitive.) Required!
Possible values for MySQL: TINYINT, SMALLINT, MEDIUMINT, INT, INTEGER, BIGINT, DECIMAL(precision[, scale]), DEC(precision[, scale]), FIXED(precision[, scale]), NUMERIC(precision[, scale]), FLOAT, REAL, DOUBLE, DOUBLE PRECISION, DATE, TIME, DATETIME, TIMESTAMP, VARCHAR(length), CHAR(length), TEXT, CLOB, TINYTEXT, MEDIUMTEXT, LONGTEXT, JSON
And if your MySQL version supports it, you can use UNSIGNED numeric types, too. (e.g. TINYINT UNSIGNED)
Possible values for PostgreSQL: SMALLINT, SMALLSERIAL, INT2, SERIAL, INT, INT4, INTEGER, BIGINT, BIGSERIAL, INT8, DECIMAL(precision[, scale]), NUMERIC(precision[, scale]), REAL, FLOAT4, DOUBLE PRECISION, FLOAT8, MONEY, OID, VARCHAR(length), CHAR(length), TEXT, XML, JSON, TIMESTAMP, TIMESTAMP WITH TIME ZONE, DATE, TIME, TIME WITH TIME ZONE, INTERVAL, BOOLEAN, BIT(length), BIT VARYING(length)
For example: varchar(100), integer, date, numeric(10), numeric(18,2)
Default value: varchar(200)
nullable Indicates whether the column can be null.
Possible values: true or false
Default value: true
defaultValue Default value of the column. Currently not in use.
An empty attribute value means there is no defaultValue.
For string types, use single quotes. E.g. 'T'
label Label of the column. It is displayed before the input field in the form, in the column’s header in the dataGrid, and in the ODS file (spreadsheet file) as column header. Required!
Please note: May be overriden by the control label or the dataGrid column label attribute.
mapping If the input field type is checkBox or the renderer in the dataGrid’s column is checkBox, you can define the value of the field in the database when checkBox is selected or not selected. Values must be listed separated by commas (without spaces). The first value is used when checkBox is selected, the second when it’s not selected.
The boolean values of checkBox are mapped to the values entered by the developer. You can only enter values with the same type as type of the column related to the input field.
For example:
mapping="T,F"
If checkBox is selected, the value of the specified field of the specified record will be a T character within the database. (In this case, the type of the column is char(1).)
mapping="1,0"
If checkBox is selected, the value of the specified field of the specified record will be 1 within the database. (In this case, the type of the column is smallint (or some other integer).)
Please note: May be overriden by the control mapping or the dataGrid column mapping attribute.
options Item list of comboBox or radioButton, also used to display selected record of comboBox or a column of a table (searches for a record from options with the same value as the column’s value – the displayed value is label from options). An options name value must be entered here.
value An expression for the column value.
Saving will set the value of the field of the current record with the value evaluated from this expression. The current record can be accessed using the selectedRecord variable.
E.g.
selectedRecord.net_price==null ? 
  (this.getOption_ops_products(selectedRecord.prod_id).net_price) : 
  selectedRecord.net_price
parentColumnName If the layout is oneToMany or manyToMany, you can use this attribute to specify the column that refers (column name attribute) to the column in the parent table (parentColumnName) in the one-to-many or many-to-many relationship.
This must be specified in the column element that refers to the specified column (parentColumnName) of the referenced (or parent) table.
transient Indicates whether the column’s contents are saved to the database. It is used for calculated columns. The value of the column is defined by the expression in the value attribute. (See value attribute) If true, only the record in memory contains this column. In this case, it does not even have to be present in the database table under this name.
Possible values: true or false
Default value: false
thousandsSeparatorUsed Indicates whether thousands separator is used for formatting numbers. If true, the numbers are formatted with thousands separators. If false, the numbers are formatted without thousands separators (useful for ID).
Possible values: true or false
Default value: true

Example #1:

<column name="per_id" key="true" type="integer" nullable="false" />
<column name="lastname" type="varchar(100)" nullable="false" />
<column name="firstname" type="varchar(100)"  nullable="false" />
<column name="gender" type="char(1)" nullable="false" />
<column name="is_active" type="char(1)" />
<column name="birth_date" type="date" />

global

Description:

The global element can contain your server-side codes with global scope: global variable declarations, global functions (used by e.g. executeAfterInsert and executeAfterUpdate) or codes, which run every time the server-side script is called by the client-side application. Here you can include other server-side scripts, too.

Example #1:

<global>
  <![CDATA[
    include "utils.php";

    function sendEmailAfterInsertUpdate($connection, 
                                        $table, 
                                        $keyColumnName, 
                                        $oldObject, 
                                        $newObject)
    {
      $sql = "SELECT * FROM users WHERE user_id in " .
             "(SELECT DISTINCT user_id FROM taskgrantedroles WHERE " . 
             "task_id = ".intval($newObject["task_id"]).")";
      $result = $connection->query($sql);

      while($user = $result->fetch_assoc())
      {
          $headers = array();
          $headers[] = "MIME-Version: 1.0";
          $headers[] = "Content-Type: text/html; charset=UTF-8";
          $emailto = mb_encode_mimeheader($user["user_fullname"], 'UTF-8', 'Q') . 
                     ' <'.$user["email_addr"].'>';
          $headers[] = "From: " . 
                       mb_encode_mimeheader("Task Manager App", 'UTF-8', 'Q') . 
                       " <noreply@example.com>";
          $headers[] = "Sender: " . 
                       mb_encode_mimeheader("Task Manager App", 'UTF-8', 'Q') . 
                       " <noreply@example.com>";
          $message = '<html><head><meta charset="utf-8" /></head><body>' . 
                     $newObject["task_name"] . 
                     ' (#' . $newObject["task_id"] . 
                     ') has been created or modified.</body></html>';
          mail($emailto, 
               mb_encode_mimeheader($newObject["task_name"], 'UTF-8', 'Q'), 
               $message, 
               implode("\r\n", 
               $headers));
      }
    }
  ]]>
</global>
<functions>
    <executeAfterInsert>
	<![CDATA[
            $r = true;
            sendEmailAfterInsertUpdate($connection, 
                                       $table, 
                                       $keyColumnName, 
                                       null, 
                                       $newObject);
            return $r;
	]]>
    </executeAfterInsert>
    <executeAfterUpdate>
	<![CDATA[
            $r = true;
            sendEmailAfterInsertUpdate($connection, 
                                       $table, 
                                       $keyColumnName, 
                                       $oldObject, 
                                       $newObject);
            return $r;
	]]>
    </executeAfterUpdate>
</functions>
In this example, the user can create/modify/delete tasks with the generated application. When a user creates (executeAfterInsert) or modifies (executeAfterUpdate) a task the program sends an email to every user who has the required permission (taskgrantedroles table) to access this task. (See functions element, executeAfterInsert element and executeAfterUpdate element for more information.) The program includes the utils.php script, too.

functions

Description:

M13E allows you to extend or modify the behaviour of the generated application. You have to implement functions for the new features or modifications. A functions element contains the code of these functions. The functions are listed as individual XML elements under functions.
The following XML elements all contain the body or code of one such function. Use <![CDATA[…]]> if you don’t want to escape XML entities.

Example #1:

<checkPermission>
	<![CDATA[
		return $_SESSION["admin"]=="T";
	]]>
</checkPermission>
In this example, the generated app can be used only with admin privileges.

We provide the function header (signature) in the description, too. (The name of the functions are prefixed with m13e_ in the generated code.)
At the moment you can extend or modify your application with the following functions:

checkPermission

Description:

Checks whether the user (session) can execute a certain operation on the selected record (or a new record) of a certain table.

Function header:

function m13e_checkPermission($connection, $table, $keyColumnName, $oldObject, $newObject, $action)

Function parameters:

Parameter Description
$connection The database connection. (Legacy mysql interface: the link identifier; mysqli interface: the mysqli object; pgsql interface: the PgSql\Connection object)
$table The name of the database table.
$keyColumnName The name of the table’s key column.
$oldObject The object or record loaded by the server from the database.
This parameter contains the record’s previous, unmodified state. When using SELECT, COUNT or INSERT ($action), this parameter is null.
$newObject The object or record the server will store in the database. This parameter contains the record’s new, not yet saved state. When using SELECT, SELECT_SINGLE, COUNT or DELETE ($action), this parameter is null.
$action The action to execute (if enabled).
Possible values: SELECT_SINGLE, SELECT, INSERT, UPDATE, DELETE

Return value:

true, if the user (session) has the permission to execute the action, false, if not.

Example #1:

<functions>
    <checkPermission>
	<![CDATA[
		return $_SESSION["admin"]=="T";
	]]>
    </checkPermission>
</functions>
In this example, the generated app can be used only with admin privileges.

Example #2:

<functions>
    <checkPermission>
	<![CDATA[
                $r = true;
                if($action=="INSERT" || $action=="UPDATE" || $action=="DELETE")
                {
                    $r = $_SESSION["order-manager"]=="T";
                }
		return $r;
	]]>
    </checkPermission>
</functions>
In this example, everybody can use the generated app, everybody can view (select) the data, but inserting, updating and deleting records only available for order managers.

Example #3:

<functions>
    <checkPermission>
	<![CDATA[
                $r = true;
                if($action=="INSERT" || $action=="UPDATE" || $action=="DELETE")
                {
                    $roleSQL = "SELECT * FROM `system_roles` WHERE `user_id` = " . 
                               intval($_SESSION["userid"]) . 
                               " AND `role_id` = (SELECT `id` FROM `roles` " . 
                               "WHERE `role_name` = 'order-manager')";
                    $result = $connection->query($roleSQL);
                    $r = $result->num_rows > 0;
                }
		return $r;
	]]>
    </checkPermission>
</functions>
In this example, everybody can use the generated app, everybody can view (select) the data, but inserting, updating and deleting records only available for order managers. The order manager role is not stored in the session. The program executes a query on system_roles to check whether the user has the order manager (order-manager) role or not.

Example #4:

<functions>
    <checkPermission>
	<![CDATA[
                $r = true;
                if($action=="UPDATE" || $action=="DELETE")
                {
                    $r = $oldObject["is_archived"] != "T" || 
                         $_SESSION["superadmin"]=="T";
                }
		return $r;
	]]>
    </checkPermission>
</functions>
In this example, everybody can use the generated app, everybody can view (select) and modify (insert, delete, update) the data, but archived records (is_archived is "T") can be updated or deleted by super admin only.

log

Description:

Logs the SQL statements executed against the selected record (or a new record) of a certain table.

Function header:

function m13e_log($connection, $table, $keyColumnName, $oldObject, $newObject, $action, $sql)

Function parameters:

Parameter Description
$connection The database connection. (Legacy mysql interface: the link identifier; mysqli interface: the mysqli object; pgsql interface: the PgSql\Connection object)
$table The name of the database table.
$oldObject The object or record loaded by the server from the database.
This parameter contains the record’s previous, unmodified state. When using SELECT, COUNT or INSERT ($action), this parameter is null.
$newObject An object (or record) already stored in the database by the server.
This parameter contains the new, already saved state of the record, reloaded from the database by the server before the function call, so it reflects other changes as well (e.g. at saving, a trigger modified some fields of the record).
When using SELECT, SELECT_SINGLE, COUNT or DELETE ($action), this parameter is null.
$action The action to execute (if enabled).
Possible values: SELECT_SINGLE, SELECT, INSERT, UPDATE, DELETE
$sql The executed SQL statement.

Return value:

true, if logged succesfully, otherwise false.

Example #1:

<functions>
    <log>
	<![CDATA[
            $r = true;
            
            $t="oldObject:\r\n". json_encode($oldObject);
            $t.="\r\n\r\n";
            $t.="newObject:\r\n". json_encode($newObject);

            $logSQL = "INSERT INTO `log` " . 
                      "(`table`, `action`, `user_id`, `sql`, `description`) " .
                      " VALUES (" .
                      "'".$table."', " .
                      "'".$action."', " .
                      intval($_SESSION['userid']).", " .
                      "'".mysqli_real_escape_string($connection, $sql)."', " .
                      "'".mysqli_real_escape_string($connection, $t)."' " .
                      ")";
            $result = $connection->query($logSQL);
            if($result===false)
            {
                $r = false;
            }
            return $r;
	]]>
    </log>
</functions>
In this example, the generated app logs every action (select, insert, update, delete,...) INTO the log table. The $oldObject and $newObject are JSON encoded, concatenated and stored in the description column.

executeBeforeInsert

Description:

Before a new record is inserted (saved) to the database, this function allows to change its state, or perform other database operations.

Function header:

function m13e_executeBeforeInsert($connection, $table, $keyColumnName, &$newObject)

Function parameters:

Parameter Description
$connection The database connection. (Legacy mysql interface: the link identifier; mysqli interface: the mysqli object; pgsql interface: the PgSql\Connection object)
$table The name of the database table.
$keyColumnName The name of the table’s key column.
$newObject The object (or record) sent by the client to the server, not yet stored by the server in the database.
This parameter contains the record’s new, not yet saved state, which can be changed by the developer.

Return value:

null or true, if no error occurs (in this case the subsequent INSERT is allowed to run), or the text of the error message as a string (the subsequent INSERT cannot run).

Example #1:

<functions>
    <executeBeforeInsert>
	<![CDATA[
            $newObject["recorder_user_id"] = $_SESSION['userid'];
            return true;
	]]>
    </executeBeforeInsert>
</functions>
In this example, the generated app stores the user ID of the current user in the record (recorder_user_id) before it is inserted.

Example #2:

<functions>
    <executeBeforeInsert>
	<![CDATA[
            $r = true;
            if(strcmp($newObject["order_date"], date("Y-m-d"))>0)
            {
                $r = "The order date cannot be in the future.";
            }
            return $r;
	]]>
    </executeBeforeInsert>
</functions>
In this example, the generated app, which stores orders, checks the order date (order_date) before insert. If the order date is in the future the function returns the "The order date cannot be in the future." error message, which is displayed by the app. The user cannot create new orders where the order date is in the future.

Example #3:

<functions>
    <executeBeforeInsert>
	<![CDATA[
            $r = true;
            $sql = "SELECT * FROM `customers` WHERE `cust_id` = " . 
                   intval($newObject["cust_id"]);
            $result = $connection->query($sql);
            if($result!==false)
            {
              if($customerROW = $result -> fetch_assoc())
              {
                if($customerROW["is_blacklisted"]=="T")
                {
                  $r = "This customer has been blacklisted. " . 
                       "You cannot record an order for this customer.";
                 }
              }
              else
              {
                $r = "This customer has been deleted. " . 
                     "You cannot save your order.";
              }
            }
            else
            {
              $r = $connection->error;
            }
            return $r;
	]]>
    </executeBeforeInsert>
</functions>
In this example, the generated app, which stores orders, checks whether the customer is blacklisted or not. First the program tries to read the customer record. If the customer does not exist anymore, the program returns the "This customer has been deleted. You cannot save your order." error message, which is displayed by the app. If the customer exists the program checks whether the customer is blacklisted or not. If the customer is blacklisted, the program returns the "This customer has been blacklisted. You cannot record an order for this customer." error message, which is displayed by the app.

executeBeforeUpdate

Description:

Before a record is modified (updated/saved) in the database, this function allows to change its state, or perform other database operations.

Function header:

function m13e_executeBeforeUpdate($connection, $table, $keyColumnName, $oldObject, &$newObject)

Function parameters:

Parameter Description
$connection The database connection. (Legacy mysql interface: the link identifier; mysqli interface: the mysqli object; pgsql interface: the PgSql\Connection object)
$table The name of the database table.
$keyColumnName The name of the table’s key column.
$oldObject The object or record loaded by the server from the database before it is changed.
This parameter contains the record’s previous, unmodified state.
$newObject The object (or record) sent by the client to the server, not yet stored by the server in the database.
This parameter contains the record’s new, not yet saved state, which can be changed by the developer.

Return value:

null or true, if no error occurs (in this case the subsequent UPDATE is allowed to run), or the text of the error message as a string (the subsequent UPDATE cannot run).

Example #1:

<functions>
    <executeBeforeUpdate>
	<![CDATA[
            $newObject["last_modifier_user_id"] = $_SESSION['userid'];
            return true;
	]]>
    </executeBeforeUpdate>
</functions>
In this example, the generated app stores the user ID of the current user in the record (last_modifier_user_id) before it is updated.

Example #2:

<functions>
    <executeBeforeUpdate>
	<![CDATA[
            $r = true;
            if(isset($oldObject["shipping_date"]))
            {
              $r = "This order has already been shipped. " . 
                   "You cannot modify this order.";
            }
            else
            if($oldObject["cust_id"])!=$newObject["cust_id"])
            {
              $r = "You cannot modify the customer field of an order.";
            }
            else
            if(strcmp($newObject["shipping_date"], date("Y-m-d"))<0)
            {
              $r = "The shipping date cannot be in the past.";
            }
            return $r;
	]]>
    </executeBeforeUpdate>
</functions>
In this example, the generated app, which stores orders, checks the order before updating it. If the shipping date (shipping_date) is not null the function returns the "This order has already been shipped. You cannot modify this order." error message, which is displayed by the app. If the user changed the customer of the order (cust_id) the function returns the "You cannot modify the customer field of an order." error message which is displayed by the app. If the shipping date (shipping_date) is in the past the function returns the "The shipping date cannot be in the past." error message, which is displayed by the app.

Example #3:

<functions>
    <executeBeforeUpdate>
	<![CDATA[
            $r = true;
            if(!isset($oldObject["delivery_date"]) && 
               isset($newObject["delivery_date"]))
            {
              $sql = "SELECT * FROM `couriers` AS cs WHERE ".
                     "(SELECT count(*) FROM `deliveries` AS ds " . 
                     "WHERE ds.`courier_id` = cs.`id` AND ds.`delivery_date` = '" .
                     mysqli_real_escape_string($connection, 
                                               $newObject["delivery_date"]) . 
                     "') < 20 LIMIT 1";
              $result = $connection->query($sql);
              if($result!==false)
              {
                if($courierROW = $result -> fetch_assoc())
                {
                  $newObject["courier_id"] = $courierROW["id"];
                }
                else
                {
                  $r = "No courier is available for this delivery date: " . 
                       $newObject["delivery_date"];
                }
              }
              else
              {
                $r = $connection->error;
              }
            }
            return $r;
	]]>
    </executeBeforeUpdate>
</functions>
In this example, the generated app, which stores orders, sets the courier of the order (courier_id) before executing the update. If the program founds a courier, which has lesser than 20 deliveries for the specified delivery date (delivery_date), it sets the courier of the order. If no courier is available for the specified delivery date, the program returns the "No courier is available for this delivery date: ..." error message, which is displayed by the app.

executeBeforeDelete

Description:

Before a record is deleted from the database, this function allows to perform other database operations.

Function header:

function m13e_executeBeforeDelete($connection, $table, $keyColumnName, $oldObject)

Function parameters:

Parameter Description
$connection The database connection. (Legacy mysql interface: the link identifier; mysqli interface: the mysqli object; pgsql interface: the PgSql\Connection object)
$table The name of the database table.
$keyColumnName The name of the table’s key column.
$oldObject The object or record loaded by the server from the database before deleting it.
This parameter contains the record’s previous state.

Return value:

null or true, if no error occurs (in this case the subsequent DELETE will run), or the text of the error message as a string (the subsequent DELETE cannot run).

Example #1:

<functions>
    <executeBeforeDelete>
	<![CDATA[
            $r = true;
            if(isset($oldObject["shipping_date"]))
            {
              $r = "This order has already been shipped. " . 
                   "You cannot delete this order.";
            }
            return $r;
	]]>
    </executeBeforeDelete>
</functions>
In this example, the generated app, which stores orders, checks the order before deleting it. If the shipping date (shipping_date) is not null the function returns the "This order has already been shipped. You cannot delete this order." error message, which is displayed by the app.

Example #2:

<functions>
    <executeBeforeDelete>
	<![CDATA[
            $r = true;
            $sql = "SELECT * FROM `orderitems` WHERE `order_id` = " . 
                   intval($oldObject["id"])." LIMIT 1";
            $result = $connection->query($sql);
            if($result!==false)
            {
              if($itemROW = $result -> fetch_assoc())
              {
                $r = "You cannot delete this order. ". 
                     "You must delete the order items first.";
              }
            }
            else
            {
              $r = $connection->error;
            }
            return $r;
	]]>
    </executeBeforeDelete>
</functions>
In this example, the generated app (which stores orders) checks whether the order has items or not before executing the delete. If the order has items, the program returns the "You cannot delete this order. You must delete the order items first." error message, which is displayed by the app.

executeAfterInsert

Description:

After a new record is inserted (saved) to the database, this function allows to perform other database operations.

Function header:

function m13e_executeAfterInsert($connection, $table, $keyColumnName, $newObject)

Function parameters:

Parameter Description
$connection The database connection. (Legacy mysql interface: the link identifier; mysqli interface: the mysqli object; pgsql interface: the PgSql\Connection object)
$table The name of the database table.
$keyColumnName The name of the table’s key column.
$newObject An object (or record) already stored in the database by the server.
This parameter contains the new, already saved state of the record, reloaded from the database by the server before the function call, so it reflects other changes as well (e.g. at saving, a trigger modified some fields of the record).

Return value:

null or true, if no error occurs, or the text of the error message as a string.

Example #1:

<functions>
    <executeAfterInsert>
	<![CDATA[
            $r = true;
            $sql = "UPDATE `customers` " . 
                   "SET `num_of_orders` = `num_of_orders` + 1 " . 
                   "WHERE `cust_id` = " . intval($newObject["order_id"]);
            $result = $connection->query($sql);
            if($result===false)
            {
                $r = $connection->error;
            }
            return $r;
	]]>
    </executeAfterInsert>
</functions>
In this example, the generated app, which stores orders, increases the number of orders (num_of_orders) of a customer after a new order has been recorded in the system. If there is an error during the execution of the SQL statement the program returns it, and it is displayed by the app.

executeAfterUpdate

Description:

After a record is updated (changed) in the database, this function allows to perform other database operations.

Function header:

function m13e_executeAfterUpdate($connection, $table, $keyColumnName, $oldObject, $newObject)

Function parameters:

Parameter Description
$connection The database connection. (Legacy mysql interface: the link identifier; mysqli interface: the mysqli object; pgsql interface: the PgSql\Connection object)
$table The name of the database table.
$keyColumnName The name of the table’s key column.
$oldObject The object or record loaded by the server from the database before it is changed.
This parameter contains the record’s previous, unmodified state.
$newObject An object (or record) already stored in the database by the server.
This parameter contains the new, already saved state of the record, reloaded from the database by the server before the function call, so it reflects other changes as well (e.g. at saving, a trigger modified some fields of the record).

Return value:

null or true, if no error occurs, or the text of the error message as a string.

Example #1:

<functions>
    <executeAfterUpdate>
	<![CDATA[
            $r = true;
            if(!isset($oldObject["delivery_date"]) && 
               isset($newObject["delivery_date"]))
            {
              $sql = "SELECT * FROM `couriers` WHERE `id` = " . 
                     intval($newObject["courier_id"]);
              $result = $connection->query($sql);
              if($result!==false)
              {
                $sql = "INSERT INTO `deliveries` " . 
                       "(`courier_id`, `order_id`, `delivery_date`) VALUES (".
                       intval($newObject["courier_id"]).", ".
                       intval($newObject["order_id"]).", ".
                       "'" . 
                       mysqli_real_escape_string($connection, 
                                                 $newObject["delivery_date"])."')".
                $result = $connection->query($sql);
                if($result!==false)
                {
                  sendEmailToCourier($courierROW["email_address"], 
                                     "You have a new delivery (order ID: " . 
                                        $newObject["order_id"].")", 
                                     "Dear Courier, ...");
                }
                else
                {
                  $r = $connection->error;
                }
              }
              else
              {
                $r = $connection->error;
              }
            }
            return $r;
	]]>
    </executeAfterUpdate>
</functions>
In this example, the generated app, which stores orders, inserts a record into the deliveries table and sends an email to the courier (courier_id) of the order after the delivery date (delivery_date) has been set. The program reads the email address of the courier from the database before sending the email. If there is an error during the execution of the SQL statements the program returns it, and it is displayed by the app.

executeAfterDelete

Description:

After a record is deleted from the database, this function allows to perform other database operations.

Function header:

function m13e_executeAfterDelete($connection, $table, $keyColumnName, $oldObject)

Function parameters:

Parameter Description
$connection The database connection. (Legacy mysql interface: the link identifier; mysqli interface: the mysqli object; pgsql interface: the PgSql\Connection object)
$table The name of the database table.
$keyColumnName The name of the table’s key column.
$oldObject The object or record loaded by the server from the database before deleting it.
This parameter contains the record’s previous state.

Return value:

null or true, if no error occurs, or the text of the error message as a string.

Example #1:

<functions>
    <executeAfterDelete>
	<![CDATA[
            $r = true;
            $sql = "UPDATE `customers` " . 
                   "SET `num_of_orders` = `num_of_orders` - 1 " . 
                   "WHERE `cust_id` = ".intval($newObject["order_id"]);
            $result = $connection->query($sql);
            if($result===false)
            {
              $r = $connection->error;
            }
            return $r;
	]]>
    </executeAfterDelete>
</functions>
In this example, the generated app, which stores orders, decreases the number of orders (num_of_orders) of a customer after an order has been deleted in the system. If there is an error during the execution of the SQL statement the program returns it, and it is displayed by the app.

getSelectWhereClause

Description:

This function allows you to set the WHERE condition of the SELECT and SELECT_SINGLE operations’ SQL SELECT statement.(Additional filtering conditions can be defined.)
WARNING! The full return value is appended to the SQL statement. Be careful handling the values returned in http parameters, to avoid creating vulnerabilities!

Function header:

function m13e_getSelectWhereClause($connection, $table)

Function parameters:

Parameter Description
$connection The database connection. (Legacy mysql interface: the link identifier; mysqli interface: the mysqli object; pgsql interface: the PgSql\Connection object)
$table The name of the database table.

Return value:

null or WHERE condition as a string, appended to the SQL SELECT statement.

Example #1:

<functions>
    <getSelectWhereClause>
	<![CDATA[
            return "`recorder_user_id` = ".intval($_SESSION['userid']);
	]]>
    </getSelectWhereClause>
</functions>
In this example, the generated app, which stores orders, filters the orders. The current user can only see the orders, which is recorded by him.

Example #2:

<functions>
    <getSelectWhereClause>
	<![CDATA[
            $roleSQL = "SELECT * FROM `system_roles` " . 
                       "WHERE `user_id` = " . intval($_SESSION["userid"]) . 
                       " AND `role_id` = (SELECT `id` FROM `roles` " . 
                       "WHERE `role_name` = 'order-manager')";
            $result = $connection->query($roleSQL);
            $r = null;
            if($result->num_rows == 0)
            {
                $r = "1 = 2";
            }
            return $r;
	]]>
    </getSelectWhereClause>
</functions>
In this example, the generated app, which stores orders, filters the orders. The current user can only see the orders if he has the order manager (order-manager) role. (If he is not an order manager the function returns the "1=2" where clause which is never true, so nothing is selected.)

getDisabledActions

Description:

This function allows you to forbid users to perform certain actions againts a specified table. These features will not be available for the user in the generated application. (Naturally, the user cannot use these actions in the server side program, either.)

Function header:

function m13e_getDisabledActions($connection, $table)

Function parameters:

Parameter Description
$connection The database connection. (Legacy mysql interface: the link identifier; mysqli interface: the mysqli object; pgsql interface: the PgSql\Connection object)
$table The name of the database table.

Return value:

null or an array of disabled action constants (e.g. return array("INSERT", "DELETE")).
Actions you can disable: INSERT, UPDATE, DELETE, EXPORT.

Example #1:

<functions>
    <getDisabledActions>
	<![CDATA[
            return array("INSERT", "UPDATE", "DELETE");
	]]>
    </getDisabledActions>
</functions>
In this example, the generated app disables the insert, update, delete buttons. The current user cannot modify the data.

Example #2:

<functions>
    <getDisabledActions>
	<![CDATA[
            return array("DELETE");
	]]>
    </getDisabledActions>
</functions>
In this example, the generated app disables the delete button. The current user cannot delete any records.

Example #3:

<functions>
    <getDisabledActions>
	<![CDATA[
            $roleSQL = "SELECT * FROM `system_roles` ". 
                       "WHERE `user_id` = " . intval($_SESSION["userid"]) . 
                       " AND `role_id` = (SELECT `id` FROM `roles` " . 
                       "WHERE `role_name` = 'order-manager')";
            $result = $connection->query($roleSQL);
            $r = null;
            if($result->num_rows == 0)
            {
                $r = array("INSERT", "UPDATE", "DELETE");
            }
            return $r;
	]]>
    </getDisabledActions>
</functions>
In this example, the generated app disables the insert, update, delete buttons if the current user is not an order manager.

executeBeforeFileUpload

Description:

Before a new file is saved to the file system, this function allows to perform database or other operations.

Function header:

function m13e_executeBeforeFileUpload($connection, $table, $keyColumnName, $parentObject, $fileFolder, $fileControlName, $originalFileName, $sanitizedFileName)

Function parameters:

Parameter Description
$connection The database connection. (Legacy mysql interface: the link identifier; mysqli interface: the mysqli object; pgsql interface: the PgSql\Connection object)
$table The name of the database table.
$keyColumnName The name of the table’s key column.
$parentObject The parent object (record) loaded by the server (the parent of the files).
$fileFolder The folder which will contain the uploaded file.
$fileControlName The name of the file control.
$originalFileName The name of the uploaded file before it has been sanitized.
$sanitizedFileName The sanitized name of the uploaded file.

Return value:

null or true, if no error occurs (in this case the file is going to be saved), or the text of the error message as a string (the file won't be saved).

Example #1:

<functions>
    <executeBeforeFileUpload>
	<![CDATA[
            $r = true;
            if(file_exists($fileFolder . DIRECTORY_SEPARATOR . $sanitizedFileName))
            {
              $r = "There is already a file with this name in this folder, " .
                   "and you cannot overwrite it. Your save is aborted!";
            }
            return $r;
	]]>
    </executeBeforeFileUpload>
</functions>
In this example, the generated app checks whether a file with this name exists in this folder before it is saved. If it exists, the save is aborted, and the user gets an error message.

executeBeforeFileDelete

Description:

Before a file is deleted from the file system, this function allows to perform database or other operations.

Function header:

function m13e_executeBeforeFileDelete($connection, $table, $keyColumnName, $parentObject, $fileFolder, $fileControlName, $deletedFileName)

Function parameters:

Parameter Description
$connection The database connection. (Legacy mysql interface: the link identifier; mysqli interface: the mysqli object; pgsql interface: the PgSql\Connection object)
$table The name of the database table.
$keyColumnName The name of the table’s key column.
$parentObject The parent object (record) loaded by the server (the parent of the files). The file has not been deleted yet.
$fileFolder The folder which contains the file which will be deleted.
$fileControlName The name of the file control.
$deletedFileName The name of the file which will be deleted.

Return value:

null or true, if no error occurs (in this case the file is going to be delete), or the text of the error message as a string (the file won't be deleted).

Example #1:

<functions>
    <executeBeforeFileDelete>
	<![CDATA[
	          $r = true;
            if(strpos($deletedFileName, ".pdf")!==false && 
               pdf_is_signed($fileFolder . DIRECTORY_SEPARATOR . $sanitizedFileName))
            {
              $r = "Signed PDF files cannot be deleted!";
            }
            return $r;
	]]>
    </executeBeforeFileDelete>
</functions>
In this example, the generated app checks whether a file with this name is a signed PDF file before it is deleted. If it is, the delete is aborted, and the user gets an error message.

executeAfterFileUpload

Description:

After a file is uploaded and saved to the file system, this function allows to perform database or other operations.

Function header:

function m13e_executeAfterFileUpload($connection, $table, $keyColumnName, $parentObject, $fileFolder, $fileControlName, $originalFileName, $sanitizedFileName)

Function parameters:

Parameter Description
$connection The database connection. (Legacy mysql interface: the link identifier; mysqli interface: the mysqli object; pgsql interface: the PgSql\Connection object)
$table The name of the database table.
$keyColumnName The name of the table’s key column.
$parentObject The parent object (record) loaded by the server (the parent of the files).
$fileFolder The folder which contains the uploaded file.
$fileControlName The name of the file control.
$originalFileName The name of the uploaded file before it has been sanitized.
$sanitizedFileName The sanitized name of the uploaded file.

Return value:

null or true, if no error occurs, or the text of the error message as a string.

Example #1:

<functions>
    <executeAfterFileUpload>
	<![CDATA[
            $r = true;
            $insertSQL = "INSERT INTO files " .
                         "(folder_name, original_file_name, file_name) " . 
                         "VALUES " .
                         "('" . $connection->real_escape_string($fileFolder) . "', '" . 
                         $connection->real_escape_string($originalFileName) . "', '" . 
                         $connection->real_escape_string($sanitizedFileName) . "')";  
            if($connection->query($insertSQL)===false)
            {
                $r = "Unable to insert a record in the files table! - " . 
                      $connection->error;
            }
            return $r;
	]]>
    </executeAfterFileUpload>
</functions>
In this example, the generated app, after it saves the uploaded file, it inserts a record in the files table. This table is used to store the original name of the file, but it could store the text content of the file (after it has been extracted with Apache Tika, for example), but it is not implemented in this example.

executeAfterFileDelete

Description:

After a file is deleted from the file system, this function allows to perform database or other operations.

Function header:

function m13e_executeAfterFileDelete($connection, $table, $keyColumnName, $parentObject, $fileFolder, $fileControlName, $deletedFileName)

Function parameters:

Parameter Description
$connection The database connection. (Legacy mysql interface: the link identifier; mysqli interface: the mysqli object; pgsql interface: the PgSql\Connection object)
$table The name of the database table.
$keyColumnName The name of the table’s key column.
$parentObject The parent object (record) loaded by the server (the parent of the files). The file has already been deleted.
$fileFolder The folder which has contained the deleted file.
$fileControlName The name of the file control.
$deletedFileName The name of the file which has been deleted.

Return value:

null or true, if no error occurs, or the text of the error message as a string.

Example #1:

<functions>
    <executeAfterFileDelete>
	<![CDATA[
            $r = true;
            $deleteSQL = "DELETE FROM files WHERE folder_name = '" . 
                         $connection->real_escape_string($fileFolder) . 
                         "' AND file_name = '" . 
                         $connection->real_escape_string($deletedFileName) . "'";  
            if($connection->query($deleteSQL)===false)
            {
                $r = "Unable to delete a record in the files table! - " . 
                     $connection->error;
            }
            return $r;
	]]>
    </executeAfterFileDelete>
</functions>
In this example, the generated app, after it deletes a file, it deletes a record from the files table.

jsFunctions

Description:

M13E allows you to extend or modify the behaviour of the generated application at the client side (JavaScript), too. You have to implement functions for the new features or modifications. A jsFunctions element contains the code of these JavaScript functions. The functions are listed as individual XML elements under jsFunctions.
The following XML elements all contain the body or code of one such function. Use <![CDATA[…]]> if you don’t want to escape XML entities.

Example #1:

<onApplicationStart>
	<![CDATA[
		alert("This is the new version of our application. The old version has been removed.");
	]]>
</onApplicationStart>
In this example, the generated app alerts the user that the old version of the application is replaced by a new version, and the old version is not available anymore.

We provide the function header (signature) in the description, too. (The name of the functions are prefixed with m13e_ in the generated code.)
At the moment you can extend or modify your application with the following functions:

onApplicationStart

Description:

After the JavaScript application started, this function allows to perform other operations.

Function header:

function m13e_onApplicationStart()

Function parameters:

This function does not have any parameters.

Return value:

This function does not return anything.

Example #1:

<jsFunctions>
    <onApplicationStart>
      <![CDATA[
          alert("This is the new version of our application. The old version has been removed.");
      ]]>
    </onApplicationStart>
</jsFunctions>
In this example, the application informs the user with an alert.

onBeforeHttpRequest

Description:

The application sends more than one HTTP request to the server and as a developer you can modify the HTTP request (you can set/add parameters and headers) before it is sent.

Function header:

function m13e_onBeforeHttpRequest(httpRequest, context)

Function parameters:

Parameter Description
httpRequest A HTTP request, which will be sent to the server. It is an instance of org.haxentric.http.AsynchronousHttpRequest. You can set/add parameters and headers with the following methods: (setParameter(param:String, value:String), addParameter(param:String, value:String), setHeader(header:String, value:String), addHeader(header:String, value:String).
context The application sends more than one HTTP request, so the m13e_onBeforeHttpRequest function is executed several times. In order to distingish these calls the context parameter contains a string to help the developer which HTTP request will be executed in the next step.
Possible values: GET_DISABLED_ACTIONS, SELECT, SELECT_SINGLE, INSERT, UPDATE, DELETE or the name value of any options element.
GET_DISABLED_ACTIONS: After the application downloaded all of the options from the server, the application requests the disabled actions from the server. For more information: getDisabledActions
SELECT: After the application downloaded all of the options from the server and disabled actions, the application requests the records from the server. You can add extra parameters to the request parameters and you can use them at server side in the getSelectWhereClause PHP function. For more information: getSelectWhereClause
SELECT_SINGLE: If the recordRefreshedOnOpen attribute of definition is set to true, the application requests the selected record from the server to refresh it.
INSERT: This request is sent to the server when the user tries to insert a new record. You can add extra parameters to the request parameters and you can use them at server side in the executeBeforeInsert and in the executeAfterInsert PHP function. For more information: executeBeforeInsert and executeAfterInsert
UPDATE: This request is sent to the server when the user tries to update the selected record. You can add extra parameters to the request parameters and you can use them at server side in the executeBeforeUpdate and in the executeAfterUpdate PHP function. For more information: executeBeforeUpdate and executeAfterUpdate
DELETE: This request is sent to the server when the user tries to delete the selected record. You can add extra parameters to the request parameters and you can use them at server side in the executeBeforeDelete and in the executeAfterDelete PHP function. For more information: executeBeforeDelete and executeAfterDelete
name of an options element: This request is sent to the server when the application requests the records of an options element. You can add extra parameters to the request parameters and you can use them at server side in the getSelectWhereClause PHP function of the M13E application of the options. For more information: getSelectWhereClause and options

Return value:

This function does not return anything.

Example #1:

<jsFunctions>
    <onBeforeHttpRequest>
      <![CDATA[
        if(context=="roles")
        {
          httpRequest.addParameter("type_filter", "task");
        }
      ]]>
    </onBeforeHttpRequest>
</jsFunctions>
This application is used for maintain task roles. There is another application for projects, too. Both applications use roles stored in the roles table (role records are maintained with the roles M13E application). This application uses the roles M13E application as options data provider (sourceURL). But we do not want to display all roles in a comboBox but only task related roles. We must filter them. We set the type_filter parameter to task and we can use it at server side in the getSelectWhereClause PHP function of the roles M13E application. (We can set this parameter in the sourceURL attribute of the options element, too.)

onAfterTabChange

Description:

After the user clicked on a tab and the program changed to that tab, this function allows to perform other operations.
If you like to know which tab is the current selected one, you have to use the selectedIndex property of the ButtonBar (this.get_m13e_buttonBar().get_selectedIndex()).

Function header:

function m13e_onAfterTabChange()

Function parameters:

This function does not have any parameters.

Return value:

This function does not return anything.

Example #1:

<jsFunctions>
    <onAfterTabChange>
      <![CDATA[
          this.c_organization_city.set_enabled(this.c_organization.get_selected());
          this.c_organization_address.set_enabled(this.c_organization.get_selected());
          this.c_organization_zip_code.set_enabled(this.c_organization.get_selected());
          this.c_organization_country.set_enabled(this.c_organization.get_selected());
      ]]>
    </onAfterTabChange>
</jsFunctions>
When the user changes to Address tab, the address fields (c_organization_*) of an organization are enabled if the Organization checkbox (c_organization) is checked.

onMessage

Description:

M13E applications send messages to other M13E applications. This function allows to perform other operations when a message was received.
The following table summarizes the messages sent by the M13E applications:
Direction Content Description
From child to parent {action: "OPEN"}

When you use oneToMany or manyToMany layout for a child application, the child application sends a message to the parent application after the child application starts.

From child to parent {action: "CLOSE"}

When you use oneToMany or manyToMany layout for a child application, the child application sends a message to the parent application after the child application stops.

From parent to child {
  parentRecord: <parent_record>,
  action: "SELECT",
  tableName: "<parent_table_name>"
}

When a record is selected by the user in the dataGrid, the parent application sends a message to the child application(s). The message contains the selected parent record and the name of the database table, in which the parent record is stored.

<parent_record> is a real JS object and <parent_table_name> is a name of a database table, e.g. customers if the parent application is generated for the customers table.

From parent to child {
  parentRecord: null,
  action: "DESELECT",
  tableName: "<parent_table_name>"
}

When a record is deselected by the user (the user deselects a record or selects an other record) in the dataGrid, the parent application sends a message to the child application(s). The message does not contain the deselected parent record, it is set to null. The message contains the name of the database table, in which the parent record is stored.

<parent_record> is null and <parent_table_name> is a name of a database table, e.g. customers if the parent application is generated for the customers table.

From parent to child {
  parentRecord: null,
  action: "NEW",
  tableName: "<parent_table_name>"
}

When the user presses the New button to create a new record in the parent application, the parent application sends a message to the child application(s). The message does not contain the a parent record (it is not stored yet and empty), it is set to null. The message contains the name of the database table, in which the new parent record will be stored.

<parent_record> is null and <parent_table_name> is a name of a database table, e.g. customers if the parent application is generated for the customers table.

From parent to child {
  parentRecord: <parent_record>,
  action: "DELETE",
  tableName: "<parent_table_name>"
}

When the user deletes a record in the parent application, the parent application sends a message to the child application(s). The message contains the deleted parent record and the name of the database table, in which the deleted parent record was stored.

<parent_record> is a real JS object and <parent_table_name> is a name of a database table, e.g. customers if the parent application is generated for the customers table.

From child to parent {
  childRecord: <child_record>,
  action: "DELETE",
  tableName: "<child_table_name>"
}

When the user deletes a record in the child application, the child application sends a message to the parent application. The message contains the deleted child record and the name of the database table, in which the deleted child record was stored.

<child_record> is a real JS object and <child_table_name> is a name of a database table, e.g. orders if the child application is generated for the orders table.

From parent to child {
  parentRecord: <parent_record>,
  action: "INSERT",
  tableName: "<parent_table_name>"
}

When the user inserts a new record in the parent application (a new record has been saved), the parent application sends a message to the child application(s). The message contains the new parent record and the name of the database table, in which the new parent record was stored.

<parent_record> is a real JS object and <parent_table_name> is a name of a database table, e.g. customers if the parent application is generated for the customers table.

From child to parent {
  childRecord: <child_record>,
  action: "INSERT",
  tableName: "<child_table_name>"
}

When the user inserts a new record in the child application, the child application sends a message to the parent application. The message contains the new child record and the name of the database table, in which the new child record was stored.

<child_record> is a real JS object and <child_table_name> is a name of a database table, e.g. orders if the child application is generated for the orders table.

From parent to child {
  parentRecord: <parent_record>,
  action: "UPDATE",
  tableName: "<parent_table_name>"
}

When the user modifies a record in the parent application (the record has been modified and saved), the parent application sends a message to the child application(s). The message contains the modified parent record and the name of the database table, in which the modified parent record was stored.

<parent_record> is a real JS object and <parent_table_name> is a name of a database table, e.g. customers if the parent application is generated for the customers table.

From child to parent {
  childRecord: <child_record>,
  action: "UPDATE",
  tableName: "<child_table_name>"
}

When the user modifies a record in the child application (the record has been modified and saved), the child application sends a message to the parent application. The message contains the modified child record and the name of the database table, in which the modified child record was stored.

<child_record> is a real JS object and <child_table_name> is a name of a database table, e.g. orders if the child application is generated for the orders table.

Function header:

function m13e_onMessage(message)

Function parameters:

Parameter Description
message The message object posted by the child or parent application. For more information check the previous table which summarizes the messages sent by the M13E applications.

Return value:

This function does not return anything.

Example #1:

<jsFunctions>
    <onMessage>
      <![CDATA[
          if(message.action == "INSERT" || 
             message.action == "UPDATE" ||
             message.action == "DELETE")
          {
            calculateTotalSpentTimes();
          }
      ]]>
    </onMessage>
</jsFunctions>
This time tracker program recalculates the total spent time of a task when a spent time is inserted/updated/deleted for that task. There is a one-to-many relationship between task records and spent time records. Task records are maintained in the parent applications and spent time records are maintained in a child application. This example (onMessage) is implemented in the parent application.

onOptionsLoad

Description:

This function allows to perform other operations when options are loaded from the server. options data are loaded sequentially.

Function header:

function m13e_onOptionsLoad(optionsName)

Function parameters:

Parameter Description
optionsName The name attribute of an options element.

Return value:

This function does not return anything.

Example #1:

<jsFunctions>
    <onOptionsLoad>
      <![CDATA[
          if(optionsName=="products")
          {
            if(!this.m_products.iterator().hasNext())
            {
              alert("You should maintain your products before recording an order!");
            }
          }
      ]]>
    </onOptionsLoad>
</jsFunctions>
This application is created for maintaining orders and uses the products master data as options. This code warns the user if the user has not recorded any products yet.

onRecordsLoad

Description:

This function allows to perform other operations when the records are loaded from the server and displayed in the dataGrid.

Function header:

function m13e_onRecordsLoad()

Function parameters:

This function does not have any parameters.

Return value:

This function does not return anything.

Example #1:

<jsFunctions>
    <onRecordsLoad>
      <![CDATA[
          var len = this.get_m13e_records().get_length();
          var count = 0;
          var nowInMillis = new Date().getTime();
          var weekInMillis = 1000 * 60 * 60 * 24 * 7;
          for(var i=0; i<len; i++)
          {
            var user = this.get_m13e_records().getItemAt(i);
            var d = Date.parse(user.registration_date);
            if(nowInMillis - d.getTime() <= weekInMillis)
            {
              count++;
            }
          }
          if(count>0)
          {
            alert("You have " + String(count) + " new registered user(s) in the last 7 days.");
          }
      ]]>
    </onRecordsLoad>
</jsFunctions>
This example warns the administrator about the new registered users in the last 7 days when the user records are loaded.

onRecordsRefresh

Description:

This function allows to perform other operations when the records are refreshed from the server and displayed in the dataGrid. You can use it with popup layout only.

Function header:

function m13e_onRecordsRefresh()

Function parameters:

This function does not have any parameters.

Return value:

This function does not return anything.

Example #1:

<jsFunctions>
    <onRecordsRefresh>
      <![CDATA[
          if(window.previousRecordCount == undefined)
          {
            window.previousRecordCount = this.get_m13e_records().get_length();
          }
          else
          {
            if(this.get_m13e_records().get_length() > window.previousRecordCount)
            {
              alert("You have " + String(this.get_m13e_records().get_length() - window.previousRecordCount) + " new registered user(s).");
            }
          }
      ]]>
    </onRecordsRefresh>
</jsFunctions>
This example warns the administrator about the new registered users when the user records are refreshed.

onBeforeSave

Description:

This function allows to perform other operations before a record is saved. This function can abort the save operation by returning a false value.
You can perform complex validations here.

Function header:

function m13e_onBeforeSave()

Function parameters:

This function does not have any parameters.

Return value:

true, if the operation can continue (in this case the save is executed), or false, if the operation cannot continue (in this case the save is aborted).

Example #1:

<jsFunctions>
    <onBeforeSave>
      <![CDATA[
          // At this point all controls are validated with their validators.
          // We check the relation of two fields here.
          // Date values are in ISO format.
          var startTimeInMillis = Date.parse(this.c_start_time.get_text()).getTime();
          var endTimeInMillis = Date.parse(this.c_end_time.get_text()).getTime();
          var r = true;
          if(startTimeInMillis >= endTimeInMillis)
          {
            r = false;
            alert("Start time must be earlier than End time!");
          }
          return r;
      ]]>
    </onBeforeSave>
</jsFunctions>
In this example, we have two DateFields, c_start_time and c_end_time. Start time must be earlier than end time. If it is not earlier, the program alerts and returns a false value to abort the save operation.

onAfterSave

Description:

This function allows to perform other operations after a record is saved.

Function header:

function m13e_onAfterSave()

Function parameters:

This function does not have any parameters.

Return value:

This function does not return anything.

Example #1:

<jsFunctions>
    <onAfterSave>
      <![CDATA[
          alert("Your HTML template has been saved. Don't forget to upload your image files.");
      ]]>
    </onAfterSave>
</jsFunctions>
The application alerts the user to upload image files after the HTML template is saved.

onBeforeDelete

Description:

This function allows to perform other operations before a record is deleted.

Function header:

function m13e_onBeforeDelete()

Function parameters:

This function does not have any parameters.

Return value:

true, if the operation can continue (in this case the delete is executed), or false, if the operation cannot continue (in this case the delete is aborted).

Example #1:

<jsFunctions>
    <onBeforeDelete>
      <![CDATA[
        // If a document is archived, it cannot be deleted.
        var r = true;
        if(this.get_m13e_selectedRecord().is_archived == "T")
        {
          r = false;
          alert("You cannot delete an archived document!");
        }
        return r;
      ]]>
    </onBeforeDelete>
</jsFunctions>
In this example, the application stores documents. Archived document cannot be deleted. Before executing delete the application checks if it is an archived document. If so, it alerts the user that the document cannot be deleted, and returns false. Otherwise it returns true.

onAfterDelete

Description:

This function allows to perform other operations after a record is deleted.

Function header:

function m13e_onAfterDelete()
This function does not have any parameters.

Return value:

This function does not return anything.

Example #1:

<jsFunctions>
    <onAfterDelete>
      <![CDATA[
          if(confirm("Do you also want to delete image files that are no longer used?"))
          {
            deleteUnusedImageFiles();
          }
      ]]>
    </onAfterDelete>
</jsFunctions>
In this example, the applications stores HTML templates. Templates use images. After a template is deleted the application deletes unused image files if the user confirms it.

onBeforeNew

Description:

This function allows to perform other operations after the New button is pressed but before a new and unsaved record is created and the form is initialized.

Function header:

function m13e_onBeforeNew()

Function parameters:

This function does not have any parameters.

Return value:

true, if the operation can continue (in this case new record is created and the form is initialized), or false, if the operation cannot continue (in this case no new record is created and the form is not initialized (remains unchanged)).

Example #1:

<jsFunctions>
    <onBeforeNew>
      <![CDATA[
      // If the record is unsaved, user must confirm creating a new one.
      var r = true;
      if(this.get_m13e_selectedRecord().id == null)
      {
        if(!confirm("You have an unsaved record. Do you really want to continue?"))
        {
          r = false;
        }
      }
      return r;
      ]]>
    </onBeforeNew>
</jsFunctions>
The user created a new record but did not save it. Then the user pressed the New button. The application warns the user that she/he has an unsaved new record. The application will continue if the user confirms it.

onAfterNew

Description:

This function allows to perform other operations after the New button is pressed and a new and unsaved record is created and the form is initialized.

Function header:

function m13e_onAfterNew()

Function parameters:

This function does not have any parameters.

Return value:

This function does not return anything.

Example #1:

<jsFunctions>
    <onAfterNew>
      <![CDATA[
          var now = new Date().toISOString();
          // 012345678901234567890123
          // YYYY-MM-DDThh:mm:ss.xxxZ
          now = now.substring(0, 10) + " " + now.substring(11, 19);
          this.c_start_time.set_text(now);
          this.c_end_time.set_text(now);
      ]]>
    </onAfterNew>
</jsFunctions>
After a new record is created the application sets the start time and end time controls to the current time.

onBeforeCancel

Description:

This function allows to perform other operations after the Cancel button is pressed but before the modifications are cancelled.

Function header:

function m13e_onBeforeCancel()

Function parameters:

This function does not have any parameters.

Return value:

true, if the operation can continue (in this case the modifications will be cancelled), or false, if the operation cannot continue (in this case the modifications will not be cancelled).

Example #1:

<jsFunctions>
    <onBeforeCancel>
      <![CDATA[
          var r = true;
          if(!confirm("You have unsave modifications. Do you really want to continue?"))
          {
            r = false;
          }
          return r;
      ]]>
    </onBeforeCancel>
</jsFunctions>
In this example, the user pressed the Cancel button. The application warns the user that she/he has unsaved modifications. The application will continue if the user confirms it.

onAfterCancel

Description:

This function allows to perform other operations after the Cancel button is pressed and the modifications are cancelled.

Function header:

function m13e_onAfterCancel()

Function parameters:

This function does not have any parameters.

Return value:

This function does not return anything.

Example #1:

<jsFunctions>
    <onAfterCancel>
      <![CDATA[
      if(this.get_m13e_selectedRecord().id != null)
      {
        alert("Your record has been restored.")
      }
      ]]>
    </onAfterCancel>
</jsFunctions>
After the user presses the Cancel button and the modifications are cancelled, the application warns the user that the current record has been restored.

onBeforeExport

Description:

This function allows to perform other operations after the Export button is pressed but before the data are exported.
This is the last chance to modify the exported data. (You can add new fields and new records, too.)

Function header:

function m13e_onBeforeExport(exportedData, exportedDataTypes, exportedFieldLabels)

Function parameters:

Parameter Description
exportedData This is an Array of indexed Arrays (the records are NOT ASSOCIATIVE arrays). It contains all records (including transient fields), which will be exported.
exportedDataTypes This is an indexed Array. It contains the data types of the fields.
exportedFieldLabels This is an indexed Array. It contains the labels of the fields.

Return value:

true, if the operation can continue (in this case the data will be exported), or false, if the operation cannot continue (in this case the export operation is aborted).

Example #1:

<jsFunctions>
    <onBeforeExport>
      <![CDATA[
          var len = exportedData.length;
          for(var i = 0; i < len; i++)
          {
            var row = exportedData[i];
            row[11] = null;
          }
          return true;
      ]]>
    </onBeforeExport>
</jsFunctions>
In this example, the name of the user is stored as the 11th item of the array. It is set to null in the exportedData.

onAfterExport

Description:

This function allows to perform other operations after the Export button is pressed and the exported data is saved on the user's computer.

Function header:

function m13e_onAfterExport()

Function parameters:

This function does not have any parameters.

Return value:

This function does not return anything.

Example #1:

<jsFunctions>
    <onAfterExport>
      <![CDATA[
          alert("The data has been exported and downloaded to your computer. You can find the exported data in your file system, e.g. in the Downloads folder.");
      ]]>
    </onAfterExport>
</jsFunctions>
In this example, the application warns the user that the exported data is downloaded to the user's computer, and it can be found in the Downloads folder.

onSelectedRecordChange

Description:

This function allows to perform other operations when the selected record is changed. (When the user selects a record in the data grid or unselects a record.)
To get the selected record use the following code:
this.get_m13e_selectedRecord()

Function header:

function m13e_onSelectedRecordChange()

Function parameters:

This function does not have any parameters.

Return value:

This function does not return anything.

Example #1:

<jsFunctions>
    <onSelectedRecordChange>
      <![CDATA[
      if(this.get_m13e_selectedRecord()!=null)
      {
        var organization = this.get_m13e_selectedRecord().is_organization == "T";
        this.c_org_city.set_enabled(organization);
        this.c_org_address.set_enabled(organization);
        this.c_org_zip.set_enabled(organization);
      }
      ]]>
    </onSelectedRecordChange>
</jsFunctions>
In this example, the program enables or disables several controls related to organizations depending on whether the record stores organization data or not.

onBeforeConstruction

Description:

This function allows to perform other operations before the components of the application are created and initialized. You can declare custom variables or functions or create custom components here.

Function header:

function m13e_onBeforeConstruction()

Function parameters:

This function does not have any parameters.

Return value:

This function does not return anything.

Example #1:

<jsFunctions>
    <onBeforeConstruction>
      <![CDATA[
      window.previousRecordCount = 0;
      window.logToConsole = function(msg) {
        console.log(msg);
      }
      ]]>
    </onBeforeConstruction>
</jsFunctions>
In this example, the program declares and initializes the previousRecordCount variable and declare a logToConsole function.

onAfterConstruction

Description:

This function allows to perform other operations after the components of the application are created and initialized. You can modify the attributes of the components here.

Function header:

function m13e_onAfterConstruction()

Function parameters:

This function does not have any parameters.

Return value:

This function does not return anything.

Example #1:

<jsFunctions>
    <onAfterConstruction>
      <![CDATA[
      this.c_task_id.setStyle("background-color", 0x0011ff);
      ]]>
    </onAfterConstruction>
</jsFunctions>
In this example, the program changes the background color of c_task_id (an input field).

onBeforeDetailWindowClose

Description:

This function allows to perform operations before the detail window is closed (you have to use oneToMany or manyToMany layout). Returning false aborts the closing.

Function header:

function m13e_onBeforeDetailWindowClose()

Function parameters:

This function does not have any parameters.

Return value:

true, if the operation can continue (in this case the window is closed), or false, if the operation cannot continue (in this case the window is not closed).

Example #1:

<jsFunctions>
    <onBeforeDetailWindowClose>
      <![CDATA[
          var r = true;
          if(this.c_task_id.get_text() == null || this.c_task_id.get_text()=='')
          {
            alert("You have a new and unsaved record.");
            r = false;
          }
          return r;
      ]]>
    </onBeforeDetailWindowClose>
</jsFunctions>
In this example, the program warns if you have a new and unsaved record. (c_task_id is empty if it is a new and unsaved record.)

onAfterDetailWindowClose

Description:

This function allows to perform operations after the detail window is closed (you have to use oneToMany or manyToMany layout).

Function header:

function m13e_onAfterDetailWindowClose()

Function parameters:

This function does not have any parameters.

Return value:

This function does not return anything.

onBeforeFileUpload

Description:

This function allows to perform other operations before a file is uploaded. This function can abort the upload operation by returning a false value.

Function header:

function m13e_onBeforeFileUpload()

Function parameters:

Parameter Description
controlName The value of the name attribute of a control element. (The value of the type attribute of this control must be files.)
fileName The name of the file. (E.g. manual.docx)
file The file object. For more information: https://developer.mozilla.org/en-US/docs/Web/API/File
fileApp The JavaScript file application. For more information: m13e_files.php

Return value:

true, if the operation can continue (in this case the file is uploaded), or false, if the operation cannot continue (in this case the upload is aborted).

Example #1:

<jsFunctions>
    <onBeforeFileUpload>
      <![CDATA[
          var r = true;
          if(!fileName.endsWith(".pdf"))
          {
            r = false;
            alert("Only PDF files can be uploaded!");
          }
          return r;
      ]]>
    </onBeforeFileUpload>
</jsFunctions>
In this example, the upload aborts if the user tries to upload a non-PDF file.

onAfterFileUpload

Description:

This function allows to perform other operations after a file is uploaded.

Function header:

function m13e_onAfterFileUpload()

Function parameters:

Parameter Description
controlName The value of the name attribute of a control element. (The value of the type attribute of this control must be files.)
fileName The sanitized name of the file. (E.g. manual.docx)
fileApp The JavaScript file application. For more information: m13e_files.php

Return value:

This function does not return anything.

Example #1:

<jsFunctions>
    <onAfterFileUpload>
      <![CDATA[
          alert("Your file has been uploaded and saved as " + fileName + ".");
      ]]>
    </onAfterFileUpload>
</jsFunctions>
The application alerts the user that his/her file has been uploaded and saved with the diplayed sanitized name.

onBeforeFileDelete

Description:

This function allows to perform other operations before a file is deleted.

Function header:

function m13e_onBeforeFileDelete()

Function parameters:

Parameter Description
controlName The value of the name attribute of a control element. (The value of the type attribute of this control must be files.)
fileName The name of the file. (E.g. manual.docx)
fileApp The JavaScript file application. For more information: m13e_files.php

Return value:

true, if the operation can continue (in this case the delete is executed), or false, if the operation cannot continue (in this case the delete is aborted).

Example #1:

<jsFunctions>
    <onBeforeFileDelete>
      <![CDATA[
        var r = true;
        if(fileName.endsWith(".pdf"))
        {
          r = false;
          alert("You cannot delete a PDF file!");
        }
        return r;
      ]]>
    </onBeforeFileDelete>
</jsFunctions>
In this example, the delete aborts if the user tries to delete a PDF file.

onAfterFileDelete

Description:

This function allows to perform other operations after a file is deleted.

Function header:

function m13e_onAfterFileDelete()
Parameter Description
controlName The value of the name attribute of a control element. (The value of the type attribute of this control must be files.)
fileName The name of the file. (E.g. manual.docx)
fileApp The JavaScript file application. For more information: m13e_files.php

Return value:

This function does not return anything.

Example #1:

<jsFunctions>
    <onAfterFileDelete>
      <![CDATA[
          alert("The file has been deleted. " + 
                "It has been moved to the recycle bin. " + 
                "You have 30 days to restore it. " + 
                "After that, it is permanently deleted.");
      ]]>
    </onAfterFileDelete>
</jsFunctions>
In this example, the application stores the deleted files in a recycle bin for 30 days. After a file is deleted, the application warns the user that he/she has 30 days to restore it.

options

Description:

Descriptor element of the possible values of radio and comboBox type input fields (options attribute), and the possible values required to resolve the foreign key values of dataGrid column (options attribute). options can contain one or more option elements, or possible values are downloaded from the address specified.
Options can be used as functions in the template expressions (see popupWindowTitle of definition and label of options) and in options filtering, too (see filter of options).
For example:
The city_id column only contains city IDs. The user, on the other hand, wants to select a value from a list containing the name of the cities. To solve the request, use comboBox with the options element.

Attributes:

Attribute Description
name Name of the value list (options), used by the program to identify value lists (options). Required!
value If values (JavaScript object with properties) are downloaded from a specified address, contains the name of the property, which contains the identifier values.
Default value: id
label If values (JavaScript object with properties) are downloaded from a specified address, contains the name of the property, which contains the name or the label (plain text representation of the value). You can use a template.
Default value: name
sourceURL If values are downloaded from a specified address, this attribute specifies the URL of the values.
Data maintenance app generated with M13E can be used as a source of options, but you must provide an action parameter with SELECT value in the URL. (E.g. cities.php?action=SELECT)
maintenanceURL If values are downloaded from a specified address, this attribute specifies location (URL) of the php file required to maintain the possible values.
It is relevant to the comboBox input field. When the user clicks the modify (edit) button in the dropdown list of the comboBox, a maintenance window pops up, similar to the current one, but with a different content.
Only data maintenance app generated with M13E can be used as a maintenance app for options (E.g. cities.php)
orderBy What the value list is ordered by. (List of columns, SELECT statement’s ORDER BY part.)
valueType Type of the value in the value field. Only use when possible values are listed with XML elements (option element).
Default value: string
Possible values: string, number, date, time, dateTime, boolean
filter A filtering condition.
Usable variables:
option: Contains the currently checked (whether it matches or not) element.
selectedRecord: Contains the record selected in the dataGrid.
refreshedAfterModification If options records are modified by the user through the dropdown list’s modify (edit) option, a true value means that options records are updated.
Possible values: true or false
Default value: false

Example #1:

...
<options name="countries" value="c_id" 
			label="c_name" 
			sourceURL="countries.php?action=SELECT" 
			maintenanceURL="countries.php"
			orderBy="c_name" 
			refreshedAfterModification="true"/>
<options name="cities" value="ci_id" 
			label="{ci_name}, {countries(c_id).c_name}" 
			sourceURL="cities.php?action=SELECT" 
			maintenanceURL="cities.php" 
			filter="option.c_id == selectedRecord.c_id"/>
...
<table name="customers">
	...
	<column name="c_id" 
		type="integer" 
		key="false" 
		nullable="true" 
		label="Country" 
		options="countries"/>
	<column name="ci_id"
		type="integer" 
		key="false" 
		nullable="true" 
		label="City" 
		options="cities"/>
	...
</table>
...
<control name="c_id" type="comboBox" width="300" />
<control name="ci_id" type="comboBox" width="300" />
...
In this example, we define two options elements, countries and cities in the data maintenance app for customers. These options are used in the column elements of the table. A comboBox control or a dataGrid column inherits the value of its options attribute from the table column element if its options attribute is not overriden (as in this case). The defined comboBox controls use these options as value lists. When the user selects a country in the first comboBox, the cities are filtered in the second comboBox (only cities in the same country are displayed in the list).

option

Description:

Descriptor element of the list value hardcoded into the definition file.
For example:
In the gender column, a person’s gender is stored in a coded format (F – Female, M – Male). The user, on the other hand, wants to use a list containing the Female or Male options. To solve the request, use comboBox with the options element containing the listed option elements. (In this case, you can use the radio input field, too, since the user has only two values to choose from.)

Attributes:

Attribute Description
value The ID or value. Required!
label The name or label of the ID or value, appearing in a drop-down list (comboBox) or a radio label. Required!

Example #1:

<options name="genders">
	<option value="F" label="Female" />
	<option value="M" label="Male" />
</options>

tab

Description:

Panel of the input fields. In case of split layout it can be found on the right side. In other cases it can be found on the pop-up window. It contains one or more control elements, and it can contain zero or one header and zero or one footer element.
Every tab has a box container. You can access a box container with its variable. (this.vb_{index}, where index is the position of a tab in the tabnavigator, from 0 to N-1, e.g. this.vb_0)

Attributes:

Attribute Description
label The label of tab. This is what appears on the tab at the top of the panel. Required!
maxLabelWidth The maximum width of the form item labels on tab, in pixels.
Default value: 150
columnCount Determines how many columns the input fields are displayed in (a value greater than 1 results in a multiple-column layout).
Default value: 1
labelPlacement Determines whether the labels are displayed on the left side of the input fields or above them.
Possible values: left, top
Default value: left
buttonsEnabled If this tab is selected by the user, this tab will, depending on the true or false value of buttonsEnabled, enable (true) or disable (false) pushbuttons.
An example: The tab has an iframe control. If the iframe contains a child application with oneToMany or manyToMany layout, you should set the buttonsEnabled attribute of the tab to false. When the user selects this tab, the push buttons of the application (the parent application to whom this tab belongs to) will be disabled when the child application appears in the iframe. This way you can avoid confusing the user whether a push button belongs to the parent application or the child application in the iframe. Setting the fullTab attribute of the iframe control to true is also recommended. (See fullTab of control.)
Possible values: true, false
Default value: true
iframesRefreshed If this tab is selected by the user, the contents of the iframes on the tab will be updated (refreshed), depending on the true or false value of iframesRefreshed.
Possible values: true, false
Default value: false

Example #1:

<tab label="Data">
	<control name="..." />
	...
</tab>

header

Description:

Every tab can have a header and a footer. It's optional. A header is an HTML (formatted) text. You can use it for a nice heading or a warning (or something completely different).
If a tab has a header, you can access it with the box container variable of the tab. E.g. this.vb_0.get_header() You can modify its content with this.vb_{index}.get_header().set_text("...");
If you don't set a header, the box container won't have a get_header method.
The header is a Text component (org.haxentric.control.Text /haxe/ or org_haxentric_control_Text /JS/).

Attributes:

Attribute Description
width Width of the header, in pixels. (Default value: 300)
height Height of the header, in pixels. (Default value: 50)

Example #1:

<tab label="Data">
  <header width="500" height="30"><![CDATA[<font style="font-weight: bold;">Delivery Address</font>]]></header>
  ...
  <control name="..." />
  ...
</tab>
This tab has a "Delivery Address" header. This is a bold text.

footer

Description:

Every tab can have a header and a footer. It's optional. A footer is an HTML (formatted) text. You can use it for a nice footer or a warning or a comment (or something completely different).
If a tab has a footer, you can access it with the box container variable of the tab. E.g. this.vb_0.get_footer() You can modify its content with this.vb_{index}.get_footer().set_text("...");
If you don't set a footer, the box container won't have a get_footer method.
The footer is a Text component (org.haxentric.control.Text /haxe/ or org_haxentric_control_Text /JS/).

Attributes:

Attribute Description
width Width of the footer, in pixels. (Default value: 300)
height Height of the footer, in pixels. (Default value: 50)

Example #1:

<tab label="Data">
  ...
  <control name="..." />
  ...
  <footer width="500" height="30"><![CDATA[<font style="font-weight: bold; color: red;">WARNING! The delivery address is not the same as the Billing address!</font>]]></footer>
  ...
</tab>
This tab has a "WARNING! ..." footer. This is a bold and red text.

control

Description:

Descriptor element of an input field. It may contain a validator element, but it’s optional.

Attributes:

Attribute Description
name Contains the name of the column from the database whose value you want to display. The column must be a column element of the table element.
Required (except: image, urlButton, iframe)!
label Label of the input field. It is displayed before or above the input field.
Please note:
Default value is the table‘s column label.
type Type of the input field.
Possible values: label, textInput, textArea, checkBox, comboBox, radio, dateField, timeField, dateTimeField, image, urlButton, iframe, richTextEditor and files.
Default value: textInput
richTextEditor Vendor or implementation of the rich text editor.
Possible values: trumbowyg and tinymce.
Default value: trumbowyg
For more information:
Trumbowyg: https://alex-d.github.io/Trumbowyg/ (Recommended! Really free!)
TinyMCE: https://www.tiny.cloud (Free for 1000 downloads/month!)
fileFolder The folder where the files are saved by the files control.
If your folder is /opt/mysever/protected and the name of your table is users and the files control has no name (the name attribute is empty) and the value of the key column is 178 (the user ID), the files will be saved in this folder: /opt/mysever/protected/users/178
If your folder is /opt/mysever/protected and the name of your table is users and the name of the files control is pictures (the value of name attribute is pictures) and the value of the key column is 178 (the user ID), the files will be saved in this folder: /opt/mysever/protected/users/178/pictures
editable Indicates whether the input field can be edited. When a developer associates the key column to an input field, the input field becomes uneditable (equivalent with editable="false").
Possible values: true, false
Default value: true
password Indicates whether the input field is a password. Only used with textInput.
Possible values: true, false
Default value: false
visible Indicates whether the input field is visible.
Possible values: true, false
Default value: true
width Width of the input field, in pixels. Default width of the input field used, if not specified.
height Height of the input field, in pixels. Default height of the input field used, if not specified.
mapping See mapping attribute of table element’s column element.
Please note:
Default value is the table‘s column mapping.
options See options attribute of table element’s column element.
Please note:
Default value is the table‘s column options.
rowCount Number of rows in the comboBox drop-down list.
Default value: 5
url If the input field type is image, it contains the url of the image displayed. Currently, the image displayed cannot be edited.
If the input field type is urlButton, clicking the button causes the user to go to the url, or the contents of the url open in a new window.
The url can be dynamic. In this case, a template is chosen by the developer. For more information about templates see popupWindowTitle attribute of definition element.
When an other record is selected in the dataGrid, the value of the url is reevaluated. This happens every time you change records, and at every record events (save, cancel, etc.).
For example:
https://www.makelovenotcode.com/pics/person_{per_id}.jpg
If the user selects the person with per_id 17, the url will be:
https://www.makelovenotcode.com/pics/person_17.jpg
target If the input field type is urlButton, clicking the button causes the user to go to the url, or the contents of the url open in a new window, depending on the value of target_self, _blank, etc. Works the same as HTML links.
Possible values: _self, _blank, _top, other window’s name.
Default value: _blank
buttonLabel If the input field type is urlButton, the developer can specify the displayed pushbutton’s label in this attribute.
comment Comment text to be displayed under the control.
commentWidth Width of the comment control.
commentHeight Height of the comment control.
help Help. A small "i" appears in a cirle next to the input field. If a user hovers over it, the text entered here will be displayed.
(Currently not supported, development in progress.)
labelPlacement Determines whether the label is displayed on the left side of input field or above it.
Possible values: left, top
Default value: left
columnSpan Determines how many columns does the input field span over (when using multiple-column layout).
Default value: 1
rowSpan Determines how many rows does the input field span over (when using multiple-column layout).
Default value: 1
fullTab If true, the control occupies the whole tab, without a label. If false, it will be displayed according to the width and height values, with a label.
An example: when a child application with oneToMany or manyToMany layout is displayed in an iframe, the fullTab attribute of the iframe should be set to true. This way the child application will occupy the whole tab.
Possible values: true, false
Default value: false

Example #1:

<tab ... >
  <control name="lastname" label="Last name" type="textInput" width="200">
	  <validator ... />
  </control>
  <control name="firstname" label="First name" type="textInput" />
  <control name="activeMember" type="checkBox" label="Active member" mapping="T,F" />
  <control name="gender" type="radio" label="Gender" options="genders" />
  <control name="comment" type="textArea" label="Comment" width="200" height="100"/>
</tab ... >
<tab ... >
  <control name="" type="files" fileFolder="/opt/mysever/protected" fullTab="true" />
</tab ... >
<tab ... >
  <control name="pictures" type="files" fileFolder="/opt/mysever/protected" fullTab="true" />
</tab ... >

validator

Description:

Descriptor element of a validation (verification). You can add verification to an input field, that will verify the value entered by the user. A control can have a maximum of one validator element!

Attributes:

Attribute Description
type Type of verification. Required!
Possible values:
email: Checks whether the entered text is an e-mail address.
string: Checks whether the length of the text entered is within the limits (minLength, maxLength).
number: Checks whether the text entered is a number, whether its value falls within the developer-defined range (minValue, maxValue), and whether the user added the required number of decimals after the decimal separator (precision).
date: Checks whether the text entered is a date, and whether its value falls within the developer-defined range (minValue, maxValue).
time: Checks whether the text entered is a time, and whether its value falls within the developer-defined range (minValue, maxValue).
dateTime: Checks whether the text entered is a date+time value, whether its value falls within the developer-defined range (minValue, maxValue).
minimal: This type of validator is only useful for comboBoxes. If the column associated with a comboBox control cannot be null, you can check with this validator whether the user selected a value or not. Set the required attribute of the validator element to true.
custom: A custom validator based on one of the previous mentioned validator types (baseType). You can write your own validation code for a control. Put your code in the text node of the validator element. The code is the body of a validator method. The method has a value parameter. If the value is invalid, your code must return a string, an error message. If the value is valid, your code must return null. (See Example #1.)
baseType Base type of verification. It is empty if you use a non-custom validator (type attribute with a value other than custom) otherwise use one of the following values:
Possible values:
email, string, number, date, time, dateTime or minimal
minLength The minimal length of the text for verifying a string, in characters.
maxLength The maximum length of the text for verifying a string, in characters.
minValue Contains the lowest acceptable number for verifying a number.
Contains the lowest acceptable date for verifying a date (format: YYYY-MM-DD).
Contains the lowest acceptable time for verifying a time (format: JJ-NN-SS, where JJ stands for hour, NN stands for minute, SS stands for second).
Contains the lowest acceptable date+time for verifying a dateTime (format: YYYY-MM-DD JJ-NN-SS).
maxValue Contains the highest acceptable number for verifying a number.
Contains the highest acceptable date for verifying a date (format: YYYY-MM-DD).
Contains the highest acceptable time for verifying a time (format: JJ-NN-SS).
Contains the highest acceptable date+time for verifying a dateTime (format: YYYY-MM-DD JJ-NN-SS).
precision Contains the highest acceptable number of decimals for verifying a number. (If only integers are accepted, its value is 0.)
required Indicated whether entering (or selecting) the value is required.
Possible values: true or false
Default value: false

Example #1:

<control ...>
  <validator type="string" minLength="2" maxLength="200" />
</control>
<control ...>
  <validator type="email" />
</control>
<control ...>
  <validator type="number" precision="0" minValue="0" maxValue="100" />
</control>
<control ...>
  <validator type="number" minValue="0" maxValue="100.00" precision="2" />
</control>
<control ...>
  <validator type="custom" baseType="string" minValue="0" maxValue="100.00" precision="2">
    <![CDATA[
      var r = null;
      // In this example, the first character must be a letter.
      // Its baseType is string. Its type is custom.
      // The upper case version of a non-letter character is 
      // the same as the lower case version.
      if(value!=null && value.length>0 && 
          value.charAt(0).toLowerCase()==value.charAt(0).toUpperCase())
      {
        r = "The first character must be a letter.";
      }
      return r;
    ]]>
  </validator>
</control>

dataGrid

Description:

Descriptor element of a dataGrid displayed on the left side (in case of split layout) or full window (in case of popup and oneToMany layout). (A definition can only contain one dataGrid element!) Users can reorder the columns of the dataGrid, and filter the records using the filter fields in the header of each column.
It may contain one or more column elements (NOT TO BE CONFUSED WITH THE table ELEMENT’S column ELEMENT!)

Attributes:

Attribute Description
headerHeight Height of the header row, in pixels.
rowHeight Height of the rows, in pixels.
filterRowHeight Height of the filter row, in pixels.
filterRowVisible Indicates whether the filter row is visible.
Possible values: true or false
Default value: true

Example #1:

<dataGrid>
	<column ... />
	...
	<column ... />
</dataGrid>

column element of the dataGrid element

Description:

Descriptor element of the column displayed in a dataGrid.

Attributes:

Attribute Description
name Contains the name of the column from the database whose value you want to display. The column must be provided as a column element of the table element. Required!
label Label of the column.
Please note:
Default value is the table‘s column label.
width Width of the column, in pixels.
minWidth Minimum width of the column, in pixels. If width is empty string or not provided, minWidth will be applied automatically, since it has a default value.
The importance of minWidth: if the columns of the dataGrid do not fill the available area, the free space is evenly distributed among the columns with minWidth.
Default value: 100
renderer The control required to display values.
Possible values: label, checkBox, checkMark
Default value: label
mapping See mapping attribute of table element’s column element.
Please note:
Default value is the table‘s column mapping.
options Allows developers to use a previously defined value list. The value of an options element’s name value must be entered here. If the column contains keys and codes only and the options attribute is not provided or is an empty string, no meaningful (for the user) data can be displayed (only ids or codes).
For example:
The city_id column only contains city IDs. We want to display the name of the cities, so we provide the name of an options element here, or its value is inherited from table element's column element.
See options attribute of table element’s column element.
Please note:
Default value is the table‘s column options.
sortIndex If the developer wants to sort the records of the dataGrid upfront, the sortIndex attribute can direct the application to sort the records by certain columns. If sortIndex >= 1, the column takes part in the sorting. sortIndex also determines in which order should the values of the columns be compared when sorting the records.
descendingSort If the developer wants to sort the records of the dataGrid upfront, and the column takes part in the sorting (sortIndex >=1), the descendingSort attribute can specify whether the records are sorted in a descending (true) or ascending (false) order by the column.
Possible values: true, false
Default value: false

Example #1:

<dataGrid>
	<column name="lastname" label="Last name" 
		width="150" />
	<column name="firstname" label="First name" 
		width="150" />
	<column name="city_id" label="City" 
		options="cities" width="150" />
	<column name="gender" label="Gender" 
		options="genders" width="50" />
	<column name="activeMember" label="Active member" 
		renderer="checkBox" mapping="T,F" width="100" />
</dataGrid>

checkList

Description:

Descriptor element of a checkList. Checklist is displayed in full window and you can only use it with manyToMany layout. (A definition can only contain one checkList element!) Users can filter the records using the filter fields in the header.

Attributes:

Attribute Description
header The header text of the control.
options A name of an options element. The records of the options will be the records of the checklist.
headerHeight Height of the header row, in pixels.
rowHeight Height of the rows, in pixels.
filterRowHeight Height of the filter row, in pixels.
filterRowVisible Indicates whether the filter row is visible.
Possible values: true or false
Default value: true

Example #1:

<checkList header="usergroups" 
           options="usergroups"
           headerHeight="26"
           rowHeight="26"
           filterRowHeight="26"
           filterRowVisible="true" />

button

Description:

You can create custom actions, which can be triggered by a button press, with the button element.
The button can be placed on the master or on the detail part of an application.
In case of split layout the master part is on the left side, and the button will be placed under the dataGrid or main component, the detail part is on the right side, and the button will be placed under the form.
In case of popup and oneToMany layout the master part is on the main window, and the button will be placed under the dataGrid or main component on the main window, the detail part is on the pop-up window, and the button will be placed under the form on the pop-up window.
If your custom action modifies/depends on/relates to a single record, put the button on the detail part of the application.

Attributes:

Attribute Description
name The unique name of the button. Required! The created button can be accessed with its variable. (this.<buttonName>, e.g. this.publish if the button name was "publish")
label Label of the button. Required!
placement Placement of the button.
Possible values: master, detail
Default value: detail
width Width of the button in pixel.
Default value: 70

Example #1:

...
      <button name="publish" label="Publish" placement="detail" width="70">
        <![CDATA[
        var xhr = new XMLHttpRequest();
        xhr.open('GET', '/publish.php?_id=' + this.get_m13e_selectedRecord()._id, true);
        var f = function(event) {
          if (xhr.readyState == 4)
          {
            if(xhr.status == 200 && xhr.responseText == "OK")
            {
              alert("Your article is published!");
            }
            else
            {
              alert("Error during publishing!");
            }
          }
        }
        xhr.addEventListener("readystatechange", f);
        xhr.send(null);
      ]]>
      </button>
...
This example application maintains articles. The developer created a Publish button to publish the article on the website. The publishing is implemented with the publish.php script. When the user presses the Publish button, the application executes an HTTP request (publish.php). If the response is "OK", the application alerts the user that the article is published, otherwise an error message is displayed.

Extra features

Selecting a record and a tab on load

If you set the selectedrecord parameter in the url of the application the application selects the record and scrolls to that record. If you set the selectedtab parameter, too, the application selects that tab, too. You can use a tabindex (0...N-1) or the name of the tab.

Example #1:

https://localhost/orders.php?selectedrecord=339
https://localhost/orders.php?selectedrecord=339&selectedtab=1
https://localhost/orders.php?selectedrecord=339&selectedtab=Order%20items

I'm a hardcore developer! Show me more!

The JavaScript part of the generated code uses the Haxentric library.
More information at:
https://haxentric.org/portfolio.php

Licenses

Make Love, Not Code! License
Haxentric License
Haxe License