Share My Creation Pen&Paper: PWCT for Basic ABMaterial WebApps

Pen&Paper Explained.png

The intension of Pen & Paper is the creation of ABMaterial WebApps as depicted in the drawing above. This was developed as a pet project out of a personal need to create ABMaterial WebApps. So far everything has gone well with the outputs.

1. The ABMaterial Library comes out with an XML file that has vast information about the components (depicted as classed) including their properties (attributes), events and methods. Any Library viewer is able to access these too.
2. These classes are represented as property bags in Pen & Paper so that I can create any component by just changing the various attributes, whether true/false, specifying text etc. The way the components are built, initialized and added to pages/containers/modal sheets has been explained in detail in the ABMaterial Demo, where all of this started.
3&4. On creating an ABM project with Pen & Paper, two databases are created, one to store the project definition (pages and component structures i.e. propertybags) and the other a production one that the data will be stored in. These are both in SQLite. Pen & Paper has functionality to perform a DAO (Data Access Object) link for each backend table and fields you want to link a component to. This is essence creates a CRUD code base. This was inspired by the ABMCRUD generator that produces a structure of ones ABMTable and ABMModal sheet with the specific input components.
5. On Project Build, Pen & Paper produces a complete B4J application including the source code that can be compiled to generate a working version of an ABM Web Application.
6. Pen & Paper does not come bundled with ABMaterial, is not affiliated with ABMaterial and to compile any Pen & Paper project to a fully fledged working ABM Webapp, you need the ABM Libraries. It is just a helper tool to elimitate the repetitive nature of creating projects, pages, containers, modalsheets, etc, in a programming without coding technology fashion. It does NOT in anyway replace ABM or intends to replicate its functionality as it just generates B4J code for your ABM application, this being achieved by use of property bags to create your components and generate the respective source code based on your options, eliminating the need to type code and what anyone gets out is the basic stuff to make ones project work. Not everything ABM is here anyway.

As everything that has a beginning has an end. This personal enjoyment project will stop being maintained as other things will evolve. As on 31 March 2018, there is no intention to advance this any further than what it is. Thanks for B4J this project was possible.

Steps in using Pen & Paper
  • Get everything related to Pen&Paper from this DropBox Link. Get executable from jar folder.
  • See videos below on usage and related articles
  • Please note that not all ABM components are covered with Pen&Paper as yet.

2018 Tutorials

Creating a Sign In Modal Dialog with Options

Interesting Tutorials

Creating a simple 'Contacts' ABMaterial WebApp - Part 1
Creating a simple 'Contacts' ABMaterial WebApp - Part 2
Creating a simple 'Contacts' ABMaterial WebApp - Part 3

Below are some of the articles touching on code generated by Pen&Paper.

ABMaterial WebApps created with Pen&Paper


CodeProject Article

Creating the Bible.Show WebApp with ABMaterial

Some YouTube Links

Pen&Paper is built using B4J and distributed with jMashProjectProfile.

NB: You will need the ABMaterial Framework to compile the generated source code.


  • abmaterial.gif
    53.1 KB · Views: 13,120
  • MyMaterialLibraries.png
    16.4 KB · Views: 844
Last edited:


Licensed User
Latest [Beta] Developments....

1. Buttons for Components: Save, Delete,Refresh Code, Copy Code moved to the buttom right status bar. The last pdf button is to open the PDF ABMaterial Pocket Reference posted earlier.


2. Almost all code generators are done (these are not linked to any datasources) and those using labels and textboxes for the initial version revamped. Page & NavBar to be visited again.

3. Functionality to compare previous and current ABMaterial Library XML files and draw dashboards. This was discussed above.

4. Methods - added methods for each component, one can select each method and select 'active', this will add that method call on the rendering of the controls source code. One can also add some code 2 execute.


5. Events - added events for each component, one can select each event and select 'active', this will add the event call for that component's rendering. One can also add some code 2 execute on the event.

6. Create tab now shows code to create the component, methods and events that will run using an Accordion.

7. A makeshift class builder for custom html components - work in progress..



8. Updated Themes definitions for Pen & Paper alignment with ABMaterial

9. Pen & Paper title bar shows ABMaterial compilation library compatible, currently 3.75.


10. Removed reduntant code and merged most repetive code with extremely minor changes - followed the Advay project approach of storing component details, e.g. simple methods to rule them all.


11. Added ABMVideo for video components and removed others and also removed the Timeline control
Last edited:


Licensed User
Latest Developments...

The structure of the designers has been enhanced. The first screen [1] will be the default properties, the second [2] will be the 'Theme' design applicable to that component. I had thought without having to necessary move around Pen & Paper, the theme should be moved to the component so that I know what I'm dealing with in each component.

If the component has rows/cells e.g. page, container and modal sheet, then the row/cell & component definition is also available. This includes a 'Field Selector' should I want to create a CRUD related container, modal sheet / page. I had thought well, I know how the grid works so I know how my designs should be like. So in my ABMComponents tab, let me define all the controls I need placed on the container, including their RC locations, the padding and margins and then let Pen & Paper figure out the grid. In the images attached, the container will have 5 rows defined by 01..05, this was picked up from the row locations when each of the components was added to the container, this also works the same with the Cells. By default, all cells are added using OSMP, but you can change that after all the components have been created. You can chop and change your padding, offset, sizes and margins as you please with that.

01ABMContainer.png 02ABMContainerTheme.png 03ABMContainerABMRows.png 04ABMContainterABMCells.png 05ABMContainerEvents.png 05ABMContainerMethods.png 06ABMContainerFieldSelector.png 07ABMContainerABMComponents.png 08ABMContainerCreate.png 09ABMContainerDefaultEvents.png


  • 02ABMContainerTheme.png
    15.2 KB · Views: 194


Licensed User
A Text Builder

I don't see myself remembering how to apply formatting every time i have to apply it to a text for any of the controls. So added is a Text Builder and later a Style builder will be added. This will make it easier for me going forward and still being tested..

So I add each 'element' of the text I want to build applying the respective format to each part. Here the content is two words, one without formatting and the other with including a link... The Preview sections gives the output...



Licensed User
Inside Pen & Paper (let's take a look behind the scenes)

Each ABMComponent is made up of properties, methods, events and perhaps some fields i.e. constants, you find most of these in the ABM.<field>.

Using the XML analysis done, a property bag is created with these properties for each of the components. As an example, selecting the ABMChip from Designers > Components in the tree, the ABMChip_Action event is fired.

Sub ABMChip_Action
    ' get the page name
    Dim pgName As String
    pgName = jMash.GetSimple("page")
    ' a page should be selected first before you can add a control
    If jMash.Len(pgName) = 0 Then
        jMash.msgboxError(MainForm,"Page Error", "The page to add the component has not been selected. Please select a page first.")
    End If
    oldName = ""
    PageName = pgName
    Dim nc As String
    nc = modABMaterial.NextCount(jMash.jSQL,PageName, "id")
    nc = nc + 1
    ComponentID = "chp" & nc
    etvComponent.SetProperty("PageName", PageName)
    etvComponent.SetProperty("ComponentID", ComponentID)
    etvComponent.SetProperty("tabindex", nc)
End Sub

The ABMChip_Initialize methods draws up the property bag using my own custom made property bag. After that method is called, the next component counter for the page is incremented and the pagename, componentid and tabindex updated in the propertybag. The tabindex just stores the order of the components.

Sub ABMChip_Initialize
    ' clear the views
    'load an empty property bag
    splitPage.LoadLayout("vComponent", "ABMChip")
    'determine if this component has a theme, if so add the theme property bag
    ThemeType = ThemeNameFromComponent("ABMChip")
    If ABMComponentHasTheme("ABMChip") = True Then
        splitPage.LoadLayout("vTheme", ThemeType)
    End If
    'add the methods property bag
    splitPage.LoadLayout("vComponentMethods", "Methods")
    'add the events property bag
    splitPage.LoadLayout("vComponentEvents", "Events")
    'add the accordion for 'Create', events and methods 
    'add the additional events a user can type source code for
    splitPage.LoadLayout("vDefaultSC", "Default Events")
    'create the property bag for the methods
    'store the create tab position in case user refreshes the code
    splitLoc= jMash.TabPageFindPos(splitPage,"Create")
    'create the default property bag
    Dim xl As List
    etvComponent.readonly = jMash.CreateList(",","PageName,ComponentType")
    etvComponent.ImagesFolder = ImagesFolder
    etvComponent.AddTextBoxProperty("Page Name", "", "Page Name", "PageName")
    etvComponent.AddTextBoxProperty("Component Type", "ABMChip", "Component Type", "ComponentType")
    xl = modABMaterial.GetComponentsForPage(PageName,True)
    etvComponent.AddComboBoxProperty("Parent ID", "", "Parent ID", "ActionButton", xl)
    etvComponent.AddComboBoxProperty("Placement", "", "Placement", "Placement", modABMaterial.abmplacement)
    etvComponent.AddTextBoxProperty("Component ID", "", "Component ID", "ComponentID")
    etvComponent.AddTextBoxProperty("Array Name", "", "Array Name", "ArrayName")
    etvComponent.AddTextBoxProperty("Chip ID", "", "Chip ID", "ID")
    etvComponent.AddTextBoxProperty("Text", "", "Text", "Text")
    etvComponent.AddImageFileChooserProperty("Image", "", "Image", "Image")
    etvComponent.AddCheckBoxProperty("Can Be Closed", "0", "Can Be Closed", "CanBeClosed")
    etvComponent.AddTextBoxProperty("Tag", "", "Tag", "Tag")
'    ThemeType = ThemeNameFromComponent("ABMChip")
    If ThemeType.length > 0 Then
        xl = modABMaterial.GetThemes(ThemeType,True,True)
        If xl.Size >= 2 Then
        etvComponent.AddComboBoxProperty("Theme Name", "", "ThemeName", "ThemeName", xl)
        End If
    End If
    etvComponent.AddComboBoxProperty("Cell Method", "Cell", "Cell Method", "CellMethod", modABMaterial.abmCellMethod)
    etvComponent.AddComboBoxProperty("Visibility", "ABM.VISIBILITY_ALL", "Visibility", "Visibility", modABMaterial.ABMVisibility)
    etvComponent.AddTextBoxProperty("Row ID / #OfRows", "1", "Row ID", "RowID")
    etvComponent.AddTextBoxProperty("Cell ID", "1", "Cell ID", "CellID")
    etvComponent.AddTextBoxProperty("Tab Index", "0", "Tab Index", "TabIndex")
    etvComponent.AddCheckBoxProperty("Active", "1", "Active", "Active")
    etvComponent.AddTextBoxProperty("# of Grid Columns", "4", "", "GridColumns")
    etvComponent.addcheckboxproperty("Table Source","0","","TableSource")
    etvComponent.AddComboBoxProperty("TableName", "", "TableName", "TableName", modABMaterial.GetTableNames)
    etvComponent.AddTextAreaProperty("Select Query", "", "Select Query", "SelectQuery")
    etvComponent.AddTextAreaProperty("Arguements (sep by ,)","Null","","Arguements")
    etvComponent.addcheckboxproperty("Arguements from LocalStorage","1","","ArguementsFromLS")
    etvComponent.AddComboBoxProperty("ID Field", "", "IDField", "IDField", xl)
    etvComponent.AddComboBoxProperty("Text Field", "", "Text Field", "TextField", xl)
    xl = modABMaterial.getallpages(True)
    etvComponent.AddComboBoxProperty("Navigate To", "", "", "NavigateTo", xl)
End Sub

1. We need the Page to know where to place the component
2. We need the parent id to know where to place the component inside the page (this could be a container / modal sheet)
3. We need the placement to know where to place the component inside the parent (this could be the header, footer etc)
4. The component id is the identifier (unique) for this component for the Initialize methods and also refering to it in the page.

So after the initialize method is executed, we see this on the screen.


Whilst inside Pen&Paper these properties are hard coded, what Advay did was to read each property per component from a database and generate the propertybag. This was due to the dynamic changes in the framework. As Pen&Paper comes a long way, re-writing the code is out of the question. (If it works, why brake it? However I have another plan in terms of maintaining this, though it will mean hard coding (not-enjoyable-at-times)).

So, after defining the properties for the component, the component is saved. A single method for all the controls with a few exceptions has been built, ABMComponent_Save

Sub ABMComponent_Save(sComponentType As String)
    Dim props As Map
    Dim propsJSON As String
    Dim title As String
    ' get the propertybag
    Needs = ""
    If etvPageNeeds.isinitialized Then Needs = etvPageNeeds.tostring
    props = etvComponent.GetPropertyBag
    PageName = etvComponent.GetProperty("PageName")
    ComponentID = etvComponent.GetProperty("ComponentID")
    TabIndex = etvComponent.GetProperty("TabIndex")
    Active = etvComponent.GetProperty("Active")
    ActionButton = etvComponent.GetProperty("ActionButton")
    RefreshOnLoad = etvComponent.GetProperty("RefreshOnLoad")
    title = etvComponent.GetProperty("title")
    Extras = ""
    Menus = ""
    If letvComponentItems.isinitialized Then Extras = letvComponentItems.tostring
    If letvComponentSubItems.isinitialized Then Menus = letvComponentSubItems.tostring
    Dim IsFieldName As String = etvComponent.GetProperty("IsFieldName")
    If IsFieldName = "1" Then
        props.Put("fieldname", ComponentID)
    End If
    Dim IsComputed As String = props.GetDefault("iscomputed","0")
    If IsComputed = "1" Then
    End If
    Dim required As String = props.getdefault("required","0")
    If required = "1" Then
    End If
    'Static = etvComponent.GetProperty("Static")
    propsJSON = jMash.Map2Json(props)
    ComponentKey = PageName & "." & ComponentID
    newName = ComponentKey
    dbAction.Put("pagename", PageName)
    dbAction.Put("componentid", ComponentID)
    dbAction.Put("tabindex", TabIndex)
    dbAction.Put("componentkey", ComponentKey)
    dbAction.Put("componentproperties", propsJSON)
    dbAction.Put("componenttype", sComponentType)
    dbAction.Put("active", Active)
    dbAction.Put("needs", Needs)
    'dbAction.Put("static", Static)
    dbAction.Put("ActionButton", ActionButton)
    dbAction.Put("refreshonload", RefreshOnLoad)
    dbAction.Put("extras", Extras)
    dbAction.Put("menus", Menus)
    dbAction.put("sourcecode", txtDefaultSC.GetText)
    If txtComputed.IsInitialized Then dbAction.Put("computed", txtComputed.gettext)
    Select Case sComponentType
    Case "ABMNavigationBar"
        DBUtils.RecordUpdateField(jMash.jSQL,"Pages","navbartitle", title, "PageName", PageName)
    End Select
End Sub

This gets the Map property bag and after reading some properties that are specific, saves the component to the database project opened. The treeview is updated with the new component and if code preview is turned on, the code for the component displayed. The generated source code is done by a method called ABMChip_Render in this particular case. This is the same method that will run for all chips defined per each of the pages to generate the code for the ABMChip.

public Sub ABMChip_Render(pgName As String, comp As Map, bPreview As Boolean, bIsVariables As Boolean) As String
    Dim componentID As String = comp.GetDefault("componentid","")
    If Main.Rendered.IndexOf(pgName & "." & componentID) = -1 Then
        Main.Rendered.Add(pgName & "." & componentID)
        'already rendered, ignore this time around
        Return ""
    End If
    Dim sb As StringBuilder
    Dim props As Map
    Dim pageName As String
    Dim propsJSON As String
    Dim componentID As String
    Dim ChipImage As String
    Dim ChipText As String
    Dim ChipCanBeClosed As String
    Dim ChipTheme As String
    Dim ChipCellID As String
    Dim ChipRowID As String
    Dim ChipID As String
    Dim ChipArrayName As String
    Dim ActionButton As String
    Dim Tag As String
    Dim Placement As String
    Dim CellMethod As String
    Dim Visibility As String
    Dim RefreshOnLoad As String
    Dim TableSource As String
    propsJSON = comp.Get("componentproperties")
    props = jMash.Json2Map(propsJSON)
    props = jMash.MapRemoveNulls(props)
    componentID = comp.Get("componentid")
    ChipText = props.Getdefault("text","")
    ChipCanBeClosed = props.Getdefault("canbeclosed","0")
    ChipTheme = props.Getdefault("themename","")
    ChipImage = props.Getdefault("image","")
    ChipCellID = props.Getdefault("cellid","1")
    ChipRowID = props.Getdefault("rowid","2")
    ChipID = props.Getdefault("id","")
    ChipArrayName = props.Getdefault("arrayname","")
    ActionButton = comp.Getdefault("actionbutton","")
    Placement = props.Getdefault("placement","")
    CellMethod = props.Getdefault("cellmethod","Cell")
    Visibility = props.Getdefault("visibility","ABM.VISIBILITY_ALL")
    RefreshOnLoad = props.getdefault("refreshonload","0")
    TableSource = props.getdefault("tablesource","0")
    Tag = props.GetDefault("tag","")
    If bPreview = False Then
        If (RefreshOnLoad = "1") And (TableSource = "1") Then Return ""
    End If
    ' define page to add to
    Select Case pgName
        Case "index"
            pageName = "AppPage"
        Case Else
            pageName = "page"
    End Select
    ' build render code
    sb.Append("Dim ").Append(componentID).Append(" As ABMChip").Append(CRLF)
    If bIsVariables = True Then
        sb.Append(ChipText).Append(" = ").Append(ChipText).Append(".Replace(")
        sb.Append(jMash.InQuotes(" ")).Append(", ").Append(jMash.InQuotes("{NBSP}"))
    End If
    sb.Append("(").Append(pageName).Append(", ")
    If ChipArrayName.length > 0 Then
        If bIsVariables = True Then
            sb.Append(ChipID).Append(", ")
            sb.Append(jMash.InQuotes(ChipID)).Append(", ")
        End If
        If bIsVariables = True Then
            sb.Append(componentID).Append(", ")
            sb.Append(jMash.InQuotes(componentID)).Append(", ")
        End If
    End If
    If bIsVariables = True Then
        sb.Append(ChipText).Append(", ")
        sb.Append(jMash.InQuotes(ChipText)).Append(", ")
    End If
    If ChipCanBeClosed = "1" Then
        sb.Append("True, ")
        sb.Append("False, ")
    End If
sb.Append(componentID).Append($".Tag = "${componentID}""$).append(CRLF)
    If jMash.Len(ChipImage) > 0 Then
        sb.Append(componentID).Append(".Image = ").Append(jMash.InQuotes(ChipImage)).Append(CRLF)
    End If
If jMash.Len(Visibility) > 0 And Visibility <> "ABM.VISIBILITY_ALL" Then
        sb.Append(componentID).Append(".Visibility = ").Append(jMash.InQuotes(Visibility)).Append(CRLF)
    End If
    If jMash.Len(Tag) > 0 Then
        sb.Append(componentID).Append(".Tag = ")
        If bIsVariables = True Then
        End If
    End If
    If jMash.Len(ActionButton) > 0 Then
    End If
    If jMash.Len(ChipArrayName) > 0 Then
        sb.Append("AddArrayComponent(").Append(componentID).Append(", ")
    End If
    Return sb.tostring
End Sub

So for each of the controls that Pen&Paper can now generate in helping build ABMaterial WebApps, that's the maintainance behind the scenes..


Licensed User
Did you know?

Once you have created a page, a component, a theme using Pen&Paper, you can export these as JSON format and another Pen&Paper user can Import them into their project? This means that more than one person can work on the same project and develop different sections of it and then consolidate later.

Each of the items to export should be selected first.

1. For themes - select Themes > Export Theme, to import a JSON theme file, select Import
2. For pages - selected Pages > Export Page, this will export both the page and components into two JSON files, to import select Import page
3. For components - select Components > Export Component, this will export the component, to import select Import Component

You can use a JSON viewer for this self-containing ABMContainer definition. Importing this and clicking 'Create Controls' will create the grid ABMRow(s) for the container and all other components inside the container.


PS: There is a Convert.NET app on this page that also does json viewing and other things...


  • contLogin.txt
    21.5 KB · Views: 213


Licensed User
Hi y'all

This update addresses everything discussed in this thread between posts #196 - #205.

NB: All projects opened with this version should be Upgraded i.e. File > Upgrade (after you open the project)

For consistency...
  • ABMGridRows has been renamed correctly to ABMRow.
  • NavPills has been renamed to be CTNavPills and
  • JustGage has been renamed to MashJustGage (this is different to the custom JustGage posted here as I added more things to the version posted here)
Doing a project upgrade will also run the renaming of the controls, thus its crucial you upgrade.

Update: Dropbox it here.

PS: This is ABMaterial 3.75 specific, you are welcome to report any breakages, I've tried to test as much as possible.

Now to the next important part, Debugging Pen&Paper and adding Reporting, let me go and learn that first.


13-11-2017 Fixed a bug with page creation, download link above updated.
Last edited:


Licensed User
HI Mashiane,
Just try create new project on the new fresh computer with installed 3.75 ABMaterial
P&P crashed
PenNpaper>java -jar pennpaper.jar
Class not found: b4j.Mashy.ETV.editabletv, trying: b4j.Mashy.PenNPaper.editabletv
Class not found: b4j.Mashy.ETV.editabletv, trying: b4j.Mashy.PenNPaper.editabletv
Class not found: b4j.Mashy.ETV.editabletv, trying: b4j.Mashy.PenNPaper.editabletv
Class not found: b4j.ABMaterialShow.editabletv, trying: b4j.Mashy.PenNPaper.editabletv
Class not found: b4j.Mashy.ETV.editabletv, trying: b4j.Mashy.PenNPaper.editabletv
Class not found: b4j.ABMaterialShow.listviewetv, trying: b4j.Mashy.PenNPaper.listviewetv
Class not found: b4j.Mashy.ETV.editabletv, trying: b4j.Mashy.PenNPaper.editabletv
Class not found: b4j.ABMaterialShow.listviewetv, trying: b4j.Mashy.PenNPaper.listviewetv
Class not found: b4j.Mashy.ETV.editabletv, trying: b4j.Mashy.PenNPaper.editabletv
Class not found: b4j.ABMaterialShow.codearea, trying: b4j.Mashy.PenNPaper.codearea
main._project_read (java line: 44904)
        at b4j.Mashy.PenNPaper.main._project_read(
        at b4j.Mashy.PenNPaper.main._project_open(
        at b4j.Mashy.PenNPaper.main._getfile(
        at b4j.Mashy.PenNPaper.main._mnufilenew_action(
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at anywheresoftware.b4a.BA.raiseEvent2(
        at anywheresoftware.b4a.BA$
        at com.sun.javafx.application.PlatformImpl.lambda$null$172(
        at Method)
        at com.sun.javafx.application.PlatformImpl.lambda$runLater$173(
        at Method)
        at Source)


Licensed User
HI Mashiane,
Just try create new project on the new fresh computer with installed 3.75 ABMaterial
P&P crashed
The only reason I think such would happen is if you did not upgrade your project. Please note that as per post #206, the NB part says that all projects opened with this version should be upgraded. Please try and upgrade your project after you open it, then compile it. If the error happens again, pm me please. Ta!


Licensed User
Hi y'all

I kindly need some volunteers who will help me take this B4J app forward.

1. In most cases new releases of this need to be tested, I need someone(s) who can help me in doing that, I miss some things I have seen.
2. The priority is just running tests and ensuring that stuff works before a release of Pen&Paper
3. This will mean creating basic apps with Pen & Paper and seeing their functionality working, in most cases, just skeletons.
4. If you are willing and will play ball, please pm me and let's talk.

Kind Regards



Licensed User
Hi y'all

Pen & Paper 4 is now available, this version supports ABMaterial 4.00. The filename is PenNPaper4.jar. You can Dropbox it here.
This version also uses MashPlugIns Library.

For now, the additional designers are:

  • CTNavPills
  • MashBreadCrumbs
  • MashCameraPlain
  • MashClock
  • MashJustGage
  • MashStats


PS: The MashPlugIns blog is here. As it takes time to develop these PlugIns, there is a free version of MashPlugs and donator specific library which has additional components for your minimum $1 donation.

Your support is greatly appreciated.
Last edited:


Licensed User
Pen & Paper 4.03

your free version here. You will also need the MashPlugIns library going forward.

The strides made with B4J and ABMaterial have been immense and I also found out some few bugs with Pen & Paper that I needed to iron out.

As usual, this helps with creating basic ABMaterial WebApps, you will have to do the rest of the customization yourself.

What you can do with ABMaterial?

1. Create a b4j project automatically based on properties you specifiy.
2. Create ABMPages with components depending on what you want to do
3. Create simple CRUD functionality inclusive of the ABMTable.

Here are some startup to tutorials:
1. Create a simple 'Hello World' WebApp
2. Create a simple 'Contacts' form - Part 1

Pen & Paper Forum Search
MashPlugIns Dropbox
Last edited: