UpviseJS User Interface Guide

UpviseJS provides 4 essential classes to create a portable, efficient and optimized User Interface on mobile and web :

All These classes are implemented natively on each platform and comply with the UI guidelines of each platform giving you a native look & feel and great performance.

The List, Map & Chart are mutually exclusive in a given screen. You can use tabs, using Toolbar.addTab to implement different views for the same object, for example a tab containing a List and another one a Map.

Pages & Navigation

A page is usually contained in to one javascript function, with a set of calls to the Toolbar object and the List object.
It ends with a List.show() call, which computes, layout and displays the screen.

To pass parameters between pages, simply add them to your function call in the List.addItemXXX() method calls. Use the string interpolation feature of UpviseJS to easily write your callback function

function page1() {
    var myid = "5436";
    List.addItem("Goto Page2", "page2({myid})");
    List.show();
}

function page2(id) {
    List.addItem("ID: ", id);
    List.show();
}

List View Screen

A list view screen usually contains a list of similar items.

function welcome() {
    List.addItem("Customers");
    List.addItem("Support Tickets");
    List.addItem("Quotes");
    List.addItem("Product Catalog", "productlist()");
    List.show();
}

function productlist() {
    Toolbar.setStyle("search");
    for (var i = 0; i < 100; i ++) {
        List.addItemSubtitle("Product " + i, "in stock");
    }
    List.show();
}


View Screen

A view screen usually presents read-only information related to a record, for example a view lead screen would show the lead name, email, phone.

The Format class is useful to format the raw value from a database table, such as phone number or dates.
function viewLead(id) {
    .....
    Toolbar.setTitle("Lead Info");
    Toolbar.addButton("Edit Lead", "editLead({id})", "edit"); 
    List.addItemTitle("John Smith", "Vice President");
    List.addItemLabel("Mobile", "6878 8585", "App.call({this.value})");
    List.addItemLabel("Address", "1 Redmond Way, Seattle", "App.map({this.value})");
    List.addHeader("More");
    List.addItemLabel("Birthday", Format.date(13845566));
    List.show();
}


Edit Screen

an Edit screen is usually called from a View screen using a toolbar action button. Edit screens looks similar to View screen with the following differences:

To edit a text, date, time, number, use the List.addTextBox(id, label, value, onchange, type) method. To edit a value selected amongst a fixed set, use List.addComboBox() or List.addComboBoxMulti().
You can also use List.addCheckBox() to change a boolean value

.
function editLead(id) {
    var lead = Query.select("leads", id);
    Toolbar.setTitle("Edit Lead");
    Toolbar.setStyle("edit"); // this change the back button to Done in the toolbar

    var onchange = "Query.updateId('leads',{id},this.id,.this.value)";
    List.addTextBox("name", "Name", lead.name, onchange, "text");
    List.addTextBox("email", "Email", lead.email, onchange, "text");
    List.addTextBox("date", "Date", lead.date, onchange, "date");
    List.addCheckBox("important", "Important", lead.important, onchange);
    List.addCheckBox("source", "Source", lead.source, onchange, "0:Website|1:Direct Mailing|2:Other");
    List.show();
}
The onchange callback function is essential here. It enables to save each field individually instead of saving the entire form.
this.id is a keyword, whose value is contextual to the current editable field (the id parameter value of the List.addTexBox() call)
this.value is the new modified value


History management

UpviseJS manages automatically the history stack for you, like in a web browser and provides a Back button to go back to the previous page. There is also a Refresh menu item to reload the current page.

You can also control and change the way the framework add pages to the history using the History.redirect(funcall) method. This is useful when you do not want certain function call to be part of the history (when creating a record for example). Use the History.back() method to programmatically go back when you implement a delete record function.

function newLead() {
    var id = Query.insert("leads", {date:Date.now(), owner:User.getName()});
    // Replace the default newLead() history state by editLead
    History.redirect("editLead({id})");
}

function editLead(id) {
    // edit the Lead
}
In the last example, if you do not add the History.redirect call, but simply add a call to editLabel() directly, when you refresh the resulting edit page, it will call the newLead() function again :-, which is not the expected behaviour.

Working with Tabs

Use Toolbar.addTab(title, onclick) to add tabs to a screen.
To support both phone, tablet and web, with the same code,do not to use more than 3 tabs, because of screen width of smartphones.

function viewContacts(tab) {
    var contacts = Query.select("Contacts.contacts", "id;name;geo", "name");
    Toolbar.addTab("List", "viewContacts()");
    Toolbar.addTab("Map", "viewContacts('map')");
    if (tab == 'map') {
        for (var i = 0; i < contacts.length; i++) {
            var contacts = contacts[i];
            Map.addItem(contact, contact.geo, "viewContact({contact.id})");
        }
        Map.show();
    } else {
        for (var i = 0; i < contacts.length; i++) {
            var contacts = contacts[i];
            List.addItem(contact.name, "viewContact({contact.id})");
        }
        List.show();
    }
}

Working with Maps

...
Map.addItem("San Fransisco", "37.769099,-122.425584", "viewCity()");
Map.addItem("Paris", "48.859875, 2.347060", "viewCity()");
Map.addUsers(); // add the real-time position of all users on my account
Map.show();

Displaying Charts

UpviseJS supports drawing charts or type bar, pie and line with the Chart class

Here is a sample which displays the number of leads per city in a bar chart, with the city name in the horizontal axis.
...
Config.tables["leads"] = "id;name;city";
....
// 1. Gather all leads and put them in a hashmap object for each city
var data = new Hashmap();
var leads = Query.select("leads", "city", "city != ''");
for (var i = 0; i < leads.length; i++) {
    var lead = leads[i];
    data.increment(lead.city, 1);
}

// 2. Init the Chart and define the columns
Chart.init();
Chart.addColumn("string", "City");
Chart.addColumn("number", "Number of Leads");

// 3. Add the rows to the chart
for (var i = 0 ; i < data.keys.length; i++) {
    var city = data.keys[i];
    var count = data.get(city);
    Chart.addRow(city, count);
}
// 4. Display the Chart
Chart.show("bar");
Current limitation: only one chart can be displayed on one page and cannot be used with other call to List, Map or WebView class.
The Chart class is not available yet on iOs.

Support Tablet & Web screen layout